1 // Copyright 2014 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/compiler/simplified-lowering.h" 6 7 #include <limits> 8 9 #include "src/address-map.h" 10 #include "src/base/bits.h" 11 #include "src/code-factory.h" 12 #include "src/compiler/access-builder.h" 13 #include "src/compiler/common-operator.h" 14 #include "src/compiler/compiler-source-position-table.h" 15 #include "src/compiler/diamond.h" 16 #include "src/compiler/linkage.h" 17 #include "src/compiler/node-matchers.h" 18 #include "src/compiler/node-origin-table.h" 19 #include "src/compiler/node-properties.h" 20 #include "src/compiler/operation-typer.h" 21 #include "src/compiler/operator-properties.h" 22 #include "src/compiler/representation-change.h" 23 #include "src/compiler/simplified-operator.h" 24 #include "src/compiler/type-cache.h" 25 #include "src/conversions-inl.h" 26 #include "src/objects.h" 27 28 namespace v8 { 29 namespace internal { 30 namespace compiler { 31 32 // Macro for outputting trace information from representation inference. 33 #define TRACE(...) \ 34 do { \ 35 if (FLAG_trace_representation) PrintF(__VA_ARGS__); \ 36 } while (false) 37 38 // Representation selection and lowering of {Simplified} operators to machine 39 // operators are interwined. We use a fixpoint calculation to compute both the 40 // output representation and the best possible lowering for {Simplified} nodes. 41 // Representation change insertion ensures that all values are in the correct 42 // machine representation after this phase, as dictated by the machine 43 // operators themselves. 44 enum Phase { 45 // 1.) PROPAGATE: Traverse the graph from the end, pushing usage information 46 // backwards from uses to definitions, around cycles in phis, according 47 // to local rules for each operator. 48 // During this phase, the usage information for a node determines the best 49 // possible lowering for each operator so far, and that in turn determines 50 // the output representation. 51 // Therefore, to be correct, this phase must iterate to a fixpoint before 52 // the next phase can begin. 53 PROPAGATE, 54 55 // 2.) RETYPE: Propagate types from type feedback forwards. 56 RETYPE, 57 58 // 3.) LOWER: perform lowering for all {Simplified} nodes by replacing some 59 // operators for some nodes, expanding some nodes to multiple nodes, or 60 // removing some (redundant) nodes. 61 // During this phase, use the {RepresentationChanger} to insert 62 // representation changes between uses that demand a particular 63 // representation and nodes that produce a different representation. 64 LOWER 65 }; 66 67 namespace { 68 69 MachineRepresentation MachineRepresentationFromArrayType( 70 ExternalArrayType array_type) { 71 switch (array_type) { 72 case kExternalUint8Array: 73 case kExternalUint8ClampedArray: 74 case kExternalInt8Array: 75 return MachineRepresentation::kWord8; 76 case kExternalUint16Array: 77 case kExternalInt16Array: 78 return MachineRepresentation::kWord16; 79 case kExternalUint32Array: 80 case kExternalInt32Array: 81 return MachineRepresentation::kWord32; 82 case kExternalFloat32Array: 83 return MachineRepresentation::kFloat32; 84 case kExternalFloat64Array: 85 return MachineRepresentation::kFloat64; 86 case kExternalBigInt64Array: 87 case kExternalBigUint64Array: 88 UNIMPLEMENTED(); 89 } 90 UNREACHABLE(); 91 } 92 93 UseInfo CheckedUseInfoAsWord32FromHint( 94 NumberOperationHint hint, const VectorSlotPair& feedback = VectorSlotPair(), 95 IdentifyZeros identify_zeros = kDistinguishZeros) { 96 switch (hint) { 97 case NumberOperationHint::kSignedSmall: 98 case NumberOperationHint::kSignedSmallInputs: 99 return UseInfo::CheckedSignedSmallAsWord32(identify_zeros, feedback); 100 case NumberOperationHint::kSigned32: 101 return UseInfo::CheckedSigned32AsWord32(identify_zeros, feedback); 102 case NumberOperationHint::kNumber: 103 return UseInfo::CheckedNumberAsWord32(feedback); 104 case NumberOperationHint::kNumberOrOddball: 105 return UseInfo::CheckedNumberOrOddballAsWord32(feedback); 106 } 107 UNREACHABLE(); 108 } 109 110 UseInfo CheckedUseInfoAsFloat64FromHint(NumberOperationHint hint, 111 const VectorSlotPair& feedback) { 112 switch (hint) { 113 case NumberOperationHint::kSignedSmall: 114 case NumberOperationHint::kSignedSmallInputs: 115 case NumberOperationHint::kSigned32: 116 // Not used currently. 117 UNREACHABLE(); 118 break; 119 case NumberOperationHint::kNumber: 120 return UseInfo::CheckedNumberAsFloat64(feedback); 121 case NumberOperationHint::kNumberOrOddball: 122 return UseInfo::CheckedNumberOrOddballAsFloat64(feedback); 123 } 124 UNREACHABLE(); 125 } 126 127 UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) { 128 switch (rep) { 129 case MachineRepresentation::kTaggedSigned: 130 return UseInfo::TaggedSigned(); 131 case MachineRepresentation::kTaggedPointer: 132 case MachineRepresentation::kTagged: 133 return UseInfo::AnyTagged(); 134 case MachineRepresentation::kFloat64: 135 return UseInfo::TruncatingFloat64(); 136 case MachineRepresentation::kFloat32: 137 return UseInfo::Float32(); 138 case MachineRepresentation::kWord8: 139 case MachineRepresentation::kWord16: 140 case MachineRepresentation::kWord32: 141 return UseInfo::TruncatingWord32(); 142 case MachineRepresentation::kWord64: 143 return UseInfo::TruncatingWord64(); 144 case MachineRepresentation::kBit: 145 return UseInfo::Bool(); 146 case MachineRepresentation::kSimd128: 147 case MachineRepresentation::kNone: 148 break; 149 } 150 UNREACHABLE(); 151 } 152 153 UseInfo UseInfoForBasePointer(const FieldAccess& access) { 154 return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt(); 155 } 156 157 UseInfo UseInfoForBasePointer(const ElementAccess& access) { 158 return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt(); 159 } 160 161 void ReplaceEffectControlUses(Node* node, Node* effect, Node* control) { 162 for (Edge edge : node->use_edges()) { 163 if (NodeProperties::IsControlEdge(edge)) { 164 edge.UpdateTo(control); 165 } else if (NodeProperties::IsEffectEdge(edge)) { 166 edge.UpdateTo(effect); 167 } else { 168 DCHECK(NodeProperties::IsValueEdge(edge) || 169 NodeProperties::IsContextEdge(edge)); 170 } 171 } 172 } 173 174 void ChangeToPureOp(Node* node, const Operator* new_op) { 175 DCHECK(new_op->HasProperty(Operator::kPure)); 176 if (node->op()->EffectInputCount() > 0) { 177 DCHECK_LT(0, node->op()->ControlInputCount()); 178 // Disconnect the node from effect and control chains. 179 Node* control = NodeProperties::GetControlInput(node); 180 Node* effect = NodeProperties::GetEffectInput(node); 181 ReplaceEffectControlUses(node, effect, control); 182 node->TrimInputCount(new_op->ValueInputCount()); 183 } else { 184 DCHECK_EQ(0, node->op()->ControlInputCount()); 185 } 186 NodeProperties::ChangeOp(node, new_op); 187 } 188 189 #ifdef DEBUG 190 // Helpers for monotonicity checking. 191 class InputUseInfos { 192 public: 193 explicit InputUseInfos(Zone* zone) : input_use_infos_(zone) {} 194 195 void SetAndCheckInput(Node* node, int index, UseInfo use_info) { 196 if (input_use_infos_.empty()) { 197 input_use_infos_.resize(node->InputCount(), UseInfo::None()); 198 } 199 // Check that the new use informatin is a super-type of the old 200 // one. 201 DCHECK(IsUseLessGeneral(input_use_infos_[index], use_info)); 202 input_use_infos_[index] = use_info; 203 } 204 205 private: 206 ZoneVector<UseInfo> input_use_infos_; 207 208 static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) { 209 return use1.truncation().IsLessGeneralThan(use2.truncation()); 210 } 211 }; 212 213 #endif // DEBUG 214 215 bool CanOverflowSigned32(const Operator* op, Type left, Type right, 216 Zone* type_zone) { 217 // We assume the inputs are checked Signed32 (or known statically 218 // to be Signed32). Technically, the inputs could also be minus zero, but 219 // that cannot cause overflow. 220 left = Type::Intersect(left, Type::Signed32(), type_zone); 221 right = Type::Intersect(right, Type::Signed32(), type_zone); 222 if (left.IsNone() || right.IsNone()) return false; 223 switch (op->opcode()) { 224 case IrOpcode::kSpeculativeSafeIntegerAdd: 225 return (left.Max() + right.Max() > kMaxInt) || 226 (left.Min() + right.Min() < kMinInt); 227 228 case IrOpcode::kSpeculativeSafeIntegerSubtract: 229 return (left.Max() - right.Min() > kMaxInt) || 230 (left.Min() - right.Max() < kMinInt); 231 232 default: 233 UNREACHABLE(); 234 } 235 return true; 236 } 237 238 bool IsSomePositiveOrderedNumber(Type type) { 239 return type.Is(Type::OrderedNumber()) && !type.IsNone() && type.Min() > 0; 240 } 241 242 } // namespace 243 244 class RepresentationSelector { 245 public: 246 // Information for each node tracked during the fixpoint. 247 class NodeInfo final { 248 public: 249 // Adds new use to the node. Returns true if something has changed 250 // and the node has to be requeued. 251 bool AddUse(UseInfo info) { 252 Truncation old_truncation = truncation_; 253 truncation_ = Truncation::Generalize(truncation_, info.truncation()); 254 return truncation_ != old_truncation; 255 } 256 257 void set_queued() { state_ = kQueued; } 258 void set_visited() { state_ = kVisited; } 259 void set_pushed() { state_ = kPushed; } 260 void reset_state() { state_ = kUnvisited; } 261 bool visited() const { return state_ == kVisited; } 262 bool queued() const { return state_ == kQueued; } 263 bool unvisited() const { return state_ == kUnvisited; } 264 Truncation truncation() const { return truncation_; } 265 void set_output(MachineRepresentation output) { representation_ = output; } 266 267 MachineRepresentation representation() const { return representation_; } 268 269 // Helpers for feedback typing. 270 void set_feedback_type(Type type) { feedback_type_ = type; } 271 Type feedback_type() const { return feedback_type_; } 272 void set_weakened() { weakened_ = true; } 273 bool weakened() const { return weakened_; } 274 void set_restriction_type(Type type) { restriction_type_ = type; } 275 Type restriction_type() const { return restriction_type_; } 276 277 private: 278 enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued }; 279 State state_ = kUnvisited; 280 MachineRepresentation representation_ = 281 MachineRepresentation::kNone; // Output representation. 282 Truncation truncation_ = Truncation::None(); // Information about uses. 283 284 Type restriction_type_ = Type::Any(); 285 Type feedback_type_; 286 bool weakened_ = false; 287 }; 288 289 RepresentationSelector(JSGraph* jsgraph, JSHeapBroker* js_heap_broker, 290 Zone* zone, RepresentationChanger* changer, 291 SourcePositionTable* source_positions, 292 NodeOriginTable* node_origins) 293 : jsgraph_(jsgraph), 294 zone_(zone), 295 count_(jsgraph->graph()->NodeCount()), 296 info_(count_, zone), 297 #ifdef DEBUG 298 node_input_use_infos_(count_, InputUseInfos(zone), zone), 299 #endif 300 nodes_(zone), 301 replacements_(zone), 302 phase_(PROPAGATE), 303 changer_(changer), 304 queue_(zone), 305 typing_stack_(zone), 306 source_positions_(source_positions), 307 node_origins_(node_origins), 308 type_cache_(TypeCache::Get()), 309 op_typer_(jsgraph->isolate(), js_heap_broker, graph_zone()) { 310 } 311 312 // Forward propagation of types from type feedback. 313 void RunTypePropagationPhase() { 314 // Run type propagation. 315 TRACE("--{Type propagation phase}--\n"); 316 phase_ = RETYPE; 317 ResetNodeInfoState(); 318 319 DCHECK(typing_stack_.empty()); 320 typing_stack_.push({graph()->end(), 0}); 321 GetInfo(graph()->end())->set_pushed(); 322 while (!typing_stack_.empty()) { 323 NodeState& current = typing_stack_.top(); 324 325 // If there is an unvisited input, push it and continue. 326 bool pushed_unvisited = false; 327 while (current.input_index < current.node->InputCount()) { 328 Node* input = current.node->InputAt(current.input_index); 329 NodeInfo* input_info = GetInfo(input); 330 current.input_index++; 331 if (input_info->unvisited()) { 332 input_info->set_pushed(); 333 typing_stack_.push({input, 0}); 334 pushed_unvisited = true; 335 break; 336 } 337 } 338 if (pushed_unvisited) continue; 339 340 // Process the top of the stack. 341 Node* node = current.node; 342 typing_stack_.pop(); 343 NodeInfo* info = GetInfo(node); 344 info->set_visited(); 345 bool updated = UpdateFeedbackType(node); 346 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); 347 VisitNode(node, info->truncation(), nullptr); 348 TRACE(" ==> output "); 349 PrintOutputInfo(info); 350 TRACE("\n"); 351 if (updated) { 352 for (Node* const user : node->uses()) { 353 if (GetInfo(user)->visited()) { 354 GetInfo(user)->set_queued(); 355 queue_.push(user); 356 } 357 } 358 } 359 } 360 361 // Process the revisit queue. 362 while (!queue_.empty()) { 363 Node* node = queue_.front(); 364 queue_.pop(); 365 NodeInfo* info = GetInfo(node); 366 info->set_visited(); 367 bool updated = UpdateFeedbackType(node); 368 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); 369 VisitNode(node, info->truncation(), nullptr); 370 TRACE(" ==> output "); 371 PrintOutputInfo(info); 372 TRACE("\n"); 373 if (updated) { 374 for (Node* const user : node->uses()) { 375 if (GetInfo(user)->visited()) { 376 GetInfo(user)->set_queued(); 377 queue_.push(user); 378 } 379 } 380 } 381 } 382 } 383 384 void ResetNodeInfoState() { 385 // Clean up for the next phase. 386 for (NodeInfo& info : info_) { 387 info.reset_state(); 388 } 389 } 390 391 Type TypeOf(Node* node) { 392 Type type = GetInfo(node)->feedback_type(); 393 return type.IsInvalid() ? NodeProperties::GetType(node) : type; 394 } 395 396 Type FeedbackTypeOf(Node* node) { 397 Type type = GetInfo(node)->feedback_type(); 398 return type.IsInvalid() ? Type::None() : type; 399 } 400 401 Type TypePhi(Node* node) { 402 int arity = node->op()->ValueInputCount(); 403 Type type = FeedbackTypeOf(node->InputAt(0)); 404 for (int i = 1; i < arity; ++i) { 405 type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i))); 406 } 407 return type; 408 } 409 410 Type TypeSelect(Node* node) { 411 return op_typer_.Merge(FeedbackTypeOf(node->InputAt(1)), 412 FeedbackTypeOf(node->InputAt(2))); 413 } 414 415 bool UpdateFeedbackType(Node* node) { 416 if (node->op()->ValueOutputCount() == 0) return false; 417 418 NodeInfo* info = GetInfo(node); 419 Type type = info->feedback_type(); 420 Type new_type = type; 421 422 // For any non-phi node just wait until we get all inputs typed. We only 423 // allow untyped inputs for phi nodes because phis are the only places 424 // where cycles need to be broken. 425 if (node->opcode() != IrOpcode::kPhi) { 426 for (int i = 0; i < node->op()->ValueInputCount(); i++) { 427 if (GetInfo(node->InputAt(i))->feedback_type().IsInvalid()) { 428 return false; 429 } 430 } 431 } 432 433 switch (node->opcode()) { 434 #define DECLARE_CASE(Name) \ 435 case IrOpcode::k##Name: { \ 436 new_type = op_typer_.Name(FeedbackTypeOf(node->InputAt(0)), \ 437 FeedbackTypeOf(node->InputAt(1))); \ 438 break; \ 439 } 440 SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_CASE) 441 DECLARE_CASE(SameValue) 442 #undef DECLARE_CASE 443 444 #define DECLARE_CASE(Name) \ 445 case IrOpcode::k##Name: { \ 446 new_type = \ 447 Type::Intersect(op_typer_.Name(FeedbackTypeOf(node->InputAt(0)), \ 448 FeedbackTypeOf(node->InputAt(1))), \ 449 info->restriction_type(), graph_zone()); \ 450 break; \ 451 } 452 SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_CASE) 453 #undef DECLARE_CASE 454 455 #define DECLARE_CASE(Name) \ 456 case IrOpcode::k##Name: { \ 457 new_type = op_typer_.Name(FeedbackTypeOf(node->InputAt(0))); \ 458 break; \ 459 } 460 SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE) 461 #undef DECLARE_CASE 462 463 #define DECLARE_CASE(Name) \ 464 case IrOpcode::k##Name: { \ 465 new_type = \ 466 Type::Intersect(op_typer_.Name(FeedbackTypeOf(node->InputAt(0))), \ 467 info->restriction_type(), graph_zone()); \ 468 break; \ 469 } 470 SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(DECLARE_CASE) 471 #undef DECLARE_CASE 472 473 case IrOpcode::kConvertReceiver: 474 new_type = op_typer_.ConvertReceiver(FeedbackTypeOf(node->InputAt(0))); 475 break; 476 477 case IrOpcode::kPlainPrimitiveToNumber: 478 new_type = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); 479 break; 480 481 case IrOpcode::kCheckFloat64Hole: 482 new_type = Type::Intersect( 483 op_typer_.CheckFloat64Hole(FeedbackTypeOf(node->InputAt(0))), 484 info->restriction_type(), graph_zone()); 485 break; 486 487 case IrOpcode::kCheckNumber: 488 new_type = Type::Intersect( 489 op_typer_.CheckNumber(FeedbackTypeOf(node->InputAt(0))), 490 info->restriction_type(), graph_zone()); 491 break; 492 493 case IrOpcode::kPhi: { 494 new_type = TypePhi(node); 495 if (!type.IsInvalid()) { 496 new_type = Weaken(node, type, new_type); 497 } 498 break; 499 } 500 501 case IrOpcode::kConvertTaggedHoleToUndefined: 502 new_type = op_typer_.ConvertTaggedHoleToUndefined( 503 FeedbackTypeOf(node->InputAt(0))); 504 break; 505 506 case IrOpcode::kTypeGuard: { 507 new_type = op_typer_.TypeTypeGuard(node->op(), 508 FeedbackTypeOf(node->InputAt(0))); 509 break; 510 } 511 512 case IrOpcode::kSelect: { 513 new_type = TypeSelect(node); 514 break; 515 } 516 517 default: 518 // Shortcut for operations that we do not handle. 519 if (type.IsInvalid()) { 520 GetInfo(node)->set_feedback_type(NodeProperties::GetType(node)); 521 return true; 522 } 523 return false; 524 } 525 // We need to guarantee that the feedback type is a subtype of the upper 526 // bound. Naively that should hold, but weakening can actually produce 527 // a bigger type if we are unlucky with ordering of phi typing. To be 528 // really sure, just intersect the upper bound with the feedback type. 529 new_type = Type::Intersect(GetUpperBound(node), new_type, graph_zone()); 530 531 if (!type.IsInvalid() && new_type.Is(type)) return false; 532 GetInfo(node)->set_feedback_type(new_type); 533 if (FLAG_trace_representation) { 534 PrintNodeFeedbackType(node); 535 } 536 return true; 537 } 538 539 void PrintNodeFeedbackType(Node* n) { 540 StdoutStream os; 541 os << "#" << n->id() << ":" << *n->op() << "("; 542 int j = 0; 543 for (Node* const i : n->inputs()) { 544 if (j++ > 0) os << ", "; 545 os << "#" << i->id() << ":" << i->op()->mnemonic(); 546 } 547 os << ")"; 548 if (NodeProperties::IsTyped(n)) { 549 Type static_type = NodeProperties::GetType(n); 550 os << " [Static type: " << static_type; 551 Type feedback_type = GetInfo(n)->feedback_type(); 552 if (!feedback_type.IsInvalid() && feedback_type != static_type) { 553 os << ", Feedback type: " << feedback_type; 554 } 555 os << "]"; 556 } 557 os << std::endl; 558 } 559 560 Type Weaken(Node* node, Type previous_type, Type current_type) { 561 // If the types have nothing to do with integers, return the types. 562 Type const integer = type_cache_.kInteger; 563 if (!previous_type.Maybe(integer)) { 564 return current_type; 565 } 566 DCHECK(current_type.Maybe(integer)); 567 568 Type current_integer = Type::Intersect(current_type, integer, graph_zone()); 569 DCHECK(!current_integer.IsNone()); 570 Type previous_integer = 571 Type::Intersect(previous_type, integer, graph_zone()); 572 DCHECK(!previous_integer.IsNone()); 573 574 // Once we start weakening a node, we should always weaken. 575 if (!GetInfo(node)->weakened()) { 576 // Only weaken if there is range involved; we should converge quickly 577 // for all other types (the exception is a union of many constants, 578 // but we currently do not increase the number of constants in unions). 579 Type previous = previous_integer.GetRange(); 580 Type current = current_integer.GetRange(); 581 if (current.IsInvalid() || previous.IsInvalid()) { 582 return current_type; 583 } 584 // Range is involved => we are weakening. 585 GetInfo(node)->set_weakened(); 586 } 587 588 return Type::Union(current_type, 589 op_typer_.WeakenRange(previous_integer, current_integer), 590 graph_zone()); 591 } 592 593 // Backward propagation of truncations. 594 void RunTruncationPropagationPhase() { 595 // Run propagation phase to a fixpoint. 596 TRACE("--{Propagation phase}--\n"); 597 phase_ = PROPAGATE; 598 EnqueueInitial(jsgraph_->graph()->end()); 599 // Process nodes from the queue until it is empty. 600 while (!queue_.empty()) { 601 Node* node = queue_.front(); 602 NodeInfo* info = GetInfo(node); 603 queue_.pop(); 604 info->set_visited(); 605 TRACE(" visit #%d: %s (trunc: %s)\n", node->id(), node->op()->mnemonic(), 606 info->truncation().description()); 607 VisitNode(node, info->truncation(), nullptr); 608 } 609 } 610 611 void Run(SimplifiedLowering* lowering) { 612 RunTruncationPropagationPhase(); 613 614 RunTypePropagationPhase(); 615 616 // Run lowering and change insertion phase. 617 TRACE("--{Simplified lowering phase}--\n"); 618 phase_ = LOWER; 619 // Process nodes from the collected {nodes_} vector. 620 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) { 621 Node* node = *i; 622 NodeInfo* info = GetInfo(node); 623 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); 624 // Reuse {VisitNode()} so the representation rules are in one place. 625 SourcePositionTable::Scope scope( 626 source_positions_, source_positions_->GetSourcePosition(node)); 627 NodeOriginTable::Scope origin_scope(node_origins_, "simplified lowering", 628 node); 629 VisitNode(node, info->truncation(), lowering); 630 } 631 632 // Perform the final replacements. 633 for (NodeVector::iterator i = replacements_.begin(); 634 i != replacements_.end(); ++i) { 635 Node* node = *i; 636 Node* replacement = *(++i); 637 node->ReplaceUses(replacement); 638 node->Kill(); 639 // We also need to replace the node in the rest of the vector. 640 for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) { 641 ++j; 642 if (*j == node) *j = replacement; 643 } 644 } 645 } 646 647 void EnqueueInitial(Node* node) { 648 NodeInfo* info = GetInfo(node); 649 info->set_queued(); 650 nodes_.push_back(node); 651 queue_.push(node); 652 } 653 654 // Enqueue {use_node}'s {index} input if the {use} contains new information 655 // for that input node. Add the input to {nodes_} if this is the first time 656 // it's been visited. 657 void EnqueueInput(Node* use_node, int index, 658 UseInfo use_info = UseInfo::None()) { 659 Node* node = use_node->InputAt(index); 660 if (phase_ != PROPAGATE) return; 661 NodeInfo* info = GetInfo(node); 662 #ifdef DEBUG 663 // Check monotonicity of input requirements. 664 node_input_use_infos_[use_node->id()].SetAndCheckInput(use_node, index, 665 use_info); 666 #endif // DEBUG 667 if (info->unvisited()) { 668 // First visit of this node. 669 info->set_queued(); 670 nodes_.push_back(node); 671 queue_.push(node); 672 TRACE(" initial #%i: ", node->id()); 673 info->AddUse(use_info); 674 PrintTruncation(info->truncation()); 675 return; 676 } 677 TRACE(" queue #%i?: ", node->id()); 678 PrintTruncation(info->truncation()); 679 if (info->AddUse(use_info)) { 680 // New usage information for the node is available. 681 if (!info->queued()) { 682 queue_.push(node); 683 info->set_queued(); 684 TRACE(" added: "); 685 } else { 686 TRACE(" inqueue: "); 687 } 688 PrintTruncation(info->truncation()); 689 } 690 } 691 692 bool lower() const { return phase_ == LOWER; } 693 bool retype() const { return phase_ == RETYPE; } 694 bool propagate() const { return phase_ == PROPAGATE; } 695 696 void SetOutput(Node* node, MachineRepresentation representation, 697 Type restriction_type = Type::Any()) { 698 NodeInfo* const info = GetInfo(node); 699 switch (phase_) { 700 case PROPAGATE: 701 info->set_restriction_type(restriction_type); 702 break; 703 case RETYPE: 704 DCHECK(info->restriction_type().Is(restriction_type)); 705 DCHECK(restriction_type.Is(info->restriction_type())); 706 info->set_output(representation); 707 break; 708 case LOWER: 709 DCHECK_EQ(info->representation(), representation); 710 DCHECK(info->restriction_type().Is(restriction_type)); 711 DCHECK(restriction_type.Is(info->restriction_type())); 712 break; 713 } 714 } 715 716 Type GetUpperBound(Node* node) { return NodeProperties::GetType(node); } 717 718 bool InputCannotBe(Node* node, Type type) { 719 DCHECK_EQ(1, node->op()->ValueInputCount()); 720 return !GetUpperBound(node->InputAt(0)).Maybe(type); 721 } 722 723 bool InputIs(Node* node, Type type) { 724 DCHECK_EQ(1, node->op()->ValueInputCount()); 725 return GetUpperBound(node->InputAt(0)).Is(type); 726 } 727 728 bool BothInputsAreSigned32(Node* node) { 729 return BothInputsAre(node, Type::Signed32()); 730 } 731 732 bool BothInputsAreUnsigned32(Node* node) { 733 return BothInputsAre(node, Type::Unsigned32()); 734 } 735 736 bool BothInputsAre(Node* node, Type type) { 737 DCHECK_EQ(2, node->op()->ValueInputCount()); 738 return GetUpperBound(node->InputAt(0)).Is(type) && 739 GetUpperBound(node->InputAt(1)).Is(type); 740 } 741 742 bool IsNodeRepresentationTagged(Node* node) { 743 MachineRepresentation representation = GetInfo(node)->representation(); 744 return IsAnyTagged(representation); 745 } 746 747 bool OneInputCannotBe(Node* node, Type type) { 748 DCHECK_EQ(2, node->op()->ValueInputCount()); 749 return !GetUpperBound(node->InputAt(0)).Maybe(type) || 750 !GetUpperBound(node->InputAt(1)).Maybe(type); 751 } 752 753 // Converts input {index} of {node} according to given UseInfo {use}, 754 // assuming the type of the input is {input_type}. If {input_type} is null, 755 // it takes the input from the input node {TypeOf(node->InputAt(index))}. 756 void ConvertInput(Node* node, int index, UseInfo use, 757 Type input_type = Type::Invalid()) { 758 Node* input = node->InputAt(index); 759 // In the change phase, insert a change before the use if necessary. 760 if (use.representation() == MachineRepresentation::kNone) 761 return; // No input requirement on the use. 762 DCHECK_NOT_NULL(input); 763 NodeInfo* input_info = GetInfo(input); 764 MachineRepresentation input_rep = input_info->representation(); 765 if (input_rep != use.representation() || 766 use.type_check() != TypeCheckKind::kNone) { 767 // Output representation doesn't match usage. 768 TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(), 769 index, input->id(), input->op()->mnemonic()); 770 TRACE(" from "); 771 PrintOutputInfo(input_info); 772 TRACE(" to "); 773 PrintUseInfo(use); 774 TRACE("\n"); 775 if (input_type.IsInvalid()) { 776 input_type = TypeOf(input); 777 } 778 Node* n = changer_->GetRepresentationFor( 779 input, input_info->representation(), input_type, node, use); 780 node->ReplaceInput(index, n); 781 } 782 } 783 784 void ProcessInput(Node* node, int index, UseInfo use) { 785 switch (phase_) { 786 case PROPAGATE: 787 EnqueueInput(node, index, use); 788 break; 789 case RETYPE: 790 break; 791 case LOWER: 792 ConvertInput(node, index, use); 793 break; 794 } 795 } 796 797 void ProcessRemainingInputs(Node* node, int index) { 798 DCHECK_GE(index, NodeProperties::PastValueIndex(node)); 799 DCHECK_GE(index, NodeProperties::PastContextIndex(node)); 800 for (int i = std::max(index, NodeProperties::FirstEffectIndex(node)); 801 i < NodeProperties::PastEffectIndex(node); ++i) { 802 EnqueueInput(node, i); // Effect inputs: just visit 803 } 804 for (int i = std::max(index, NodeProperties::FirstControlIndex(node)); 805 i < NodeProperties::PastControlIndex(node); ++i) { 806 EnqueueInput(node, i); // Control inputs: just visit 807 } 808 } 809 810 // The default, most general visitation case. For {node}, process all value, 811 // context, frame state, effect, and control inputs, assuming that value 812 // inputs should have {kRepTagged} representation and can observe all output 813 // values {kTypeAny}. 814 void VisitInputs(Node* node) { 815 int tagged_count = node->op()->ValueInputCount() + 816 OperatorProperties::GetContextInputCount(node->op()) + 817 OperatorProperties::GetFrameStateInputCount(node->op()); 818 // Visit value, context and frame state inputs as tagged. 819 for (int i = 0; i < tagged_count; i++) { 820 ProcessInput(node, i, UseInfo::AnyTagged()); 821 } 822 // Only enqueue other inputs (effects, control). 823 for (int i = tagged_count; i < node->InputCount(); i++) { 824 EnqueueInput(node, i); 825 } 826 } 827 828 void VisitReturn(Node* node) { 829 int tagged_limit = node->op()->ValueInputCount() + 830 OperatorProperties::GetContextInputCount(node->op()) + 831 OperatorProperties::GetFrameStateInputCount(node->op()); 832 // Visit integer slot count to pop 833 ProcessInput(node, 0, UseInfo::TruncatingWord32()); 834 835 // Visit value, context and frame state inputs as tagged. 836 for (int i = 1; i < tagged_limit; i++) { 837 ProcessInput(node, i, UseInfo::AnyTagged()); 838 } 839 // Only enqueue other inputs (effects, control). 840 for (int i = tagged_limit; i < node->InputCount(); i++) { 841 EnqueueInput(node, i); 842 } 843 } 844 845 // Helper for an unused node. 846 void VisitUnused(Node* node) { 847 int value_count = node->op()->ValueInputCount() + 848 OperatorProperties::GetContextInputCount(node->op()) + 849 OperatorProperties::GetFrameStateInputCount(node->op()); 850 for (int i = 0; i < value_count; i++) { 851 ProcessInput(node, i, UseInfo::None()); 852 } 853 ProcessRemainingInputs(node, value_count); 854 if (lower()) Kill(node); 855 } 856 857 // Helper for no-op node. 858 void VisitNoop(Node* node, Truncation truncation) { 859 if (truncation.IsUnused()) return VisitUnused(node); 860 MachineRepresentation representation = 861 GetOutputInfoForPhi(node, TypeOf(node), truncation); 862 VisitUnop(node, UseInfo(representation, truncation), representation); 863 if (lower()) DeferReplacement(node, node->InputAt(0)); 864 } 865 866 // Helper for binops of the R x L -> O variety. 867 void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use, 868 MachineRepresentation output, 869 Type restriction_type = Type::Any()) { 870 DCHECK_EQ(2, node->op()->ValueInputCount()); 871 ProcessInput(node, 0, left_use); 872 ProcessInput(node, 1, right_use); 873 for (int i = 2; i < node->InputCount(); i++) { 874 EnqueueInput(node, i); 875 } 876 SetOutput(node, output, restriction_type); 877 } 878 879 // Helper for binops of the I x I -> O variety. 880 void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output, 881 Type restriction_type = Type::Any()) { 882 VisitBinop(node, input_use, input_use, output, restriction_type); 883 } 884 885 void VisitSpeculativeInt32Binop(Node* node) { 886 DCHECK_EQ(2, node->op()->ValueInputCount()); 887 if (BothInputsAre(node, Type::NumberOrOddball())) { 888 return VisitBinop(node, UseInfo::TruncatingWord32(), 889 MachineRepresentation::kWord32); 890 } 891 NumberOperationHint hint = NumberOperationHintOf(node->op()); 892 return VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), 893 MachineRepresentation::kWord32); 894 } 895 896 // Helper for unops of the I -> O variety. 897 void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output, 898 Type restriction_type = Type::Any()) { 899 DCHECK_EQ(1, node->op()->ValueInputCount()); 900 ProcessInput(node, 0, input_use); 901 ProcessRemainingInputs(node, 1); 902 SetOutput(node, output, restriction_type); 903 } 904 905 // Helper for leaf nodes. 906 void VisitLeaf(Node* node, MachineRepresentation output) { 907 DCHECK_EQ(0, node->InputCount()); 908 SetOutput(node, output); 909 } 910 911 // Helpers for specific types of binops. 912 void VisitFloat64Binop(Node* node) { 913 VisitBinop(node, UseInfo::TruncatingFloat64(), 914 MachineRepresentation::kFloat64); 915 } 916 void VisitWord32TruncatingBinop(Node* node) { 917 VisitBinop(node, UseInfo::TruncatingWord32(), 918 MachineRepresentation::kWord32); 919 } 920 921 // Infer representation for phi-like nodes. 922 // The {node} parameter is only used to decide on the int64 representation. 923 // Once the type system supports an external pointer type, the {node} 924 // parameter can be removed. 925 MachineRepresentation GetOutputInfoForPhi(Node* node, Type type, 926 Truncation use) { 927 // Compute the representation. 928 if (type.Is(Type::None())) { 929 return MachineRepresentation::kNone; 930 } else if (type.Is(Type::Signed32()) || type.Is(Type::Unsigned32())) { 931 return MachineRepresentation::kWord32; 932 } else if (type.Is(Type::NumberOrOddball()) && use.IsUsedAsWord32()) { 933 return MachineRepresentation::kWord32; 934 } else if (type.Is(Type::Boolean())) { 935 return MachineRepresentation::kBit; 936 } else if (type.Is(Type::NumberOrOddball()) && use.IsUsedAsFloat64()) { 937 return MachineRepresentation::kFloat64; 938 } else if (type.Is(Type::Union(Type::SignedSmall(), Type::NaN(), zone()))) { 939 // TODO(turbofan): For Phis that return either NaN or some Smi, it's 940 // beneficial to not go all the way to double, unless the uses are 941 // double uses. For tagging that just means some potentially expensive 942 // allocation code; we might want to do the same for -0 as well? 943 return MachineRepresentation::kTagged; 944 } else if (type.Is(Type::Number())) { 945 return MachineRepresentation::kFloat64; 946 } else if (type.Is(Type::ExternalPointer())) { 947 return MachineType::PointerRepresentation(); 948 } 949 return MachineRepresentation::kTagged; 950 } 951 952 // Helper for handling selects. 953 void VisitSelect(Node* node, Truncation truncation, 954 SimplifiedLowering* lowering) { 955 DCHECK(TypeOf(node->InputAt(0)).Is(Type::Boolean())); 956 ProcessInput(node, 0, UseInfo::Bool()); 957 958 MachineRepresentation output = 959 GetOutputInfoForPhi(node, TypeOf(node), truncation); 960 SetOutput(node, output); 961 962 if (lower()) { 963 // Update the select operator. 964 SelectParameters p = SelectParametersOf(node->op()); 965 if (output != p.representation()) { 966 NodeProperties::ChangeOp(node, 967 lowering->common()->Select(output, p.hint())); 968 } 969 } 970 // Convert inputs to the output representation of this phi, pass the 971 // truncation truncation along. 972 UseInfo input_use(output, truncation); 973 ProcessInput(node, 1, input_use); 974 ProcessInput(node, 2, input_use); 975 } 976 977 // Helper for handling phis. 978 void VisitPhi(Node* node, Truncation truncation, 979 SimplifiedLowering* lowering) { 980 MachineRepresentation output = 981 GetOutputInfoForPhi(node, TypeOf(node), truncation); 982 // Only set the output representation if not running with type 983 // feedback. (Feedback typing will set the representation.) 984 SetOutput(node, output); 985 986 int values = node->op()->ValueInputCount(); 987 if (lower()) { 988 // Update the phi operator. 989 if (output != PhiRepresentationOf(node->op())) { 990 NodeProperties::ChangeOp(node, lowering->common()->Phi(output, values)); 991 } 992 } 993 994 // Convert inputs to the output representation of this phi, pass the 995 // truncation along. 996 UseInfo input_use(output, truncation); 997 for (int i = 0; i < node->InputCount(); i++) { 998 ProcessInput(node, i, i < values ? input_use : UseInfo::None()); 999 } 1000 } 1001 1002 void VisitObjectIs(Node* node, Type type, SimplifiedLowering* lowering) { 1003 Type const input_type = TypeOf(node->InputAt(0)); 1004 if (input_type.Is(type)) { 1005 VisitUnop(node, UseInfo::None(), MachineRepresentation::kBit); 1006 if (lower()) { 1007 DeferReplacement(node, lowering->jsgraph()->Int32Constant(1)); 1008 } 1009 } else { 1010 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 1011 if (lower() && !input_type.Maybe(type)) { 1012 DeferReplacement(node, lowering->jsgraph()->Int32Constant(0)); 1013 } 1014 } 1015 } 1016 1017 void VisitCheck(Node* node, Type type, SimplifiedLowering* lowering) { 1018 if (InputIs(node, type)) { 1019 VisitUnop(node, UseInfo::AnyTagged(), 1020 MachineRepresentation::kTaggedPointer); 1021 if (lower()) DeferReplacement(node, node->InputAt(0)); 1022 } else { 1023 VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(), 1024 MachineRepresentation::kTaggedPointer); 1025 } 1026 return; 1027 } 1028 1029 void VisitCall(Node* node, SimplifiedLowering* lowering) { 1030 auto call_descriptor = CallDescriptorOf(node->op()); 1031 int params = static_cast<int>(call_descriptor->ParameterCount()); 1032 int value_input_count = node->op()->ValueInputCount(); 1033 // Propagate representation information from call descriptor. 1034 for (int i = 0; i < value_input_count; i++) { 1035 if (i == 0) { 1036 // The target of the call. 1037 ProcessInput(node, i, UseInfo::Any()); 1038 } else if ((i - 1) < params) { 1039 ProcessInput(node, i, 1040 TruncatingUseInfoFromRepresentation( 1041 call_descriptor->GetInputType(i).representation())); 1042 } else { 1043 ProcessInput(node, i, UseInfo::AnyTagged()); 1044 } 1045 } 1046 ProcessRemainingInputs(node, value_input_count); 1047 1048 if (call_descriptor->ReturnCount() > 0) { 1049 SetOutput(node, call_descriptor->GetReturnType(0).representation()); 1050 } else { 1051 SetOutput(node, MachineRepresentation::kTagged); 1052 } 1053 } 1054 1055 static MachineSemantic DeoptValueSemanticOf(Type type) { 1056 // We only need signedness to do deopt correctly. 1057 if (type.Is(Type::Signed32())) { 1058 return MachineSemantic::kInt32; 1059 } else if (type.Is(Type::Unsigned32())) { 1060 return MachineSemantic::kUint32; 1061 } else { 1062 return MachineSemantic::kAny; 1063 } 1064 } 1065 1066 static MachineType DeoptMachineTypeOf(MachineRepresentation rep, Type type) { 1067 if (type.IsNone()) { 1068 return MachineType::None(); 1069 } 1070 // TODO(turbofan): Special treatment for ExternalPointer here, 1071 // to avoid incompatible truncations. We really need a story 1072 // for the JSFunction::entry field. 1073 if (type.Is(Type::ExternalPointer())) { 1074 return MachineType::Pointer(); 1075 } 1076 // Do not distinguish between various Tagged variations. 1077 if (IsAnyTagged(rep)) { 1078 return MachineType::AnyTagged(); 1079 } 1080 MachineType machine_type(rep, DeoptValueSemanticOf(type)); 1081 DCHECK(machine_type.representation() != MachineRepresentation::kWord32 || 1082 machine_type.semantic() == MachineSemantic::kInt32 || 1083 machine_type.semantic() == MachineSemantic::kUint32); 1084 DCHECK(machine_type.representation() != MachineRepresentation::kBit || 1085 type.Is(Type::Boolean())); 1086 return machine_type; 1087 } 1088 1089 void VisitStateValues(Node* node) { 1090 if (propagate()) { 1091 for (int i = 0; i < node->InputCount(); i++) { 1092 EnqueueInput(node, i, UseInfo::Any()); 1093 } 1094 } else if (lower()) { 1095 Zone* zone = jsgraph_->zone(); 1096 ZoneVector<MachineType>* types = 1097 new (zone->New(sizeof(ZoneVector<MachineType>))) 1098 ZoneVector<MachineType>(node->InputCount(), zone); 1099 for (int i = 0; i < node->InputCount(); i++) { 1100 Node* input = node->InputAt(i); 1101 (*types)[i] = 1102 DeoptMachineTypeOf(GetInfo(input)->representation(), TypeOf(input)); 1103 } 1104 SparseInputMask mask = SparseInputMaskOf(node->op()); 1105 NodeProperties::ChangeOp( 1106 node, jsgraph_->common()->TypedStateValues(types, mask)); 1107 } 1108 SetOutput(node, MachineRepresentation::kTagged); 1109 } 1110 1111 void VisitFrameState(Node* node) { 1112 DCHECK_EQ(5, node->op()->ValueInputCount()); 1113 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); 1114 1115 ProcessInput(node, 0, UseInfo::AnyTagged()); // Parameters. 1116 ProcessInput(node, 1, UseInfo::AnyTagged()); // Registers. 1117 1118 // Accumulator is a special flower - we need to remember its type in 1119 // a singleton typed-state-values node (as if it was a singleton 1120 // state-values node). 1121 if (propagate()) { 1122 EnqueueInput(node, 2, UseInfo::Any()); 1123 } else if (lower()) { 1124 Zone* zone = jsgraph_->zone(); 1125 Node* accumulator = node->InputAt(2); 1126 if (accumulator == jsgraph_->OptimizedOutConstant()) { 1127 node->ReplaceInput(2, jsgraph_->SingleDeadTypedStateValues()); 1128 } else { 1129 ZoneVector<MachineType>* types = 1130 new (zone->New(sizeof(ZoneVector<MachineType>))) 1131 ZoneVector<MachineType>(1, zone); 1132 (*types)[0] = DeoptMachineTypeOf(GetInfo(accumulator)->representation(), 1133 TypeOf(accumulator)); 1134 1135 node->ReplaceInput( 1136 2, jsgraph_->graph()->NewNode(jsgraph_->common()->TypedStateValues( 1137 types, SparseInputMask::Dense()), 1138 accumulator)); 1139 } 1140 } 1141 1142 ProcessInput(node, 3, UseInfo::AnyTagged()); // Context. 1143 ProcessInput(node, 4, UseInfo::AnyTagged()); // Closure. 1144 ProcessInput(node, 5, UseInfo::AnyTagged()); // Outer frame state. 1145 return SetOutput(node, MachineRepresentation::kTagged); 1146 } 1147 1148 void VisitObjectState(Node* node) { 1149 if (propagate()) { 1150 for (int i = 0; i < node->InputCount(); i++) { 1151 EnqueueInput(node, i, UseInfo::Any()); 1152 } 1153 } else if (lower()) { 1154 Zone* zone = jsgraph_->zone(); 1155 ZoneVector<MachineType>* types = 1156 new (zone->New(sizeof(ZoneVector<MachineType>))) 1157 ZoneVector<MachineType>(node->InputCount(), zone); 1158 for (int i = 0; i < node->InputCount(); i++) { 1159 Node* input = node->InputAt(i); 1160 (*types)[i] = 1161 DeoptMachineTypeOf(GetInfo(input)->representation(), TypeOf(input)); 1162 } 1163 NodeProperties::ChangeOp(node, jsgraph_->common()->TypedObjectState( 1164 ObjectIdOf(node->op()), types)); 1165 } 1166 SetOutput(node, MachineRepresentation::kTagged); 1167 } 1168 1169 const Operator* Int32Op(Node* node) { 1170 return changer_->Int32OperatorFor(node->opcode()); 1171 } 1172 1173 const Operator* Int32OverflowOp(Node* node) { 1174 return changer_->Int32OverflowOperatorFor(node->opcode()); 1175 } 1176 1177 const Operator* Uint32Op(Node* node) { 1178 return changer_->Uint32OperatorFor(node->opcode()); 1179 } 1180 1181 const Operator* Uint32OverflowOp(Node* node) { 1182 return changer_->Uint32OverflowOperatorFor(node->opcode()); 1183 } 1184 1185 const Operator* Float64Op(Node* node) { 1186 return changer_->Float64OperatorFor(node->opcode()); 1187 } 1188 1189 WriteBarrierKind WriteBarrierKindFor( 1190 BaseTaggedness base_taggedness, 1191 MachineRepresentation field_representation, Type field_type, 1192 MachineRepresentation value_representation, Node* value) { 1193 if (base_taggedness == kTaggedBase && 1194 CanBeTaggedPointer(field_representation)) { 1195 Type value_type = NodeProperties::GetType(value); 1196 if (field_representation == MachineRepresentation::kTaggedSigned || 1197 value_representation == MachineRepresentation::kTaggedSigned) { 1198 // Write barriers are only for stores of heap objects. 1199 return kNoWriteBarrier; 1200 } 1201 if (field_type.Is(Type::BooleanOrNullOrUndefined()) || 1202 value_type.Is(Type::BooleanOrNullOrUndefined())) { 1203 // Write barriers are not necessary when storing true, false, null or 1204 // undefined, because these special oddballs are always in the root set. 1205 return kNoWriteBarrier; 1206 } 1207 if (value_type.IsHeapConstant()) { 1208 Heap::RootListIndex root_index; 1209 Heap* heap = jsgraph_->isolate()->heap(); 1210 if (heap->IsRootHandle(value_type.AsHeapConstant()->Value(), 1211 &root_index)) { 1212 if (heap->RootIsImmortalImmovable(root_index)) { 1213 // Write barriers are unnecessary for immortal immovable roots. 1214 return kNoWriteBarrier; 1215 } 1216 } 1217 } 1218 if (field_representation == MachineRepresentation::kTaggedPointer || 1219 value_representation == MachineRepresentation::kTaggedPointer) { 1220 // Write barriers for heap objects are cheaper. 1221 return kPointerWriteBarrier; 1222 } 1223 NumberMatcher m(value); 1224 if (m.HasValue()) { 1225 if (IsSmiDouble(m.Value())) { 1226 // Storing a smi doesn't need a write barrier. 1227 return kNoWriteBarrier; 1228 } 1229 // The NumberConstant will be represented as HeapNumber. 1230 return kPointerWriteBarrier; 1231 } 1232 return kFullWriteBarrier; 1233 } 1234 return kNoWriteBarrier; 1235 } 1236 1237 WriteBarrierKind WriteBarrierKindFor( 1238 BaseTaggedness base_taggedness, 1239 MachineRepresentation field_representation, int field_offset, 1240 Type field_type, MachineRepresentation value_representation, 1241 Node* value) { 1242 WriteBarrierKind write_barrier_kind = 1243 WriteBarrierKindFor(base_taggedness, field_representation, field_type, 1244 value_representation, value); 1245 if (write_barrier_kind != kNoWriteBarrier) { 1246 if (base_taggedness == kTaggedBase && 1247 field_offset == HeapObject::kMapOffset) { 1248 write_barrier_kind = kMapWriteBarrier; 1249 } 1250 } 1251 return write_barrier_kind; 1252 } 1253 1254 Graph* graph() const { return jsgraph_->graph(); } 1255 CommonOperatorBuilder* common() const { return jsgraph_->common(); } 1256 SimplifiedOperatorBuilder* simplified() const { 1257 return jsgraph_->simplified(); 1258 } 1259 1260 void LowerToCheckedInt32Mul(Node* node, Truncation truncation, 1261 Type input0_type, Type input1_type) { 1262 // If one of the inputs is positive and/or truncation is being applied, 1263 // there is no need to return -0. 1264 CheckForMinusZeroMode mz_mode = 1265 truncation.IdentifiesZeroAndMinusZero() || 1266 IsSomePositiveOrderedNumber(input0_type) || 1267 IsSomePositiveOrderedNumber(input1_type) 1268 ? CheckForMinusZeroMode::kDontCheckForMinusZero 1269 : CheckForMinusZeroMode::kCheckForMinusZero; 1270 1271 NodeProperties::ChangeOp(node, simplified()->CheckedInt32Mul(mz_mode)); 1272 } 1273 1274 void ChangeToInt32OverflowOp(Node* node) { 1275 NodeProperties::ChangeOp(node, Int32OverflowOp(node)); 1276 } 1277 1278 void ChangeToUint32OverflowOp(Node* node) { 1279 NodeProperties::ChangeOp(node, Uint32OverflowOp(node)); 1280 } 1281 1282 void VisitSpeculativeIntegerAdditiveOp(Node* node, Truncation truncation, 1283 SimplifiedLowering* lowering) { 1284 Type left_upper = GetUpperBound(node->InputAt(0)); 1285 Type right_upper = GetUpperBound(node->InputAt(1)); 1286 1287 if (left_upper.Is(type_cache_.kAdditiveSafeIntegerOrMinusZero) && 1288 right_upper.Is(type_cache_.kAdditiveSafeIntegerOrMinusZero)) { 1289 // Only eliminate the node if its typing rule can be satisfied, namely 1290 // that a safe integer is produced. 1291 if (truncation.IsUnused()) return VisitUnused(node); 1292 1293 // If we know how to interpret the result or if the users only care 1294 // about the low 32-bits, we can truncate to Word32 do a wrapping 1295 // addition. 1296 if (GetUpperBound(node).Is(Type::Signed32()) || 1297 GetUpperBound(node).Is(Type::Unsigned32()) || 1298 truncation.IsUsedAsWord32()) { 1299 // => Int32Add/Sub 1300 VisitWord32TruncatingBinop(node); 1301 if (lower()) ChangeToPureOp(node, Int32Op(node)); 1302 return; 1303 } 1304 } 1305 1306 // Try to use type feedback. 1307 NumberOperationHint hint = NumberOperationHintOf(node->op()); 1308 1309 DCHECK(hint == NumberOperationHint::kSignedSmall || 1310 hint == NumberOperationHint::kSigned32); 1311 1312 Type left_feedback_type = TypeOf(node->InputAt(0)); 1313 Type right_feedback_type = TypeOf(node->InputAt(1)); 1314 // Handle the case when no int32 checks on inputs are necessary (but 1315 // an overflow check is needed on the output). Note that we do not 1316 // have to do any check if at most one side can be minus zero. 1317 if (left_upper.Is(Type::Signed32OrMinusZero()) && 1318 right_upper.Is(Type::Signed32OrMinusZero()) && 1319 (left_upper.Is(Type::Signed32()) || right_upper.Is(Type::Signed32()))) { 1320 VisitBinop(node, UseInfo::TruncatingWord32(), 1321 MachineRepresentation::kWord32, Type::Signed32()); 1322 } else { 1323 // If the output's truncation is identify-zeros, we can pass it 1324 // along. Moreover, if the operation is addition and we know the 1325 // right-hand side is not minus zero, we do not have to distinguish 1326 // between 0 and -0. 1327 IdentifyZeros left_identify_zeros = truncation.identify_zeros(); 1328 if (node->opcode() == IrOpcode::kSpeculativeSafeIntegerAdd && 1329 !right_feedback_type.Maybe(Type::MinusZero())) { 1330 left_identify_zeros = kIdentifyZeros; 1331 } 1332 UseInfo left_use = CheckedUseInfoAsWord32FromHint(hint, VectorSlotPair(), 1333 left_identify_zeros); 1334 // For CheckedInt32Add and CheckedInt32Sub, we don't need to do 1335 // a minus zero check for the right hand side, since we already 1336 // know that the left hand side is a proper Signed32 value, 1337 // potentially guarded by a check. 1338 UseInfo right_use = CheckedUseInfoAsWord32FromHint(hint, VectorSlotPair(), 1339 kIdentifyZeros); 1340 VisitBinop(node, left_use, right_use, MachineRepresentation::kWord32, 1341 Type::Signed32()); 1342 } 1343 if (lower()) { 1344 if (truncation.IsUsedAsWord32() || 1345 !CanOverflowSigned32(node->op(), left_feedback_type, 1346 right_feedback_type, graph_zone())) { 1347 ChangeToPureOp(node, Int32Op(node)); 1348 1349 } else { 1350 ChangeToInt32OverflowOp(node); 1351 } 1352 } 1353 return; 1354 } 1355 1356 void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation, 1357 SimplifiedLowering* lowering) { 1358 if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) && 1359 (GetUpperBound(node).Is(Type::Signed32()) || 1360 GetUpperBound(node).Is(Type::Unsigned32()) || 1361 truncation.IsUsedAsWord32())) { 1362 // => Int32Add/Sub 1363 VisitWord32TruncatingBinop(node); 1364 if (lower()) ChangeToPureOp(node, Int32Op(node)); 1365 return; 1366 } 1367 1368 // default case => Float64Add/Sub 1369 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(VectorSlotPair()), 1370 MachineRepresentation::kFloat64, Type::Number()); 1371 if (lower()) { 1372 ChangeToPureOp(node, Float64Op(node)); 1373 } 1374 return; 1375 } 1376 1377 void VisitSpeculativeNumberModulus(Node* node, Truncation truncation, 1378 SimplifiedLowering* lowering) { 1379 if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) && 1380 (truncation.IsUsedAsWord32() || 1381 NodeProperties::GetType(node).Is(Type::Unsigned32()))) { 1382 // => unsigned Uint32Mod 1383 VisitWord32TruncatingBinop(node); 1384 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); 1385 return; 1386 } 1387 if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) && 1388 (truncation.IsUsedAsWord32() || 1389 NodeProperties::GetType(node).Is(Type::Signed32()))) { 1390 // => signed Int32Mod 1391 VisitWord32TruncatingBinop(node); 1392 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); 1393 return; 1394 } 1395 1396 // Try to use type feedback. 1397 NumberOperationHint hint = NumberOperationHintOf(node->op()); 1398 1399 // Handle the case when no uint32 checks on inputs are necessary 1400 // (but an overflow check is needed on the output). 1401 if (BothInputsAreUnsigned32(node)) { 1402 if (hint == NumberOperationHint::kSignedSmall || 1403 hint == NumberOperationHint::kSigned32) { 1404 VisitBinop(node, UseInfo::TruncatingWord32(), 1405 MachineRepresentation::kWord32, Type::Unsigned32()); 1406 if (lower()) ChangeToUint32OverflowOp(node); 1407 return; 1408 } 1409 } 1410 1411 // Handle the case when no int32 checks on inputs are necessary 1412 // (but an overflow check is needed on the output). 1413 if (BothInputsAre(node, Type::Signed32())) { 1414 // If both the inputs the feedback are int32, use the overflow op. 1415 if (hint == NumberOperationHint::kSignedSmall || 1416 hint == NumberOperationHint::kSigned32) { 1417 VisitBinop(node, UseInfo::TruncatingWord32(), 1418 MachineRepresentation::kWord32, Type::Signed32()); 1419 if (lower()) ChangeToInt32OverflowOp(node); 1420 return; 1421 } 1422 } 1423 1424 if (hint == NumberOperationHint::kSignedSmall || 1425 hint == NumberOperationHint::kSigned32) { 1426 // If the result is truncated, we only need to check the inputs. 1427 if (truncation.IsUsedAsWord32()) { 1428 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), 1429 MachineRepresentation::kWord32); 1430 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); 1431 } else if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN())) { 1432 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), 1433 MachineRepresentation::kWord32, Type::Unsigned32()); 1434 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); 1435 } else { 1436 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), 1437 MachineRepresentation::kWord32, Type::Signed32()); 1438 if (lower()) ChangeToInt32OverflowOp(node); 1439 } 1440 return; 1441 } 1442 1443 if (TypeOf(node->InputAt(0)).Is(Type::Unsigned32()) && 1444 TypeOf(node->InputAt(1)).Is(Type::Unsigned32()) && 1445 (truncation.IsUsedAsWord32() || 1446 NodeProperties::GetType(node).Is(Type::Unsigned32()))) { 1447 // We can only promise Float64 truncation here, as the decision is 1448 // based on the feedback types of the inputs. 1449 VisitBinop(node, 1450 UseInfo(MachineRepresentation::kWord32, Truncation::Float64()), 1451 MachineRepresentation::kWord32, Type::Number()); 1452 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); 1453 return; 1454 } 1455 if (TypeOf(node->InputAt(0)).Is(Type::Signed32()) && 1456 TypeOf(node->InputAt(1)).Is(Type::Signed32()) && 1457 (truncation.IsUsedAsWord32() || 1458 NodeProperties::GetType(node).Is(Type::Signed32()))) { 1459 // We can only promise Float64 truncation here, as the decision is 1460 // based on the feedback types of the inputs. 1461 VisitBinop(node, 1462 UseInfo(MachineRepresentation::kWord32, Truncation::Float64()), 1463 MachineRepresentation::kWord32, Type::Number()); 1464 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); 1465 return; 1466 } 1467 // default case => Float64Mod 1468 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(VectorSlotPair()), 1469 MachineRepresentation::kFloat64, Type::Number()); 1470 if (lower()) ChangeToPureOp(node, Float64Op(node)); 1471 return; 1472 } 1473 1474 // Dispatching routine for visiting the node {node} with the usage {use}. 1475 // Depending on the operator, propagate new usage info to the inputs. 1476 void VisitNode(Node* node, Truncation truncation, 1477 SimplifiedLowering* lowering) { 1478 // Unconditionally eliminate unused pure nodes (only relevant if there's 1479 // a pure operation in between two effectful ones, where the last one 1480 // is unused). 1481 // Note: We must not do this for constants, as they are cached and we 1482 // would thus kill the cached {node} during lowering (i.e. replace all 1483 // uses with Dead), but at that point some node lowering might have 1484 // already taken the constant {node} from the cache (while it was in 1485 // a sane state still) and we would afterwards replace that use with 1486 // Dead as well. 1487 if (node->op()->ValueInputCount() > 0 && 1488 node->op()->HasProperty(Operator::kPure)) { 1489 if (truncation.IsUnused()) return VisitUnused(node); 1490 } 1491 switch (node->opcode()) { 1492 //------------------------------------------------------------------ 1493 // Common operators. 1494 //------------------------------------------------------------------ 1495 case IrOpcode::kStart: 1496 // We use Start as a terminator for the frame state chain, so even 1497 // tho Start doesn't really produce a value, we have to say Tagged 1498 // here, otherwise the input conversion will fail. 1499 return VisitLeaf(node, MachineRepresentation::kTagged); 1500 case IrOpcode::kParameter: 1501 // TODO(titzer): use representation from linkage. 1502 return VisitUnop(node, UseInfo::None(), MachineRepresentation::kTagged); 1503 case IrOpcode::kInt32Constant: 1504 return VisitLeaf(node, MachineRepresentation::kWord32); 1505 case IrOpcode::kInt64Constant: 1506 return VisitLeaf(node, MachineRepresentation::kWord64); 1507 case IrOpcode::kExternalConstant: 1508 return VisitLeaf(node, MachineType::PointerRepresentation()); 1509 case IrOpcode::kNumberConstant: { 1510 double const value = OpParameter<double>(node->op()); 1511 int value_as_int; 1512 if (DoubleToSmiInteger(value, &value_as_int)) { 1513 VisitLeaf(node, MachineRepresentation::kTaggedSigned); 1514 if (lower()) { 1515 intptr_t smi = bit_cast<intptr_t>(Smi::FromInt(value_as_int)); 1516 DeferReplacement(node, lowering->jsgraph()->IntPtrConstant(smi)); 1517 } 1518 return; 1519 } 1520 VisitLeaf(node, MachineRepresentation::kTagged); 1521 return; 1522 } 1523 case IrOpcode::kHeapConstant: 1524 return VisitLeaf(node, MachineRepresentation::kTaggedPointer); 1525 case IrOpcode::kPointerConstant: { 1526 VisitLeaf(node, MachineType::PointerRepresentation()); 1527 if (lower()) { 1528 intptr_t const value = OpParameter<intptr_t>(node->op()); 1529 DeferReplacement(node, lowering->jsgraph()->IntPtrConstant(value)); 1530 } 1531 return; 1532 } 1533 1534 case IrOpcode::kBranch: { 1535 DCHECK(TypeOf(node->InputAt(0)).Is(Type::Boolean())); 1536 ProcessInput(node, 0, UseInfo::Bool()); 1537 EnqueueInput(node, NodeProperties::FirstControlIndex(node)); 1538 return; 1539 } 1540 case IrOpcode::kSwitch: 1541 ProcessInput(node, 0, UseInfo::TruncatingWord32()); 1542 EnqueueInput(node, NodeProperties::FirstControlIndex(node)); 1543 return; 1544 case IrOpcode::kSelect: 1545 return VisitSelect(node, truncation, lowering); 1546 case IrOpcode::kPhi: 1547 return VisitPhi(node, truncation, lowering); 1548 case IrOpcode::kCall: 1549 return VisitCall(node, lowering); 1550 1551 //------------------------------------------------------------------ 1552 // JavaScript operators. 1553 //------------------------------------------------------------------ 1554 case IrOpcode::kToBoolean: { 1555 if (truncation.IsUsedAsBool()) { 1556 ProcessInput(node, 0, UseInfo::Bool()); 1557 SetOutput(node, MachineRepresentation::kBit); 1558 if (lower()) DeferReplacement(node, node->InputAt(0)); 1559 } else { 1560 VisitInputs(node); 1561 SetOutput(node, MachineRepresentation::kTaggedPointer); 1562 } 1563 return; 1564 } 1565 case IrOpcode::kJSToNumber: 1566 case IrOpcode::kJSToNumberConvertBigInt: 1567 case IrOpcode::kJSToNumeric: { 1568 VisitInputs(node); 1569 // TODO(bmeurer): Optimize somewhat based on input type? 1570 if (truncation.IsUsedAsWord32()) { 1571 SetOutput(node, MachineRepresentation::kWord32); 1572 if (lower()) 1573 lowering->DoJSToNumberOrNumericTruncatesToWord32(node, this); 1574 } else if (truncation.IsUsedAsFloat64()) { 1575 SetOutput(node, MachineRepresentation::kFloat64); 1576 if (lower()) 1577 lowering->DoJSToNumberOrNumericTruncatesToFloat64(node, this); 1578 } else { 1579 SetOutput(node, MachineRepresentation::kTagged); 1580 } 1581 return; 1582 } 1583 1584 //------------------------------------------------------------------ 1585 // Simplified operators. 1586 //------------------------------------------------------------------ 1587 case IrOpcode::kBooleanNot: { 1588 if (lower()) { 1589 NodeInfo* input_info = GetInfo(node->InputAt(0)); 1590 if (input_info->representation() == MachineRepresentation::kBit) { 1591 // BooleanNot(x: kRepBit) => Word32Equal(x, #0) 1592 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0)); 1593 NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal()); 1594 } else if (CanBeTaggedPointer(input_info->representation())) { 1595 // BooleanNot(x: kRepTagged) => WordEqual(x, #false) 1596 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant()); 1597 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); 1598 } else { 1599 DCHECK(TypeOf(node->InputAt(0)).IsNone()); 1600 DeferReplacement(node, lowering->jsgraph()->Int32Constant(0)); 1601 } 1602 } else { 1603 // No input representation requirement; adapt during lowering. 1604 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool()); 1605 SetOutput(node, MachineRepresentation::kBit); 1606 } 1607 return; 1608 } 1609 case IrOpcode::kNumberEqual: { 1610 Type const lhs_type = TypeOf(node->InputAt(0)); 1611 Type const rhs_type = TypeOf(node->InputAt(1)); 1612 // Number comparisons reduce to integer comparisons for integer inputs. 1613 if ((lhs_type.Is(Type::Unsigned32()) && 1614 rhs_type.Is(Type::Unsigned32())) || 1615 (lhs_type.Is(Type::Unsigned32OrMinusZeroOrNaN()) && 1616 rhs_type.Is(Type::Unsigned32OrMinusZeroOrNaN()) && 1617 OneInputCannotBe(node, type_cache_.kZeroish))) { 1618 // => unsigned Int32Cmp 1619 VisitBinop(node, UseInfo::TruncatingWord32(), 1620 MachineRepresentation::kBit); 1621 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); 1622 return; 1623 } 1624 if ((lhs_type.Is(Type::Signed32()) && rhs_type.Is(Type::Signed32())) || 1625 (lhs_type.Is(Type::Signed32OrMinusZeroOrNaN()) && 1626 rhs_type.Is(Type::Signed32OrMinusZeroOrNaN()) && 1627 OneInputCannotBe(node, type_cache_.kZeroish))) { 1628 // => signed Int32Cmp 1629 VisitBinop(node, UseInfo::TruncatingWord32(), 1630 MachineRepresentation::kBit); 1631 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); 1632 return; 1633 } 1634 // => Float64Cmp 1635 VisitBinop(node, UseInfo::TruncatingFloat64(), 1636 MachineRepresentation::kBit); 1637 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); 1638 return; 1639 } 1640 case IrOpcode::kNumberLessThan: 1641 case IrOpcode::kNumberLessThanOrEqual: { 1642 // Number comparisons reduce to integer comparisons for integer inputs. 1643 if (TypeOf(node->InputAt(0)).Is(Type::Unsigned32()) && 1644 TypeOf(node->InputAt(1)).Is(Type::Unsigned32())) { 1645 // => unsigned Int32Cmp 1646 VisitBinop(node, UseInfo::TruncatingWord32(), 1647 MachineRepresentation::kBit); 1648 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); 1649 } else if (TypeOf(node->InputAt(0)).Is(Type::Signed32()) && 1650 TypeOf(node->InputAt(1)).Is(Type::Signed32())) { 1651 // => signed Int32Cmp 1652 VisitBinop(node, UseInfo::TruncatingWord32(), 1653 MachineRepresentation::kBit); 1654 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); 1655 } else { 1656 // => Float64Cmp 1657 VisitBinop(node, UseInfo::TruncatingFloat64(), 1658 MachineRepresentation::kBit); 1659 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); 1660 } 1661 return; 1662 } 1663 1664 case IrOpcode::kSpeculativeSafeIntegerAdd: 1665 case IrOpcode::kSpeculativeSafeIntegerSubtract: 1666 return VisitSpeculativeIntegerAdditiveOp(node, truncation, lowering); 1667 1668 case IrOpcode::kSpeculativeNumberAdd: 1669 case IrOpcode::kSpeculativeNumberSubtract: 1670 return VisitSpeculativeAdditiveOp(node, truncation, lowering); 1671 1672 case IrOpcode::kSpeculativeNumberLessThan: 1673 case IrOpcode::kSpeculativeNumberLessThanOrEqual: 1674 case IrOpcode::kSpeculativeNumberEqual: { 1675 // Number comparisons reduce to integer comparisons for integer inputs. 1676 if (TypeOf(node->InputAt(0)).Is(Type::Unsigned32()) && 1677 TypeOf(node->InputAt(1)).Is(Type::Unsigned32())) { 1678 // => unsigned Int32Cmp 1679 VisitBinop(node, UseInfo::TruncatingWord32(), 1680 MachineRepresentation::kBit); 1681 if (lower()) ChangeToPureOp(node, Uint32Op(node)); 1682 return; 1683 } else if (TypeOf(node->InputAt(0)).Is(Type::Signed32()) && 1684 TypeOf(node->InputAt(1)).Is(Type::Signed32())) { 1685 // => signed Int32Cmp 1686 VisitBinop(node, UseInfo::TruncatingWord32(), 1687 MachineRepresentation::kBit); 1688 if (lower()) ChangeToPureOp(node, Int32Op(node)); 1689 return; 1690 } 1691 // Try to use type feedback. 1692 NumberOperationHint hint = NumberOperationHintOf(node->op()); 1693 switch (hint) { 1694 case NumberOperationHint::kSigned32: 1695 case NumberOperationHint::kSignedSmall: 1696 if (propagate()) { 1697 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), 1698 MachineRepresentation::kBit); 1699 } else if (retype()) { 1700 SetOutput(node, MachineRepresentation::kBit, Type::Any()); 1701 } else { 1702 DCHECK(lower()); 1703 Node* lhs = node->InputAt(0); 1704 Node* rhs = node->InputAt(1); 1705 if (IsNodeRepresentationTagged(lhs) && 1706 IsNodeRepresentationTagged(rhs)) { 1707 VisitBinop( 1708 node, 1709 UseInfo::CheckedSignedSmallAsTaggedSigned(VectorSlotPair()), 1710 MachineRepresentation::kBit); 1711 ChangeToPureOp( 1712 node, changer_->TaggedSignedOperatorFor(node->opcode())); 1713 1714 } else { 1715 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), 1716 MachineRepresentation::kBit); 1717 ChangeToPureOp(node, Int32Op(node)); 1718 } 1719 } 1720 return; 1721 case NumberOperationHint::kSignedSmallInputs: 1722 // This doesn't make sense for compare operations. 1723 UNREACHABLE(); 1724 case NumberOperationHint::kNumberOrOddball: 1725 // Abstract and strict equality don't perform ToNumber conversions 1726 // on Oddballs, so make sure we don't accidentially sneak in a 1727 // hint with Oddball feedback here. 1728 DCHECK_NE(IrOpcode::kSpeculativeNumberEqual, node->opcode()); 1729 V8_FALLTHROUGH; 1730 case NumberOperationHint::kNumber: 1731 VisitBinop(node, 1732 CheckedUseInfoAsFloat64FromHint(hint, VectorSlotPair()), 1733 MachineRepresentation::kBit); 1734 if (lower()) ChangeToPureOp(node, Float64Op(node)); 1735 return; 1736 } 1737 UNREACHABLE(); 1738 return; 1739 } 1740 1741 case IrOpcode::kNumberAdd: 1742 case IrOpcode::kNumberSubtract: { 1743 if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) && 1744 (GetUpperBound(node).Is(Type::Signed32()) || 1745 GetUpperBound(node).Is(Type::Unsigned32()) || 1746 truncation.IsUsedAsWord32())) { 1747 // => Int32Add/Sub 1748 VisitWord32TruncatingBinop(node); 1749 if (lower()) ChangeToPureOp(node, Int32Op(node)); 1750 } else { 1751 // => Float64Add/Sub 1752 VisitFloat64Binop(node); 1753 if (lower()) ChangeToPureOp(node, Float64Op(node)); 1754 } 1755 return; 1756 } 1757 case IrOpcode::kSpeculativeNumberMultiply: { 1758 if (BothInputsAre(node, Type::Integral32()) && 1759 (NodeProperties::GetType(node).Is(Type::Signed32()) || 1760 NodeProperties::GetType(node).Is(Type::Unsigned32()) || 1761 (truncation.IsUsedAsWord32() && 1762 NodeProperties::GetType(node).Is( 1763 type_cache_.kSafeIntegerOrMinusZero)))) { 1764 // Multiply reduces to Int32Mul if the inputs are integers, and 1765 // (a) the output is either known to be Signed32, or 1766 // (b) the output is known to be Unsigned32, or 1767 // (c) the uses are truncating and the result is in the safe 1768 // integer range. 1769 VisitWord32TruncatingBinop(node); 1770 if (lower()) ChangeToPureOp(node, Int32Op(node)); 1771 return; 1772 } 1773 // Try to use type feedback. 1774 NumberOperationHint hint = NumberOperationHintOf(node->op()); 1775 Type input0_type = TypeOf(node->InputAt(0)); 1776 Type input1_type = TypeOf(node->InputAt(1)); 1777 1778 // Handle the case when no int32 checks on inputs are necessary 1779 // (but an overflow check is needed on the output). 1780 if (BothInputsAre(node, Type::Signed32())) { 1781 // If both inputs and feedback are int32, use the overflow op. 1782 if (hint == NumberOperationHint::kSignedSmall || 1783 hint == NumberOperationHint::kSigned32) { 1784 VisitBinop(node, UseInfo::TruncatingWord32(), 1785 MachineRepresentation::kWord32, Type::Signed32()); 1786 if (lower()) { 1787 LowerToCheckedInt32Mul(node, truncation, input0_type, 1788 input1_type); 1789 } 1790 return; 1791 } 1792 } 1793 1794 if (hint == NumberOperationHint::kSignedSmall || 1795 hint == NumberOperationHint::kSigned32) { 1796 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), 1797 MachineRepresentation::kWord32, Type::Signed32()); 1798 if (lower()) { 1799 LowerToCheckedInt32Mul(node, truncation, input0_type, input1_type); 1800 } 1801 return; 1802 } 1803 1804 // Checked float64 x float64 => float64 1805 VisitBinop(node, 1806 UseInfo::CheckedNumberOrOddballAsFloat64(VectorSlotPair()), 1807 MachineRepresentation::kFloat64, Type::Number()); 1808 if (lower()) ChangeToPureOp(node, Float64Op(node)); 1809 return; 1810 } 1811 case IrOpcode::kNumberMultiply: { 1812 if (BothInputsAre(node, Type::Integral32()) && 1813 (NodeProperties::GetType(node).Is(Type::Signed32()) || 1814 NodeProperties::GetType(node).Is(Type::Unsigned32()) || 1815 (truncation.IsUsedAsWord32() && 1816 NodeProperties::GetType(node).Is( 1817 type_cache_.kSafeIntegerOrMinusZero)))) { 1818 // Multiply reduces to Int32Mul if the inputs are integers, and 1819 // (a) the output is either known to be Signed32, or 1820 // (b) the output is known to be Unsigned32, or 1821 // (c) the uses are truncating and the result is in the safe 1822 // integer range. 1823 VisitWord32TruncatingBinop(node); 1824 if (lower()) ChangeToPureOp(node, Int32Op(node)); 1825 return; 1826 } 1827 // Number x Number => Float64Mul 1828 VisitFloat64Binop(node); 1829 if (lower()) ChangeToPureOp(node, Float64Op(node)); 1830 return; 1831 } 1832 case IrOpcode::kSpeculativeNumberDivide: { 1833 if (BothInputsAreUnsigned32(node) && truncation.IsUsedAsWord32()) { 1834 // => unsigned Uint32Div 1835 VisitWord32TruncatingBinop(node); 1836 if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); 1837 return; 1838 } 1839 if (BothInputsAreSigned32(node)) { 1840 if (NodeProperties::GetType(node).Is(Type::Signed32())) { 1841 // => signed Int32Div 1842 VisitWord32TruncatingBinop(node); 1843 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); 1844 return; 1845 } 1846 if (truncation.IsUsedAsWord32()) { 1847 // => signed Int32Div 1848 VisitWord32TruncatingBinop(node); 1849 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); 1850 return; 1851 } 1852 } 1853 1854 // Try to use type feedback. 1855 NumberOperationHint hint = NumberOperationHintOf(node->op()); 1856 1857 // Handle the case when no uint32 checks on inputs are necessary 1858 // (but an overflow check is needed on the output). 1859 if (BothInputsAreUnsigned32(node)) { 1860 if (hint == NumberOperationHint::kSignedSmall || 1861 hint == NumberOperationHint::kSigned32) { 1862 VisitBinop(node, UseInfo::TruncatingWord32(), 1863 MachineRepresentation::kWord32, Type::Unsigned32()); 1864 if (lower()) ChangeToUint32OverflowOp(node); 1865 return; 1866 } 1867 } 1868 1869 // Handle the case when no int32 checks on inputs are necessary 1870 // (but an overflow check is needed on the output). 1871 if (BothInputsAreSigned32(node)) { 1872 // If both the inputs the feedback are int32, use the overflow op. 1873 if (hint == NumberOperationHint::kSignedSmall || 1874 hint == NumberOperationHint::kSigned32) { 1875 VisitBinop(node, UseInfo::TruncatingWord32(), 1876 MachineRepresentation::kWord32, Type::Signed32()); 1877 if (lower()) ChangeToInt32OverflowOp(node); 1878 return; 1879 } 1880 } 1881 1882 if (hint == NumberOperationHint::kSigned32 || 1883 hint == NumberOperationHint::kSignedSmall || 1884 hint == NumberOperationHint::kSignedSmallInputs) { 1885 // If the result is truncated, we only need to check the inputs. 1886 if (truncation.IsUsedAsWord32()) { 1887 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), 1888 MachineRepresentation::kWord32); 1889 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); 1890 return; 1891 } else if (hint != NumberOperationHint::kSignedSmallInputs) { 1892 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), 1893 MachineRepresentation::kWord32, Type::Signed32()); 1894 if (lower()) ChangeToInt32OverflowOp(node); 1895 return; 1896 } 1897 } 1898 1899 // default case => Float64Div 1900 VisitBinop(node, 1901 UseInfo::CheckedNumberOrOddballAsFloat64(VectorSlotPair()), 1902 MachineRepresentation::kFloat64, Type::Number()); 1903 if (lower()) ChangeToPureOp(node, Float64Op(node)); 1904 return; 1905 } 1906 case IrOpcode::kNumberDivide: { 1907 if (BothInputsAreUnsigned32(node) && truncation.IsUsedAsWord32()) { 1908 // => unsigned Uint32Div 1909 VisitWord32TruncatingBinop(node); 1910 if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); 1911 return; 1912 } 1913 if (BothInputsAreSigned32(node)) { 1914 if (NodeProperties::GetType(node).Is(Type::Signed32())) { 1915 // => signed Int32Div 1916 VisitWord32TruncatingBinop(node); 1917 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); 1918 return; 1919 } 1920 if (truncation.IsUsedAsWord32()) { 1921 // => signed Int32Div 1922 VisitWord32TruncatingBinop(node); 1923 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); 1924 return; 1925 } 1926 } 1927 // Number x Number => Float64Div 1928 VisitFloat64Binop(node); 1929 if (lower()) ChangeToPureOp(node, Float64Op(node)); 1930 return; 1931 } 1932 case IrOpcode::kSpeculativeNumberModulus: 1933 return VisitSpeculativeNumberModulus(node, truncation, lowering); 1934 case IrOpcode::kNumberModulus: { 1935 if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) && 1936 (truncation.IsUsedAsWord32() || 1937 NodeProperties::GetType(node).Is(Type::Unsigned32()))) { 1938 // => unsigned Uint32Mod 1939 VisitWord32TruncatingBinop(node); 1940 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); 1941 return; 1942 } 1943 if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) && 1944 (truncation.IsUsedAsWord32() || 1945 NodeProperties::GetType(node).Is(Type::Signed32()))) { 1946 // => signed Int32Mod 1947 VisitWord32TruncatingBinop(node); 1948 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); 1949 return; 1950 } 1951 if (TypeOf(node->InputAt(0)).Is(Type::Unsigned32()) && 1952 TypeOf(node->InputAt(1)).Is(Type::Unsigned32()) && 1953 (truncation.IsUsedAsWord32() || 1954 NodeProperties::GetType(node).Is(Type::Unsigned32()))) { 1955 // We can only promise Float64 truncation here, as the decision is 1956 // based on the feedback types of the inputs. 1957 VisitBinop(node, UseInfo(MachineRepresentation::kWord32, 1958 Truncation::Float64()), 1959 MachineRepresentation::kWord32); 1960 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); 1961 return; 1962 } 1963 if (TypeOf(node->InputAt(0)).Is(Type::Signed32()) && 1964 TypeOf(node->InputAt(1)).Is(Type::Signed32()) && 1965 (truncation.IsUsedAsWord32() || 1966 NodeProperties::GetType(node).Is(Type::Signed32()))) { 1967 // We can only promise Float64 truncation here, as the decision is 1968 // based on the feedback types of the inputs. 1969 VisitBinop(node, UseInfo(MachineRepresentation::kWord32, 1970 Truncation::Float64()), 1971 MachineRepresentation::kWord32); 1972 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); 1973 return; 1974 } 1975 // default case => Float64Mod 1976 VisitFloat64Binop(node); 1977 if (lower()) ChangeToPureOp(node, Float64Op(node)); 1978 return; 1979 } 1980 case IrOpcode::kNumberBitwiseOr: 1981 case IrOpcode::kNumberBitwiseXor: 1982 case IrOpcode::kNumberBitwiseAnd: { 1983 VisitWord32TruncatingBinop(node); 1984 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); 1985 return; 1986 } 1987 case IrOpcode::kSpeculativeNumberBitwiseOr: 1988 case IrOpcode::kSpeculativeNumberBitwiseXor: 1989 case IrOpcode::kSpeculativeNumberBitwiseAnd: 1990 VisitSpeculativeInt32Binop(node); 1991 if (lower()) { 1992 ChangeToPureOp(node, Int32Op(node)); 1993 } 1994 return; 1995 case IrOpcode::kNumberShiftLeft: { 1996 Type rhs_type = GetUpperBound(node->InputAt(1)); 1997 VisitBinop(node, UseInfo::TruncatingWord32(), 1998 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); 1999 if (lower()) { 2000 lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type); 2001 } 2002 return; 2003 } 2004 case IrOpcode::kSpeculativeNumberShiftLeft: { 2005 if (BothInputsAre(node, Type::NumberOrOddball())) { 2006 Type rhs_type = GetUpperBound(node->InputAt(1)); 2007 VisitBinop(node, UseInfo::TruncatingWord32(), 2008 UseInfo::TruncatingWord32(), 2009 MachineRepresentation::kWord32); 2010 if (lower()) { 2011 lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type); 2012 } 2013 return; 2014 } 2015 NumberOperationHint hint = NumberOperationHintOf(node->op()); 2016 Type rhs_type = GetUpperBound(node->InputAt(1)); 2017 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), 2018 MachineRepresentation::kWord32, Type::Signed32()); 2019 if (lower()) { 2020 lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type); 2021 } 2022 return; 2023 } 2024 case IrOpcode::kNumberShiftRight: { 2025 Type rhs_type = GetUpperBound(node->InputAt(1)); 2026 VisitBinop(node, UseInfo::TruncatingWord32(), 2027 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); 2028 if (lower()) { 2029 lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type); 2030 } 2031 return; 2032 } 2033 case IrOpcode::kSpeculativeNumberShiftRight: { 2034 if (BothInputsAre(node, Type::NumberOrOddball())) { 2035 Type rhs_type = GetUpperBound(node->InputAt(1)); 2036 VisitBinop(node, UseInfo::TruncatingWord32(), 2037 UseInfo::TruncatingWord32(), 2038 MachineRepresentation::kWord32); 2039 if (lower()) { 2040 lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type); 2041 } 2042 return; 2043 } 2044 NumberOperationHint hint = NumberOperationHintOf(node->op()); 2045 Type rhs_type = GetUpperBound(node->InputAt(1)); 2046 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), 2047 MachineRepresentation::kWord32, Type::Signed32()); 2048 if (lower()) { 2049 lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type); 2050 } 2051 return; 2052 } 2053 case IrOpcode::kNumberShiftRightLogical: { 2054 Type rhs_type = GetUpperBound(node->InputAt(1)); 2055 VisitBinop(node, UseInfo::TruncatingWord32(), 2056 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); 2057 if (lower()) { 2058 lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type); 2059 } 2060 return; 2061 } 2062 case IrOpcode::kSpeculativeNumberShiftRightLogical: { 2063 NumberOperationHint hint = NumberOperationHintOf(node->op()); 2064 Type rhs_type = GetUpperBound(node->InputAt(1)); 2065 if (rhs_type.Is(type_cache_.kZeroish) && 2066 (hint == NumberOperationHint::kSignedSmall || 2067 hint == NumberOperationHint::kSigned32) && 2068 !truncation.IsUsedAsWord32()) { 2069 // The SignedSmall or Signed32 feedback means that the results that we 2070 // have seen so far were of type Unsigned31. We speculate that this 2071 // will continue to hold. Moreover, since the RHS is 0, the result 2072 // will just be the (converted) LHS. 2073 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), 2074 MachineRepresentation::kWord32, Type::Unsigned31()); 2075 if (lower()) { 2076 node->RemoveInput(1); 2077 NodeProperties::ChangeOp( 2078 node, simplified()->CheckedUint32ToInt32(VectorSlotPair())); 2079 } 2080 return; 2081 } 2082 if (BothInputsAre(node, Type::NumberOrOddball())) { 2083 VisitBinop(node, UseInfo::TruncatingWord32(), 2084 UseInfo::TruncatingWord32(), 2085 MachineRepresentation::kWord32); 2086 if (lower()) { 2087 lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type); 2088 } 2089 return; 2090 } 2091 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), 2092 MachineRepresentation::kWord32, Type::Unsigned32()); 2093 if (lower()) { 2094 lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type); 2095 } 2096 return; 2097 } 2098 case IrOpcode::kNumberAbs: { 2099 if (TypeOf(node->InputAt(0)).Is(Type::Unsigned32())) { 2100 VisitUnop(node, UseInfo::TruncatingWord32(), 2101 MachineRepresentation::kWord32); 2102 if (lower()) DeferReplacement(node, node->InputAt(0)); 2103 } else if (TypeOf(node->InputAt(0)).Is(Type::Signed32())) { 2104 VisitUnop(node, UseInfo::TruncatingWord32(), 2105 MachineRepresentation::kWord32); 2106 if (lower()) DeferReplacement(node, lowering->Int32Abs(node)); 2107 } else if (TypeOf(node->InputAt(0)) 2108 .Is(type_cache_.kPositiveIntegerOrMinusZeroOrNaN)) { 2109 VisitUnop(node, UseInfo::TruncatingFloat64(), 2110 MachineRepresentation::kFloat64); 2111 if (lower()) DeferReplacement(node, node->InputAt(0)); 2112 } else { 2113 VisitUnop(node, UseInfo::TruncatingFloat64(), 2114 MachineRepresentation::kFloat64); 2115 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); 2116 } 2117 return; 2118 } 2119 case IrOpcode::kNumberClz32: { 2120 VisitUnop(node, UseInfo::TruncatingWord32(), 2121 MachineRepresentation::kWord32); 2122 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); 2123 return; 2124 } 2125 case IrOpcode::kNumberImul: { 2126 VisitBinop(node, UseInfo::TruncatingWord32(), 2127 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); 2128 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); 2129 return; 2130 } 2131 case IrOpcode::kNumberFround: { 2132 VisitUnop(node, UseInfo::TruncatingFloat64(), 2133 MachineRepresentation::kFloat32); 2134 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); 2135 return; 2136 } 2137 case IrOpcode::kNumberMax: { 2138 // It is safe to use the feedback types for left and right hand side 2139 // here, since we can only narrow those types and thus we can only 2140 // promise a more specific truncation. 2141 Type const lhs_type = TypeOf(node->InputAt(0)); 2142 Type const rhs_type = TypeOf(node->InputAt(1)); 2143 if (lhs_type.Is(Type::Unsigned32()) && 2144 rhs_type.Is(Type::Unsigned32())) { 2145 VisitWord32TruncatingBinop(node); 2146 if (lower()) { 2147 lowering->DoMax(node, lowering->machine()->Uint32LessThan(), 2148 MachineRepresentation::kWord32); 2149 } 2150 } else if (lhs_type.Is(Type::Signed32()) && 2151 rhs_type.Is(Type::Signed32())) { 2152 VisitWord32TruncatingBinop(node); 2153 if (lower()) { 2154 lowering->DoMax(node, lowering->machine()->Int32LessThan(), 2155 MachineRepresentation::kWord32); 2156 } 2157 } else if (lhs_type.Is(Type::PlainNumber()) && 2158 rhs_type.Is(Type::PlainNumber())) { 2159 VisitFloat64Binop(node); 2160 if (lower()) { 2161 lowering->DoMax(node, lowering->machine()->Float64LessThan(), 2162 MachineRepresentation::kFloat64); 2163 } 2164 } else { 2165 VisitFloat64Binop(node); 2166 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); 2167 } 2168 return; 2169 } 2170 case IrOpcode::kNumberMin: { 2171 // It is safe to use the feedback types for left and right hand side 2172 // here, since we can only narrow those types and thus we can only 2173 // promise a more specific truncation. 2174 Type const lhs_type = TypeOf(node->InputAt(0)); 2175 Type const rhs_type = TypeOf(node->InputAt(1)); 2176 if (lhs_type.Is(Type::Unsigned32()) && 2177 rhs_type.Is(Type::Unsigned32())) { 2178 VisitWord32TruncatingBinop(node); 2179 if (lower()) { 2180 lowering->DoMin(node, lowering->machine()->Uint32LessThan(), 2181 MachineRepresentation::kWord32); 2182 } 2183 } else if (lhs_type.Is(Type::Signed32()) && 2184 rhs_type.Is(Type::Signed32())) { 2185 VisitWord32TruncatingBinop(node); 2186 if (lower()) { 2187 lowering->DoMin(node, lowering->machine()->Int32LessThan(), 2188 MachineRepresentation::kWord32); 2189 } 2190 } else if (lhs_type.Is(Type::PlainNumber()) && 2191 rhs_type.Is(Type::PlainNumber())) { 2192 VisitFloat64Binop(node); 2193 if (lower()) { 2194 lowering->DoMin(node, lowering->machine()->Float64LessThan(), 2195 MachineRepresentation::kFloat64); 2196 } 2197 } else { 2198 VisitFloat64Binop(node); 2199 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); 2200 } 2201 return; 2202 } 2203 case IrOpcode::kNumberAtan2: 2204 case IrOpcode::kNumberPow: { 2205 VisitBinop(node, UseInfo::TruncatingFloat64(), 2206 MachineRepresentation::kFloat64); 2207 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); 2208 return; 2209 } 2210 case IrOpcode::kNumberAcos: 2211 case IrOpcode::kNumberAcosh: 2212 case IrOpcode::kNumberAsin: 2213 case IrOpcode::kNumberAsinh: 2214 case IrOpcode::kNumberAtan: 2215 case IrOpcode::kNumberAtanh: 2216 case IrOpcode::kNumberCeil: 2217 case IrOpcode::kNumberCos: 2218 case IrOpcode::kNumberCosh: 2219 case IrOpcode::kNumberExp: 2220 case IrOpcode::kNumberExpm1: 2221 case IrOpcode::kNumberFloor: 2222 case IrOpcode::kNumberLog: 2223 case IrOpcode::kNumberLog1p: 2224 case IrOpcode::kNumberLog2: 2225 case IrOpcode::kNumberLog10: 2226 case IrOpcode::kNumberCbrt: 2227 case IrOpcode::kNumberSin: 2228 case IrOpcode::kNumberSinh: 2229 case IrOpcode::kNumberTan: 2230 case IrOpcode::kNumberTanh: 2231 case IrOpcode::kNumberTrunc: { 2232 VisitUnop(node, UseInfo::TruncatingFloat64(), 2233 MachineRepresentation::kFloat64); 2234 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); 2235 return; 2236 } 2237 case IrOpcode::kNumberRound: { 2238 VisitUnop(node, UseInfo::TruncatingFloat64(), 2239 MachineRepresentation::kFloat64); 2240 if (lower()) DeferReplacement(node, lowering->Float64Round(node)); 2241 return; 2242 } 2243 case IrOpcode::kNumberSign: { 2244 if (InputIs(node, Type::Signed32())) { 2245 VisitUnop(node, UseInfo::TruncatingWord32(), 2246 MachineRepresentation::kWord32); 2247 if (lower()) DeferReplacement(node, lowering->Int32Sign(node)); 2248 } else { 2249 VisitUnop(node, UseInfo::TruncatingFloat64(), 2250 MachineRepresentation::kFloat64); 2251 if (lower()) DeferReplacement(node, lowering->Float64Sign(node)); 2252 } 2253 return; 2254 } 2255 case IrOpcode::kNumberSqrt: { 2256 VisitUnop(node, UseInfo::TruncatingFloat64(), 2257 MachineRepresentation::kFloat64); 2258 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); 2259 return; 2260 } 2261 case IrOpcode::kNumberToBoolean: { 2262 Type const input_type = TypeOf(node->InputAt(0)); 2263 if (input_type.Is(Type::Integral32())) { 2264 VisitUnop(node, UseInfo::TruncatingWord32(), 2265 MachineRepresentation::kBit); 2266 if (lower()) lowering->DoIntegral32ToBit(node); 2267 } else if (input_type.Is(Type::OrderedNumber())) { 2268 VisitUnop(node, UseInfo::TruncatingFloat64(), 2269 MachineRepresentation::kBit); 2270 if (lower()) lowering->DoOrderedNumberToBit(node); 2271 } else { 2272 VisitUnop(node, UseInfo::TruncatingFloat64(), 2273 MachineRepresentation::kBit); 2274 if (lower()) lowering->DoNumberToBit(node); 2275 } 2276 return; 2277 } 2278 case IrOpcode::kNumberToInt32: { 2279 // Just change representation if necessary. 2280 VisitUnop(node, UseInfo::TruncatingWord32(), 2281 MachineRepresentation::kWord32); 2282 if (lower()) DeferReplacement(node, node->InputAt(0)); 2283 return; 2284 } 2285 case IrOpcode::kNumberToString: { 2286 VisitUnop(node, UseInfo::AnyTagged(), 2287 MachineRepresentation::kTaggedPointer); 2288 return; 2289 } 2290 case IrOpcode::kNumberToUint32: { 2291 // Just change representation if necessary. 2292 VisitUnop(node, UseInfo::TruncatingWord32(), 2293 MachineRepresentation::kWord32); 2294 if (lower()) DeferReplacement(node, node->InputAt(0)); 2295 return; 2296 } 2297 case IrOpcode::kNumberToUint8Clamped: { 2298 Type const input_type = TypeOf(node->InputAt(0)); 2299 if (input_type.Is(type_cache_.kUint8OrMinusZeroOrNaN)) { 2300 VisitUnop(node, UseInfo::TruncatingWord32(), 2301 MachineRepresentation::kWord32); 2302 if (lower()) DeferReplacement(node, node->InputAt(0)); 2303 } else if (input_type.Is(Type::Unsigned32OrMinusZeroOrNaN())) { 2304 VisitUnop(node, UseInfo::TruncatingWord32(), 2305 MachineRepresentation::kWord32); 2306 if (lower()) lowering->DoUnsigned32ToUint8Clamped(node); 2307 } else if (input_type.Is(Type::Signed32OrMinusZeroOrNaN())) { 2308 VisitUnop(node, UseInfo::TruncatingWord32(), 2309 MachineRepresentation::kWord32); 2310 if (lower()) lowering->DoSigned32ToUint8Clamped(node); 2311 } else if (input_type.Is(type_cache_.kIntegerOrMinusZeroOrNaN)) { 2312 VisitUnop(node, UseInfo::TruncatingFloat64(), 2313 MachineRepresentation::kFloat64); 2314 if (lower()) lowering->DoIntegerToUint8Clamped(node); 2315 } else { 2316 VisitUnop(node, UseInfo::TruncatingFloat64(), 2317 MachineRepresentation::kFloat64); 2318 if (lower()) lowering->DoNumberToUint8Clamped(node); 2319 } 2320 return; 2321 } 2322 case IrOpcode::kReferenceEqual: { 2323 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 2324 if (lower()) { 2325 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); 2326 } 2327 return; 2328 } 2329 case IrOpcode::kSameValue: { 2330 if (truncation.IsUnused()) return VisitUnused(node); 2331 VisitBinop(node, UseInfo::AnyTagged(), 2332 MachineRepresentation::kTaggedPointer); 2333 return; 2334 } 2335 case IrOpcode::kTypeOf: { 2336 return VisitUnop(node, UseInfo::AnyTagged(), 2337 MachineRepresentation::kTaggedPointer); 2338 } 2339 case IrOpcode::kNewConsString: { 2340 ProcessInput(node, 0, UseInfo::TaggedSigned()); // length 2341 ProcessInput(node, 1, UseInfo::AnyTagged()); // first 2342 ProcessInput(node, 2, UseInfo::AnyTagged()); // second 2343 SetOutput(node, MachineRepresentation::kTaggedPointer); 2344 return; 2345 } 2346 case IrOpcode::kStringEqual: 2347 case IrOpcode::kStringLessThan: 2348 case IrOpcode::kStringLessThanOrEqual: { 2349 return VisitBinop(node, UseInfo::AnyTagged(), 2350 MachineRepresentation::kTaggedPointer); 2351 } 2352 case IrOpcode::kStringCharCodeAt: { 2353 return VisitBinop(node, UseInfo::AnyTagged(), 2354 UseInfo::TruncatingWord32(), 2355 MachineRepresentation::kWord32); 2356 } 2357 case IrOpcode::kStringCodePointAt: { 2358 return VisitBinop(node, UseInfo::AnyTagged(), 2359 UseInfo::TruncatingWord32(), 2360 MachineRepresentation::kTaggedSigned); 2361 } 2362 case IrOpcode::kStringFromSingleCharCode: { 2363 VisitUnop(node, UseInfo::TruncatingWord32(), 2364 MachineRepresentation::kTaggedPointer); 2365 return; 2366 } 2367 case IrOpcode::kStringFromSingleCodePoint: { 2368 VisitUnop(node, UseInfo::TruncatingWord32(), 2369 MachineRepresentation::kTaggedPointer); 2370 return; 2371 } 2372 case IrOpcode::kStringIndexOf: { 2373 ProcessInput(node, 0, UseInfo::AnyTagged()); 2374 ProcessInput(node, 1, UseInfo::AnyTagged()); 2375 ProcessInput(node, 2, UseInfo::TaggedSigned()); 2376 SetOutput(node, MachineRepresentation::kTaggedSigned); 2377 return; 2378 } 2379 case IrOpcode::kStringLength: { 2380 // TODO(bmeurer): The input representation should be TaggedPointer. 2381 // Fix this once we have a dedicated StringConcat/JSStringAdd 2382 // operator, which marks it's output as TaggedPointer properly. 2383 VisitUnop(node, UseInfo::AnyTagged(), 2384 MachineRepresentation::kTaggedSigned); 2385 return; 2386 } 2387 case IrOpcode::kStringSubstring: { 2388 ProcessInput(node, 0, UseInfo::AnyTagged()); 2389 ProcessInput(node, 1, UseInfo::TruncatingWord32()); 2390 ProcessInput(node, 2, UseInfo::TruncatingWord32()); 2391 ProcessRemainingInputs(node, 3); 2392 SetOutput(node, MachineRepresentation::kTaggedPointer); 2393 return; 2394 } 2395 case IrOpcode::kStringToLowerCaseIntl: 2396 case IrOpcode::kStringToUpperCaseIntl: { 2397 VisitUnop(node, UseInfo::AnyTagged(), 2398 MachineRepresentation::kTaggedPointer); 2399 return; 2400 } 2401 case IrOpcode::kCheckBounds: { 2402 const CheckParameters& p = CheckParametersOf(node->op()); 2403 Type index_type = TypeOf(node->InputAt(0)); 2404 Type length_type = TypeOf(node->InputAt(1)); 2405 if (index_type.Is(Type::Integral32OrMinusZero())) { 2406 // Map -0 to 0, and the values in the [-2^31,-1] range to the 2407 // [2^31,2^32-1] range, which will be considered out-of-bounds 2408 // as well, because the {length_type} is limited to Unsigned31. 2409 VisitBinop(node, UseInfo::TruncatingWord32(), 2410 MachineRepresentation::kWord32); 2411 if (lower() && lowering->poisoning_level_ == 2412 PoisoningMitigationLevel::kDontPoison) { 2413 if (index_type.IsNone() || length_type.IsNone() || 2414 (index_type.Min() >= 0.0 && 2415 index_type.Max() < length_type.Min())) { 2416 // The bounds check is redundant if we already know that 2417 // the index is within the bounds of [0.0, length[. 2418 DeferReplacement(node, node->InputAt(0)); 2419 } 2420 } 2421 } else { 2422 VisitBinop( 2423 node, 2424 UseInfo::CheckedSigned32AsWord32(kIdentifyZeros, p.feedback()), 2425 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); 2426 } 2427 return; 2428 } 2429 case IrOpcode::kPoisonIndex: { 2430 VisitUnop(node, UseInfo::TruncatingWord32(), 2431 MachineRepresentation::kWord32); 2432 return; 2433 } 2434 case IrOpcode::kCheckHeapObject: { 2435 if (InputCannotBe(node, Type::SignedSmall())) { 2436 VisitUnop(node, UseInfo::AnyTagged(), 2437 MachineRepresentation::kTaggedPointer); 2438 } else { 2439 VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(), 2440 MachineRepresentation::kTaggedPointer); 2441 } 2442 if (lower()) DeferReplacement(node, node->InputAt(0)); 2443 return; 2444 } 2445 case IrOpcode::kCheckIf: { 2446 ProcessInput(node, 0, UseInfo::Bool()); 2447 ProcessRemainingInputs(node, 1); 2448 SetOutput(node, MachineRepresentation::kNone); 2449 return; 2450 } 2451 case IrOpcode::kCheckInternalizedString: { 2452 VisitCheck(node, Type::InternalizedString(), lowering); 2453 return; 2454 } 2455 case IrOpcode::kCheckNumber: { 2456 Type const input_type = TypeOf(node->InputAt(0)); 2457 if (input_type.Is(Type::Number())) { 2458 VisitNoop(node, truncation); 2459 } else { 2460 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); 2461 } 2462 return; 2463 } 2464 case IrOpcode::kCheckReceiver: { 2465 VisitCheck(node, Type::Receiver(), lowering); 2466 return; 2467 } 2468 case IrOpcode::kCheckSmi: { 2469 const CheckParameters& params = CheckParametersOf(node->op()); 2470 if (SmiValuesAre32Bits() && truncation.IsUsedAsWord32()) { 2471 VisitUnop(node, 2472 UseInfo::CheckedSignedSmallAsWord32(kDistinguishZeros, 2473 params.feedback()), 2474 MachineRepresentation::kWord32); 2475 } else { 2476 VisitUnop( 2477 node, 2478 UseInfo::CheckedSignedSmallAsTaggedSigned(params.feedback()), 2479 MachineRepresentation::kTaggedSigned); 2480 } 2481 if (lower()) DeferReplacement(node, node->InputAt(0)); 2482 return; 2483 } 2484 case IrOpcode::kCheckString: { 2485 VisitCheck(node, Type::String(), lowering); 2486 return; 2487 } 2488 case IrOpcode::kCheckSymbol: { 2489 VisitCheck(node, Type::Symbol(), lowering); 2490 return; 2491 } 2492 2493 case IrOpcode::kAllocate: { 2494 ProcessInput(node, 0, UseInfo::TruncatingWord32()); 2495 ProcessRemainingInputs(node, 1); 2496 SetOutput(node, MachineRepresentation::kTaggedPointer); 2497 return; 2498 } 2499 case IrOpcode::kLoadFieldByIndex: { 2500 if (truncation.IsUnused()) return VisitUnused(node); 2501 VisitBinop(node, UseInfo::AnyTagged(), UseInfo::TruncatingWord32(), 2502 MachineRepresentation::kTagged); 2503 return; 2504 } 2505 case IrOpcode::kLoadField: { 2506 if (truncation.IsUnused()) return VisitUnused(node); 2507 FieldAccess access = FieldAccessOf(node->op()); 2508 MachineRepresentation const representation = 2509 access.machine_type.representation(); 2510 VisitUnop(node, UseInfoForBasePointer(access), representation); 2511 return; 2512 } 2513 case IrOpcode::kStoreField: { 2514 FieldAccess access = FieldAccessOf(node->op()); 2515 Node* value_node = node->InputAt(1); 2516 NodeInfo* input_info = GetInfo(value_node); 2517 MachineRepresentation field_representation = 2518 access.machine_type.representation(); 2519 2520 // Convert to Smi if possible, such that we can avoid a write barrier. 2521 if (field_representation == MachineRepresentation::kTagged && 2522 TypeOf(value_node).Is(Type::SignedSmall())) { 2523 field_representation = MachineRepresentation::kTaggedSigned; 2524 } 2525 WriteBarrierKind write_barrier_kind = WriteBarrierKindFor( 2526 access.base_is_tagged, field_representation, access.offset, 2527 access.type, input_info->representation(), value_node); 2528 2529 ProcessInput(node, 0, UseInfoForBasePointer(access)); 2530 ProcessInput(node, 1, 2531 TruncatingUseInfoFromRepresentation(field_representation)); 2532 ProcessRemainingInputs(node, 2); 2533 SetOutput(node, MachineRepresentation::kNone); 2534 if (lower()) { 2535 if (write_barrier_kind < access.write_barrier_kind) { 2536 access.write_barrier_kind = write_barrier_kind; 2537 NodeProperties::ChangeOp( 2538 node, jsgraph_->simplified()->StoreField(access)); 2539 } 2540 } 2541 return; 2542 } 2543 case IrOpcode::kLoadElement: { 2544 if (truncation.IsUnused()) return VisitUnused(node); 2545 ElementAccess access = ElementAccessOf(node->op()); 2546 VisitBinop(node, UseInfoForBasePointer(access), 2547 UseInfo::TruncatingWord32(), 2548 access.machine_type.representation()); 2549 return; 2550 } 2551 case IrOpcode::kStoreElement: { 2552 ElementAccess access = ElementAccessOf(node->op()); 2553 Node* value_node = node->InputAt(2); 2554 NodeInfo* input_info = GetInfo(value_node); 2555 MachineRepresentation element_representation = 2556 access.machine_type.representation(); 2557 2558 // Convert to Smi if possible, such that we can avoid a write barrier. 2559 if (element_representation == MachineRepresentation::kTagged && 2560 TypeOf(value_node).Is(Type::SignedSmall())) { 2561 element_representation = MachineRepresentation::kTaggedSigned; 2562 } 2563 WriteBarrierKind write_barrier_kind = WriteBarrierKindFor( 2564 access.base_is_tagged, element_representation, access.type, 2565 input_info->representation(), value_node); 2566 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base 2567 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index 2568 ProcessInput(node, 2, 2569 TruncatingUseInfoFromRepresentation( 2570 element_representation)); // value 2571 ProcessRemainingInputs(node, 3); 2572 SetOutput(node, MachineRepresentation::kNone); 2573 if (lower()) { 2574 if (write_barrier_kind < access.write_barrier_kind) { 2575 access.write_barrier_kind = write_barrier_kind; 2576 NodeProperties::ChangeOp( 2577 node, jsgraph_->simplified()->StoreElement(access)); 2578 } 2579 } 2580 return; 2581 } 2582 case IrOpcode::kNumberIsFloat64Hole: { 2583 VisitUnop(node, UseInfo::TruncatingFloat64(), 2584 MachineRepresentation::kBit); 2585 return; 2586 } 2587 case IrOpcode::kTransitionAndStoreElement: { 2588 Type value_type = TypeOf(node->InputAt(2)); 2589 2590 ProcessInput(node, 0, UseInfo::AnyTagged()); // array 2591 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index 2592 2593 if (value_type.Is(Type::SignedSmall())) { 2594 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // value 2595 if (lower()) { 2596 NodeProperties::ChangeOp(node, 2597 simplified()->StoreSignedSmallElement()); 2598 } 2599 } else if (value_type.Is(Type::Number())) { 2600 ProcessInput(node, 2, UseInfo::TruncatingFloat64()); // value 2601 if (lower()) { 2602 Handle<Map> double_map = DoubleMapParameterOf(node->op()); 2603 NodeProperties::ChangeOp( 2604 node, 2605 simplified()->TransitionAndStoreNumberElement(double_map)); 2606 } 2607 } else if (value_type.Is(Type::NonNumber())) { 2608 ProcessInput(node, 2, UseInfo::AnyTagged()); // value 2609 if (lower()) { 2610 Handle<Map> fast_map = FastMapParameterOf(node->op()); 2611 NodeProperties::ChangeOp( 2612 node, simplified()->TransitionAndStoreNonNumberElement( 2613 fast_map, value_type)); 2614 } 2615 } else { 2616 ProcessInput(node, 2, UseInfo::AnyTagged()); // value 2617 } 2618 2619 ProcessRemainingInputs(node, 3); 2620 SetOutput(node, MachineRepresentation::kNone); 2621 return; 2622 } 2623 case IrOpcode::kLoadTypedElement: { 2624 MachineRepresentation const rep = 2625 MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op())); 2626 ProcessInput(node, 0, UseInfo::AnyTagged()); // buffer 2627 ProcessInput(node, 1, UseInfo::AnyTagged()); // base pointer 2628 ProcessInput(node, 2, UseInfo::PointerInt()); // external pointer 2629 ProcessInput(node, 3, UseInfo::TruncatingWord32()); // index 2630 ProcessRemainingInputs(node, 4); 2631 SetOutput(node, rep); 2632 return; 2633 } 2634 case IrOpcode::kLoadDataViewElement: { 2635 MachineRepresentation const rep = 2636 MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op())); 2637 ProcessInput(node, 0, UseInfo::AnyTagged()); // buffer 2638 ProcessInput(node, 1, UseInfo::PointerInt()); // external pointer 2639 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // index 2640 ProcessInput(node, 3, UseInfo::Bool()); // little-endian 2641 ProcessRemainingInputs(node, 4); 2642 SetOutput(node, rep); 2643 return; 2644 } 2645 case IrOpcode::kStoreTypedElement: { 2646 MachineRepresentation const rep = 2647 MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op())); 2648 ProcessInput(node, 0, UseInfo::AnyTagged()); // buffer 2649 ProcessInput(node, 1, UseInfo::AnyTagged()); // base pointer 2650 ProcessInput(node, 2, UseInfo::PointerInt()); // external pointer 2651 ProcessInput(node, 3, UseInfo::TruncatingWord32()); // index 2652 ProcessInput(node, 4, 2653 TruncatingUseInfoFromRepresentation(rep)); // value 2654 ProcessRemainingInputs(node, 5); 2655 SetOutput(node, MachineRepresentation::kNone); 2656 return; 2657 } 2658 case IrOpcode::kStoreDataViewElement: { 2659 MachineRepresentation const rep = 2660 MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op())); 2661 ProcessInput(node, 0, UseInfo::AnyTagged()); // buffer 2662 ProcessInput(node, 1, UseInfo::PointerInt()); // external pointer 2663 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // index 2664 ProcessInput(node, 3, 2665 TruncatingUseInfoFromRepresentation(rep)); // value 2666 ProcessInput(node, 4, UseInfo::Bool()); // little-endian 2667 ProcessRemainingInputs(node, 5); 2668 SetOutput(node, MachineRepresentation::kNone); 2669 return; 2670 } 2671 case IrOpcode::kConvertReceiver: { 2672 Type input_type = TypeOf(node->InputAt(0)); 2673 VisitBinop(node, UseInfo::AnyTagged(), 2674 MachineRepresentation::kTaggedPointer); 2675 if (lower()) { 2676 // Try to optimize the {node} based on the input type. 2677 if (input_type.Is(Type::Receiver())) { 2678 DeferReplacement(node, node->InputAt(0)); 2679 } else if (input_type.Is(Type::NullOrUndefined())) { 2680 DeferReplacement(node, node->InputAt(1)); 2681 } else if (!input_type.Maybe(Type::NullOrUndefined())) { 2682 NodeProperties::ChangeOp( 2683 node, lowering->simplified()->ConvertReceiver( 2684 ConvertReceiverMode::kNotNullOrUndefined)); 2685 } 2686 } 2687 return; 2688 } 2689 case IrOpcode::kPlainPrimitiveToNumber: { 2690 if (InputIs(node, Type::Boolean())) { 2691 VisitUnop(node, UseInfo::Bool(), MachineRepresentation::kWord32); 2692 if (lower()) DeferReplacement(node, node->InputAt(0)); 2693 } else if (InputIs(node, Type::String())) { 2694 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); 2695 if (lower()) { 2696 NodeProperties::ChangeOp(node, simplified()->StringToNumber()); 2697 } 2698 } else if (truncation.IsUsedAsWord32()) { 2699 if (InputIs(node, Type::NumberOrOddball())) { 2700 VisitUnop(node, UseInfo::TruncatingWord32(), 2701 MachineRepresentation::kWord32); 2702 if (lower()) DeferReplacement(node, node->InputAt(0)); 2703 } else { 2704 VisitUnop(node, UseInfo::AnyTagged(), 2705 MachineRepresentation::kWord32); 2706 if (lower()) { 2707 NodeProperties::ChangeOp(node, 2708 simplified()->PlainPrimitiveToWord32()); 2709 } 2710 } 2711 } else if (truncation.IsUsedAsFloat64()) { 2712 if (InputIs(node, Type::NumberOrOddball())) { 2713 VisitUnop(node, UseInfo::TruncatingFloat64(), 2714 MachineRepresentation::kFloat64); 2715 if (lower()) DeferReplacement(node, node->InputAt(0)); 2716 } else { 2717 VisitUnop(node, UseInfo::AnyTagged(), 2718 MachineRepresentation::kFloat64); 2719 if (lower()) { 2720 NodeProperties::ChangeOp(node, 2721 simplified()->PlainPrimitiveToFloat64()); 2722 } 2723 } 2724 } else { 2725 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); 2726 } 2727 return; 2728 } 2729 case IrOpcode::kSpeculativeToNumber: { 2730 NumberOperationParameters const& p = 2731 NumberOperationParametersOf(node->op()); 2732 switch (p.hint()) { 2733 case NumberOperationHint::kSigned32: 2734 case NumberOperationHint::kSignedSmall: 2735 case NumberOperationHint::kSignedSmallInputs: 2736 VisitUnop(node, 2737 CheckedUseInfoAsWord32FromHint(p.hint(), p.feedback()), 2738 MachineRepresentation::kWord32, Type::Signed32()); 2739 break; 2740 case NumberOperationHint::kNumber: 2741 case NumberOperationHint::kNumberOrOddball: 2742 VisitUnop(node, 2743 CheckedUseInfoAsFloat64FromHint(p.hint(), p.feedback()), 2744 MachineRepresentation::kFloat64); 2745 break; 2746 } 2747 if (lower()) DeferReplacement(node, node->InputAt(0)); 2748 return; 2749 } 2750 case IrOpcode::kObjectIsArrayBufferView: { 2751 // TODO(turbofan): Introduce a Type::ArrayBufferView? 2752 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 2753 return; 2754 } 2755 case IrOpcode::kObjectIsBigInt: { 2756 VisitObjectIs(node, Type::BigInt(), lowering); 2757 return; 2758 } 2759 case IrOpcode::kObjectIsCallable: { 2760 VisitObjectIs(node, Type::Callable(), lowering); 2761 return; 2762 } 2763 case IrOpcode::kObjectIsConstructor: { 2764 // TODO(turbofan): Introduce a Type::Constructor? 2765 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 2766 return; 2767 } 2768 case IrOpcode::kObjectIsDetectableCallable: { 2769 VisitObjectIs(node, Type::DetectableCallable(), lowering); 2770 return; 2771 } 2772 case IrOpcode::kObjectIsFiniteNumber: { 2773 Type const input_type = GetUpperBound(node->InputAt(0)); 2774 if (input_type.Is(type_cache_.kSafeInteger)) { 2775 VisitUnop(node, UseInfo::None(), MachineRepresentation::kBit); 2776 if (lower()) { 2777 DeferReplacement(node, lowering->jsgraph()->Int32Constant(1)); 2778 } 2779 } else if (!input_type.Maybe(Type::Number())) { 2780 VisitUnop(node, UseInfo::Any(), MachineRepresentation::kBit); 2781 if (lower()) { 2782 DeferReplacement(node, lowering->jsgraph()->Int32Constant(0)); 2783 } 2784 } else if (input_type.Is(Type::Number())) { 2785 VisitUnop(node, UseInfo::TruncatingFloat64(), 2786 MachineRepresentation::kBit); 2787 if (lower()) { 2788 NodeProperties::ChangeOp(node, 2789 lowering->simplified()->NumberIsFinite()); 2790 } 2791 } else { 2792 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 2793 } 2794 return; 2795 } 2796 case IrOpcode::kNumberIsFinite: { 2797 VisitUnop(node, UseInfo::TruncatingFloat64(), 2798 MachineRepresentation::kBit); 2799 return; 2800 } 2801 case IrOpcode::kObjectIsSafeInteger: { 2802 Type const input_type = GetUpperBound(node->InputAt(0)); 2803 if (input_type.Is(type_cache_.kSafeInteger)) { 2804 VisitUnop(node, UseInfo::None(), MachineRepresentation::kBit); 2805 if (lower()) { 2806 DeferReplacement(node, lowering->jsgraph()->Int32Constant(1)); 2807 } 2808 } else if (!input_type.Maybe(Type::Number())) { 2809 VisitUnop(node, UseInfo::Any(), MachineRepresentation::kBit); 2810 if (lower()) { 2811 DeferReplacement(node, lowering->jsgraph()->Int32Constant(0)); 2812 } 2813 } else if (input_type.Is(Type::Number())) { 2814 VisitUnop(node, UseInfo::TruncatingFloat64(), 2815 MachineRepresentation::kBit); 2816 if (lower()) { 2817 NodeProperties::ChangeOp( 2818 node, lowering->simplified()->NumberIsSafeInteger()); 2819 } 2820 } else { 2821 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 2822 } 2823 return; 2824 } 2825 case IrOpcode::kNumberIsSafeInteger: { 2826 UNREACHABLE(); 2827 } 2828 case IrOpcode::kObjectIsInteger: { 2829 Type const input_type = GetUpperBound(node->InputAt(0)); 2830 if (input_type.Is(type_cache_.kSafeInteger)) { 2831 VisitUnop(node, UseInfo::None(), MachineRepresentation::kBit); 2832 if (lower()) { 2833 DeferReplacement(node, lowering->jsgraph()->Int32Constant(1)); 2834 } 2835 } else if (!input_type.Maybe(Type::Number())) { 2836 VisitUnop(node, UseInfo::Any(), MachineRepresentation::kBit); 2837 if (lower()) { 2838 DeferReplacement(node, lowering->jsgraph()->Int32Constant(0)); 2839 } 2840 } else if (input_type.Is(Type::Number())) { 2841 VisitUnop(node, UseInfo::TruncatingFloat64(), 2842 MachineRepresentation::kBit); 2843 if (lower()) { 2844 NodeProperties::ChangeOp(node, 2845 lowering->simplified()->NumberIsInteger()); 2846 } 2847 } else { 2848 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 2849 } 2850 return; 2851 } 2852 case IrOpcode::kNumberIsInteger: { 2853 VisitUnop(node, UseInfo::TruncatingFloat64(), 2854 MachineRepresentation::kBit); 2855 return; 2856 } 2857 case IrOpcode::kObjectIsMinusZero: { 2858 Type const input_type = GetUpperBound(node->InputAt(0)); 2859 if (input_type.Is(Type::MinusZero())) { 2860 VisitUnop(node, UseInfo::None(), MachineRepresentation::kBit); 2861 if (lower()) { 2862 DeferReplacement(node, lowering->jsgraph()->Int32Constant(1)); 2863 } 2864 } else if (!input_type.Maybe(Type::MinusZero())) { 2865 VisitUnop(node, UseInfo::Any(), MachineRepresentation::kBit); 2866 if (lower()) { 2867 DeferReplacement(node, lowering->jsgraph()->Int32Constant(0)); 2868 } 2869 } else if (input_type.Is(Type::Number())) { 2870 VisitUnop(node, UseInfo::TruncatingFloat64(), 2871 MachineRepresentation::kBit); 2872 if (lower()) { 2873 // ObjectIsMinusZero(x:kRepFloat64) 2874 // => Float64Equal(Float64Div(1.0,x),-Infinity) 2875 Node* const input = node->InputAt(0); 2876 node->ReplaceInput( 2877 0, jsgraph_->graph()->NewNode( 2878 lowering->machine()->Float64Div(), 2879 lowering->jsgraph()->Float64Constant(1.0), input)); 2880 node->AppendInput(jsgraph_->zone(), 2881 jsgraph_->Float64Constant( 2882 -std::numeric_limits<double>::infinity())); 2883 NodeProperties::ChangeOp(node, lowering->machine()->Float64Equal()); 2884 } 2885 } else { 2886 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 2887 } 2888 return; 2889 } 2890 case IrOpcode::kObjectIsNaN: { 2891 Type const input_type = GetUpperBound(node->InputAt(0)); 2892 if (input_type.Is(Type::NaN())) { 2893 VisitUnop(node, UseInfo::None(), MachineRepresentation::kBit); 2894 if (lower()) { 2895 DeferReplacement(node, lowering->jsgraph()->Int32Constant(1)); 2896 } 2897 } else if (!input_type.Maybe(Type::NaN())) { 2898 VisitUnop(node, UseInfo::Any(), MachineRepresentation::kBit); 2899 if (lower()) { 2900 DeferReplacement(node, lowering->jsgraph()->Int32Constant(0)); 2901 } 2902 } else if (input_type.Is(Type::Number())) { 2903 VisitUnop(node, UseInfo::TruncatingFloat64(), 2904 MachineRepresentation::kBit); 2905 if (lower()) { 2906 NodeProperties::ChangeOp(node, simplified()->NumberIsNaN()); 2907 } 2908 } else { 2909 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 2910 } 2911 return; 2912 } 2913 case IrOpcode::kNumberIsNaN: { 2914 VisitUnop(node, UseInfo::TruncatingFloat64(), 2915 MachineRepresentation::kBit); 2916 return; 2917 } 2918 case IrOpcode::kObjectIsNonCallable: { 2919 VisitObjectIs(node, Type::NonCallable(), lowering); 2920 return; 2921 } 2922 case IrOpcode::kObjectIsNumber: { 2923 VisitObjectIs(node, Type::Number(), lowering); 2924 return; 2925 } 2926 case IrOpcode::kObjectIsReceiver: { 2927 VisitObjectIs(node, Type::Receiver(), lowering); 2928 return; 2929 } 2930 case IrOpcode::kObjectIsSmi: { 2931 // TODO(turbofan): Optimize based on input representation. 2932 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 2933 return; 2934 } 2935 case IrOpcode::kObjectIsString: { 2936 VisitObjectIs(node, Type::String(), lowering); 2937 return; 2938 } 2939 case IrOpcode::kObjectIsSymbol: { 2940 VisitObjectIs(node, Type::Symbol(), lowering); 2941 return; 2942 } 2943 case IrOpcode::kObjectIsUndetectable: { 2944 VisitObjectIs(node, Type::Undetectable(), lowering); 2945 return; 2946 } 2947 case IrOpcode::kArgumentsFrame: { 2948 SetOutput(node, MachineType::PointerRepresentation()); 2949 return; 2950 } 2951 case IrOpcode::kArgumentsLength: { 2952 VisitUnop(node, UseInfo::PointerInt(), 2953 MachineRepresentation::kTaggedSigned); 2954 return; 2955 } 2956 case IrOpcode::kNewDoubleElements: 2957 case IrOpcode::kNewSmiOrObjectElements: { 2958 VisitUnop(node, UseInfo::TruncatingWord32(), 2959 MachineRepresentation::kTaggedPointer); 2960 return; 2961 } 2962 case IrOpcode::kNewArgumentsElements: { 2963 VisitBinop(node, UseInfo::PointerInt(), UseInfo::TaggedSigned(), 2964 MachineRepresentation::kTaggedPointer); 2965 return; 2966 } 2967 case IrOpcode::kArrayBufferWasNeutered: { 2968 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 2969 return; 2970 } 2971 case IrOpcode::kCheckFloat64Hole: { 2972 Type const input_type = TypeOf(node->InputAt(0)); 2973 if (input_type.Is(Type::Number())) { 2974 VisitNoop(node, truncation); 2975 } else { 2976 CheckFloat64HoleMode mode = 2977 CheckFloat64HoleParametersOf(node->op()).mode(); 2978 switch (mode) { 2979 case CheckFloat64HoleMode::kAllowReturnHole: 2980 if (truncation.IsUnused()) return VisitUnused(node); 2981 if (truncation.IsUsedAsFloat64()) { 2982 VisitUnop(node, UseInfo::TruncatingFloat64(), 2983 MachineRepresentation::kFloat64); 2984 if (lower()) DeferReplacement(node, node->InputAt(0)); 2985 } else { 2986 VisitUnop( 2987 node, 2988 UseInfo(MachineRepresentation::kFloat64, Truncation::Any()), 2989 MachineRepresentation::kFloat64, Type::Number()); 2990 } 2991 break; 2992 case CheckFloat64HoleMode::kNeverReturnHole: 2993 VisitUnop( 2994 node, 2995 UseInfo(MachineRepresentation::kFloat64, Truncation::Any()), 2996 MachineRepresentation::kFloat64, Type::Number()); 2997 break; 2998 } 2999 } 3000 return; 3001 } 3002 case IrOpcode::kCheckNotTaggedHole: { 3003 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); 3004 return; 3005 } 3006 case IrOpcode::kConvertTaggedHoleToUndefined: { 3007 if (InputIs(node, Type::NumberOrOddball()) && 3008 truncation.IsUsedAsWord32()) { 3009 // Propagate the Word32 truncation. 3010 VisitUnop(node, UseInfo::TruncatingWord32(), 3011 MachineRepresentation::kWord32); 3012 if (lower()) DeferReplacement(node, node->InputAt(0)); 3013 } else if (InputIs(node, Type::NumberOrOddball()) && 3014 truncation.IsUsedAsFloat64()) { 3015 // Propagate the Float64 truncation. 3016 VisitUnop(node, UseInfo::TruncatingFloat64(), 3017 MachineRepresentation::kFloat64); 3018 if (lower()) DeferReplacement(node, node->InputAt(0)); 3019 } else if (InputIs(node, Type::NonInternal())) { 3020 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); 3021 if (lower()) DeferReplacement(node, node->InputAt(0)); 3022 } else { 3023 // TODO(turbofan): Add a (Tagged) truncation that identifies hole 3024 // and undefined, i.e. for a[i] === obj cases. 3025 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); 3026 } 3027 return; 3028 } 3029 case IrOpcode::kCheckEqualsSymbol: 3030 case IrOpcode::kCheckEqualsInternalizedString: 3031 return VisitBinop(node, UseInfo::AnyTagged(), 3032 MachineRepresentation::kNone); 3033 case IrOpcode::kMapGuard: 3034 // Eliminate MapGuard nodes here. 3035 return VisitUnused(node); 3036 case IrOpcode::kCheckMaps: 3037 case IrOpcode::kTransitionElementsKind: { 3038 VisitInputs(node); 3039 return SetOutput(node, MachineRepresentation::kNone); 3040 } 3041 case IrOpcode::kCompareMaps: 3042 return VisitUnop(node, UseInfo::AnyTagged(), 3043 MachineRepresentation::kBit); 3044 case IrOpcode::kEnsureWritableFastElements: 3045 return VisitBinop(node, UseInfo::AnyTagged(), 3046 MachineRepresentation::kTaggedPointer); 3047 case IrOpcode::kMaybeGrowFastElements: { 3048 ProcessInput(node, 0, UseInfo::AnyTagged()); // object 3049 ProcessInput(node, 1, UseInfo::AnyTagged()); // elements 3050 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // index 3051 ProcessInput(node, 3, UseInfo::TruncatingWord32()); // length 3052 ProcessRemainingInputs(node, 4); 3053 SetOutput(node, MachineRepresentation::kTaggedPointer); 3054 return; 3055 } 3056 3057 case IrOpcode::kNumberSilenceNaN: 3058 VisitUnop(node, UseInfo::TruncatingFloat64(), 3059 MachineRepresentation::kFloat64); 3060 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); 3061 return; 3062 case IrOpcode::kDateNow: 3063 VisitInputs(node); 3064 return SetOutput(node, MachineRepresentation::kTaggedPointer); 3065 case IrOpcode::kFrameState: 3066 return VisitFrameState(node); 3067 case IrOpcode::kStateValues: 3068 return VisitStateValues(node); 3069 case IrOpcode::kObjectState: 3070 return VisitObjectState(node); 3071 case IrOpcode::kObjectId: 3072 return SetOutput(node, MachineRepresentation::kTaggedPointer); 3073 case IrOpcode::kTypeGuard: { 3074 // We just get rid of the sigma here, choosing the best representation 3075 // for the sigma's type. 3076 Type type = TypeOf(node); 3077 MachineRepresentation representation = 3078 GetOutputInfoForPhi(node, type, truncation); 3079 3080 // Here we pretend that the input has the sigma's type for the 3081 // conversion. 3082 UseInfo use(representation, truncation); 3083 if (propagate()) { 3084 EnqueueInput(node, 0, use); 3085 } else if (lower()) { 3086 ConvertInput(node, 0, use, type); 3087 } 3088 ProcessRemainingInputs(node, 1); 3089 SetOutput(node, representation); 3090 return; 3091 } 3092 3093 case IrOpcode::kFinishRegion: 3094 VisitInputs(node); 3095 // Assume the output is tagged pointer. 3096 return SetOutput(node, MachineRepresentation::kTaggedPointer); 3097 3098 case IrOpcode::kReturn: 3099 VisitReturn(node); 3100 // Assume the output is tagged. 3101 return SetOutput(node, MachineRepresentation::kTagged); 3102 3103 case IrOpcode::kFindOrderedHashMapEntry: { 3104 Type const key_type = TypeOf(node->InputAt(1)); 3105 if (key_type.Is(Type::Signed32OrMinusZero())) { 3106 VisitBinop(node, UseInfo::AnyTagged(), UseInfo::TruncatingWord32(), 3107 MachineRepresentation::kWord32); 3108 if (lower()) { 3109 NodeProperties::ChangeOp( 3110 node, 3111 lowering->simplified()->FindOrderedHashMapEntryForInt32Key()); 3112 } 3113 } else { 3114 VisitBinop(node, UseInfo::AnyTagged(), 3115 MachineRepresentation::kTaggedSigned); 3116 } 3117 return; 3118 } 3119 3120 // Operators with all inputs tagged and no or tagged output have uniform 3121 // handling. 3122 case IrOpcode::kEnd: 3123 case IrOpcode::kIfSuccess: 3124 case IrOpcode::kIfException: 3125 case IrOpcode::kIfTrue: 3126 case IrOpcode::kIfFalse: 3127 case IrOpcode::kIfValue: 3128 case IrOpcode::kIfDefault: 3129 case IrOpcode::kDeoptimize: 3130 case IrOpcode::kEffectPhi: 3131 case IrOpcode::kTerminate: 3132 case IrOpcode::kCheckpoint: 3133 case IrOpcode::kLoop: 3134 case IrOpcode::kMerge: 3135 case IrOpcode::kThrow: 3136 case IrOpcode::kBeginRegion: 3137 case IrOpcode::kProjection: 3138 case IrOpcode::kOsrValue: 3139 case IrOpcode::kArgumentsElementsState: 3140 case IrOpcode::kArgumentsLengthState: 3141 case IrOpcode::kUnreachable: 3142 case IrOpcode::kRuntimeAbort: 3143 // All JavaScript operators except JSToNumber have uniform handling. 3144 #define OPCODE_CASE(name) case IrOpcode::k##name: 3145 JS_SIMPLE_BINOP_LIST(OPCODE_CASE) 3146 JS_OBJECT_OP_LIST(OPCODE_CASE) 3147 JS_CONTEXT_OP_LIST(OPCODE_CASE) 3148 JS_OTHER_OP_LIST(OPCODE_CASE) 3149 #undef OPCODE_CASE 3150 case IrOpcode::kJSBitwiseNot: 3151 case IrOpcode::kJSDecrement: 3152 case IrOpcode::kJSIncrement: 3153 case IrOpcode::kJSNegate: 3154 case IrOpcode::kJSToInteger: 3155 case IrOpcode::kJSToLength: 3156 case IrOpcode::kJSToName: 3157 case IrOpcode::kJSToObject: 3158 case IrOpcode::kJSToString: 3159 case IrOpcode::kJSParseInt: 3160 VisitInputs(node); 3161 // Assume the output is tagged. 3162 return SetOutput(node, MachineRepresentation::kTagged); 3163 case IrOpcode::kDeadValue: 3164 ProcessInput(node, 0, UseInfo::Any()); 3165 return SetOutput(node, MachineRepresentation::kNone); 3166 default: 3167 FATAL( 3168 "Representation inference: unsupported opcode %i (%s), node #%i\n.", 3169 node->opcode(), node->op()->mnemonic(), node->id()); 3170 break; 3171 } 3172 UNREACHABLE(); 3173 } 3174 3175 void DeferReplacement(Node* node, Node* replacement) { 3176 TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(), 3177 node->op()->mnemonic(), replacement->id(), 3178 replacement->op()->mnemonic()); 3179 3180 // Disconnect the node from effect and control chains, if necessary. 3181 if (node->op()->EffectInputCount() > 0) { 3182 DCHECK_LT(0, node->op()->ControlInputCount()); 3183 // Disconnect the node from effect and control chains. 3184 Node* control = NodeProperties::GetControlInput(node); 3185 Node* effect = NodeProperties::GetEffectInput(node); 3186 ReplaceEffectControlUses(node, effect, control); 3187 } 3188 3189 replacements_.push_back(node); 3190 replacements_.push_back(replacement); 3191 3192 node->NullAllInputs(); // Node is now dead. 3193 } 3194 3195 void Kill(Node* node) { 3196 TRACE("killing #%d:%s\n", node->id(), node->op()->mnemonic()); 3197 3198 if (node->op()->EffectInputCount() == 1) { 3199 DCHECK_LT(0, node->op()->ControlInputCount()); 3200 // Disconnect the node from effect and control chains. 3201 Node* control = NodeProperties::GetControlInput(node); 3202 Node* effect = NodeProperties::GetEffectInput(node); 3203 ReplaceEffectControlUses(node, effect, control); 3204 } else { 3205 DCHECK_EQ(0, node->op()->EffectInputCount()); 3206 DCHECK_EQ(0, node->op()->ControlOutputCount()); 3207 DCHECK_EQ(0, node->op()->EffectOutputCount()); 3208 } 3209 3210 node->ReplaceUses(jsgraph_->Dead()); 3211 3212 node->NullAllInputs(); // The {node} is now dead. 3213 } 3214 3215 void PrintOutputInfo(NodeInfo* info) { 3216 if (FLAG_trace_representation) { 3217 StdoutStream{} << info->representation(); 3218 } 3219 } 3220 3221 void PrintRepresentation(MachineRepresentation rep) { 3222 if (FLAG_trace_representation) { 3223 StdoutStream{} << rep; 3224 } 3225 } 3226 3227 void PrintTruncation(Truncation truncation) { 3228 if (FLAG_trace_representation) { 3229 StdoutStream{} << truncation.description() << std::endl; 3230 } 3231 } 3232 3233 void PrintUseInfo(UseInfo info) { 3234 if (FLAG_trace_representation) { 3235 StdoutStream{} << info.representation() << ":" 3236 << info.truncation().description(); 3237 } 3238 } 3239 3240 private: 3241 JSGraph* jsgraph_; 3242 Zone* zone_; // Temporary zone. 3243 size_t const count_; // number of nodes in the graph 3244 ZoneVector<NodeInfo> info_; // node id -> usage information 3245 #ifdef DEBUG 3246 ZoneVector<InputUseInfos> node_input_use_infos_; // Debug information about 3247 // requirements on inputs. 3248 #endif // DEBUG 3249 NodeVector nodes_; // collected nodes 3250 NodeVector replacements_; // replacements to be done after lowering 3251 Phase phase_; // current phase of algorithm 3252 RepresentationChanger* changer_; // for inserting representation changes 3253 ZoneQueue<Node*> queue_; // queue for traversing the graph 3254 3255 struct NodeState { 3256 Node* node; 3257 int input_index; 3258 }; 3259 ZoneStack<NodeState> typing_stack_; // stack for graph typing. 3260 // TODO(danno): RepresentationSelector shouldn't know anything about the 3261 // source positions table, but must for now since there currently is no other 3262 // way to pass down source position information to nodes created during 3263 // lowering. Once this phase becomes a vanilla reducer, it should get source 3264 // position information via the SourcePositionWrapper like all other reducers. 3265 SourcePositionTable* source_positions_; 3266 NodeOriginTable* node_origins_; 3267 TypeCache const& type_cache_; 3268 OperationTyper op_typer_; // helper for the feedback typer 3269 3270 NodeInfo* GetInfo(Node* node) { 3271 DCHECK(node->id() < count_); 3272 return &info_[node->id()]; 3273 } 3274 Zone* zone() { return zone_; } 3275 Zone* graph_zone() { return jsgraph_->zone(); } 3276 }; 3277 3278 SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, 3279 JSHeapBroker* js_heap_broker, Zone* zone, 3280 SourcePositionTable* source_positions, 3281 NodeOriginTable* node_origins, 3282 PoisoningMitigationLevel poisoning_level) 3283 : jsgraph_(jsgraph), 3284 js_heap_broker_(js_heap_broker), 3285 zone_(zone), 3286 type_cache_(TypeCache::Get()), 3287 source_positions_(source_positions), 3288 node_origins_(node_origins), 3289 poisoning_level_(poisoning_level) {} 3290 3291 void SimplifiedLowering::LowerAllNodes() { 3292 RepresentationChanger changer(jsgraph(), jsgraph()->isolate()); 3293 RepresentationSelector selector(jsgraph(), js_heap_broker_, zone_, &changer, 3294 source_positions_, node_origins_); 3295 selector.Run(this); 3296 } 3297 3298 void SimplifiedLowering::DoJSToNumberOrNumericTruncatesToFloat64( 3299 Node* node, RepresentationSelector* selector) { 3300 DCHECK(node->opcode() == IrOpcode::kJSToNumber || 3301 node->opcode() == IrOpcode::kJSToNumberConvertBigInt || 3302 node->opcode() == IrOpcode::kJSToNumeric); 3303 Node* value = node->InputAt(0); 3304 Node* context = node->InputAt(1); 3305 Node* frame_state = node->InputAt(2); 3306 Node* effect = node->InputAt(3); 3307 Node* control = node->InputAt(4); 3308 3309 Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value); 3310 Node* branch0 = 3311 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); 3312 3313 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); 3314 Node* etrue0 = effect; 3315 Node* vtrue0; 3316 { 3317 vtrue0 = graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value); 3318 vtrue0 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue0); 3319 } 3320 3321 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); 3322 Node* efalse0 = effect; 3323 Node* vfalse0; 3324 { 3325 Operator const* op = 3326 node->opcode() == IrOpcode::kJSToNumber 3327 ? (node->opcode() == IrOpcode::kJSToNumberConvertBigInt 3328 ? ToNumberConvertBigIntOperator() 3329 : ToNumberOperator()) 3330 : ToNumericOperator(); 3331 Node* code = node->opcode() == IrOpcode::kJSToNumber 3332 ? ToNumberCode() 3333 : (node->opcode() == IrOpcode::kJSToNumberConvertBigInt 3334 ? ToNumberConvertBigIntCode() 3335 : ToNumericCode()); 3336 vfalse0 = efalse0 = if_false0 = graph()->NewNode( 3337 op, code, value, context, frame_state, efalse0, if_false0); 3338 3339 // Update potential {IfException} uses of {node} to point to the above 3340 // stub call node instead. 3341 Node* on_exception = nullptr; 3342 if (NodeProperties::IsExceptionalCall(node, &on_exception)) { 3343 NodeProperties::ReplaceControlInput(on_exception, vfalse0); 3344 NodeProperties::ReplaceEffectInput(on_exception, efalse0); 3345 if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0); 3346 } 3347 3348 Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0); 3349 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); 3350 3351 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); 3352 Node* etrue1 = efalse0; 3353 Node* vtrue1; 3354 { 3355 vtrue1 = 3356 graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0); 3357 vtrue1 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue1); 3358 } 3359 3360 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); 3361 Node* efalse1 = efalse0; 3362 Node* vfalse1; 3363 { 3364 vfalse1 = efalse1 = graph()->NewNode( 3365 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0, 3366 efalse1, if_false1); 3367 } 3368 3369 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); 3370 efalse0 = 3371 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0); 3372 vfalse0 = 3373 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), 3374 vtrue1, vfalse1, if_false0); 3375 } 3376 3377 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); 3378 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); 3379 value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), 3380 vtrue0, vfalse0, control); 3381 3382 // Replace effect and control uses appropriately. 3383 for (Edge edge : node->use_edges()) { 3384 if (NodeProperties::IsControlEdge(edge)) { 3385 if (edge.from()->opcode() == IrOpcode::kIfSuccess) { 3386 edge.from()->ReplaceUses(control); 3387 edge.from()->Kill(); 3388 } else { 3389 DCHECK_NE(IrOpcode::kIfException, edge.from()->opcode()); 3390 edge.UpdateTo(control); 3391 } 3392 } else if (NodeProperties::IsEffectEdge(edge)) { 3393 edge.UpdateTo(effect); 3394 } 3395 } 3396 3397 selector->DeferReplacement(node, value); 3398 } 3399 3400 void SimplifiedLowering::DoJSToNumberOrNumericTruncatesToWord32( 3401 Node* node, RepresentationSelector* selector) { 3402 DCHECK(node->opcode() == IrOpcode::kJSToNumber || 3403 node->opcode() == IrOpcode::kJSToNumberConvertBigInt || 3404 node->opcode() == IrOpcode::kJSToNumeric); 3405 Node* value = node->InputAt(0); 3406 Node* context = node->InputAt(1); 3407 Node* frame_state = node->InputAt(2); 3408 Node* effect = node->InputAt(3); 3409 Node* control = node->InputAt(4); 3410 3411 Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value); 3412 Node* branch0 = 3413 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); 3414 3415 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); 3416 Node* etrue0 = effect; 3417 Node* vtrue0 = 3418 graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value); 3419 3420 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); 3421 Node* efalse0 = effect; 3422 Node* vfalse0; 3423 { 3424 Operator const* op = 3425 node->opcode() == IrOpcode::kJSToNumber 3426 ? (node->opcode() == IrOpcode::kJSToNumberConvertBigInt 3427 ? ToNumberConvertBigIntOperator() 3428 : ToNumberOperator()) 3429 : ToNumericOperator(); 3430 Node* code = node->opcode() == IrOpcode::kJSToNumber 3431 ? ToNumberCode() 3432 : (node->opcode() == IrOpcode::kJSToNumberConvertBigInt 3433 ? ToNumberConvertBigIntCode() 3434 : ToNumericCode()); 3435 vfalse0 = efalse0 = if_false0 = graph()->NewNode( 3436 op, code, value, context, frame_state, efalse0, if_false0); 3437 3438 // Update potential {IfException} uses of {node} to point to the above 3439 // stub call node instead. 3440 Node* on_exception = nullptr; 3441 if (NodeProperties::IsExceptionalCall(node, &on_exception)) { 3442 NodeProperties::ReplaceControlInput(on_exception, vfalse0); 3443 NodeProperties::ReplaceEffectInput(on_exception, efalse0); 3444 if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0); 3445 } 3446 3447 Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0); 3448 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); 3449 3450 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); 3451 Node* etrue1 = efalse0; 3452 Node* vtrue1 = 3453 graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0); 3454 3455 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); 3456 Node* efalse1 = efalse0; 3457 Node* vfalse1; 3458 { 3459 vfalse1 = efalse1 = graph()->NewNode( 3460 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0, 3461 efalse1, if_false1); 3462 vfalse1 = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse1); 3463 } 3464 3465 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); 3466 efalse0 = 3467 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0); 3468 vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), 3469 vtrue1, vfalse1, if_false0); 3470 } 3471 3472 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); 3473 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); 3474 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), 3475 vtrue0, vfalse0, control); 3476 3477 // Replace effect and control uses appropriately. 3478 for (Edge edge : node->use_edges()) { 3479 if (NodeProperties::IsControlEdge(edge)) { 3480 if (edge.from()->opcode() == IrOpcode::kIfSuccess) { 3481 edge.from()->ReplaceUses(control); 3482 edge.from()->Kill(); 3483 } else { 3484 DCHECK_NE(IrOpcode::kIfException, edge.from()->opcode()); 3485 edge.UpdateTo(control); 3486 } 3487 } else if (NodeProperties::IsEffectEdge(edge)) { 3488 edge.UpdateTo(effect); 3489 } 3490 } 3491 3492 selector->DeferReplacement(node, value); 3493 } 3494 3495 Node* SimplifiedLowering::Float64Round(Node* const node) { 3496 Node* const one = jsgraph()->Float64Constant(1.0); 3497 Node* const one_half = jsgraph()->Float64Constant(0.5); 3498 Node* const input = node->InputAt(0); 3499 3500 // Round up towards Infinity, and adjust if the difference exceeds 0.5. 3501 Node* result = graph()->NewNode(machine()->Float64RoundUp().placeholder(), 3502 node->InputAt(0)); 3503 return graph()->NewNode( 3504 common()->Select(MachineRepresentation::kFloat64), 3505 graph()->NewNode( 3506 machine()->Float64LessThanOrEqual(), 3507 graph()->NewNode(machine()->Float64Sub(), result, one_half), input), 3508 result, graph()->NewNode(machine()->Float64Sub(), result, one)); 3509 } 3510 3511 Node* SimplifiedLowering::Float64Sign(Node* const node) { 3512 Node* const minus_one = jsgraph()->Float64Constant(-1.0); 3513 Node* const zero = jsgraph()->Float64Constant(0.0); 3514 Node* const one = jsgraph()->Float64Constant(1.0); 3515 3516 Node* const input = node->InputAt(0); 3517 3518 return graph()->NewNode( 3519 common()->Select(MachineRepresentation::kFloat64), 3520 graph()->NewNode(machine()->Float64LessThan(), input, zero), minus_one, 3521 graph()->NewNode( 3522 common()->Select(MachineRepresentation::kFloat64), 3523 graph()->NewNode(machine()->Float64LessThan(), zero, input), one, 3524 input)); 3525 } 3526 3527 Node* SimplifiedLowering::Int32Abs(Node* const node) { 3528 Node* const input = node->InputAt(0); 3529 3530 // Generate case for absolute integer value. 3531 // 3532 // let sign = input >> 31 in 3533 // (input ^ sign) - sign 3534 3535 Node* sign = graph()->NewNode(machine()->Word32Sar(), input, 3536 jsgraph()->Int32Constant(31)); 3537 return graph()->NewNode(machine()->Int32Sub(), 3538 graph()->NewNode(machine()->Word32Xor(), input, sign), 3539 sign); 3540 } 3541 3542 Node* SimplifiedLowering::Int32Div(Node* const node) { 3543 Int32BinopMatcher m(node); 3544 Node* const zero = jsgraph()->Int32Constant(0); 3545 Node* const minus_one = jsgraph()->Int32Constant(-1); 3546 Node* const lhs = m.left().node(); 3547 Node* const rhs = m.right().node(); 3548 3549 if (m.right().Is(-1)) { 3550 return graph()->NewNode(machine()->Int32Sub(), zero, lhs); 3551 } else if (m.right().Is(0)) { 3552 return rhs; 3553 } else if (machine()->Int32DivIsSafe() || m.right().HasValue()) { 3554 return graph()->NewNode(machine()->Int32Div(), lhs, rhs, graph()->start()); 3555 } 3556 3557 // General case for signed integer division. 3558 // 3559 // if 0 < rhs then 3560 // lhs / rhs 3561 // else 3562 // if rhs < -1 then 3563 // lhs / rhs 3564 // else if rhs == 0 then 3565 // 0 3566 // else 3567 // 0 - lhs 3568 // 3569 // Note: We do not use the Diamond helper class here, because it really hurts 3570 // readability with nested diamonds. 3571 const Operator* const merge_op = common()->Merge(2); 3572 const Operator* const phi_op = 3573 common()->Phi(MachineRepresentation::kWord32, 2); 3574 3575 Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs); 3576 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, 3577 graph()->start()); 3578 3579 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); 3580 Node* true0 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true0); 3581 3582 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); 3583 Node* false0; 3584 { 3585 Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one); 3586 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); 3587 3588 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); 3589 Node* true1 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true1); 3590 3591 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); 3592 Node* false1; 3593 { 3594 Node* check2 = graph()->NewNode(machine()->Word32Equal(), rhs, zero); 3595 Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_false1); 3596 3597 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); 3598 Node* true2 = zero; 3599 3600 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); 3601 Node* false2 = graph()->NewNode(machine()->Int32Sub(), zero, lhs); 3602 3603 if_false1 = graph()->NewNode(merge_op, if_true2, if_false2); 3604 false1 = graph()->NewNode(phi_op, true2, false2, if_false1); 3605 } 3606 3607 if_false0 = graph()->NewNode(merge_op, if_true1, if_false1); 3608 false0 = graph()->NewNode(phi_op, true1, false1, if_false0); 3609 } 3610 3611 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0); 3612 return graph()->NewNode(phi_op, true0, false0, merge0); 3613 } 3614 3615 Node* SimplifiedLowering::Int32Mod(Node* const node) { 3616 Int32BinopMatcher m(node); 3617 Node* const zero = jsgraph()->Int32Constant(0); 3618 Node* const minus_one = jsgraph()->Int32Constant(-1); 3619 Node* const lhs = m.left().node(); 3620 Node* const rhs = m.right().node(); 3621 3622 if (m.right().Is(-1) || m.right().Is(0)) { 3623 return zero; 3624 } else if (m.right().HasValue()) { 3625 return graph()->NewNode(machine()->Int32Mod(), lhs, rhs, graph()->start()); 3626 } 3627 3628 // General case for signed integer modulus, with optimization for (unknown) 3629 // power of 2 right hand side. 3630 // 3631 // if 0 < rhs then 3632 // msk = rhs - 1 3633 // if rhs & msk != 0 then 3634 // lhs % rhs 3635 // else 3636 // if lhs < 0 then 3637 // -(-lhs & msk) 3638 // else 3639 // lhs & msk 3640 // else 3641 // if rhs < -1 then 3642 // lhs % rhs 3643 // else 3644 // zero 3645 // 3646 // Note: We do not use the Diamond helper class here, because it really hurts 3647 // readability with nested diamonds. 3648 const Operator* const merge_op = common()->Merge(2); 3649 const Operator* const phi_op = 3650 common()->Phi(MachineRepresentation::kWord32, 2); 3651 3652 Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs); 3653 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, 3654 graph()->start()); 3655 3656 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); 3657 Node* true0; 3658 { 3659 Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one); 3660 3661 Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk); 3662 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0); 3663 3664 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); 3665 Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1); 3666 3667 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); 3668 Node* false1; 3669 { 3670 Node* check2 = graph()->NewNode(machine()->Int32LessThan(), lhs, zero); 3671 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse), 3672 check2, if_false1); 3673 3674 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); 3675 Node* true2 = graph()->NewNode( 3676 machine()->Int32Sub(), zero, 3677 graph()->NewNode(machine()->Word32And(), 3678 graph()->NewNode(machine()->Int32Sub(), zero, lhs), 3679 msk)); 3680 3681 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); 3682 Node* false2 = graph()->NewNode(machine()->Word32And(), lhs, msk); 3683 3684 if_false1 = graph()->NewNode(merge_op, if_true2, if_false2); 3685 false1 = graph()->NewNode(phi_op, true2, false2, if_false1); 3686 } 3687 3688 if_true0 = graph()->NewNode(merge_op, if_true1, if_false1); 3689 true0 = graph()->NewNode(phi_op, true1, false1, if_true0); 3690 } 3691 3692 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); 3693 Node* false0; 3694 { 3695 Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one); 3696 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue), 3697 check1, if_false0); 3698 3699 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); 3700 Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1); 3701 3702 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); 3703 Node* false1 = zero; 3704 3705 if_false0 = graph()->NewNode(merge_op, if_true1, if_false1); 3706 false0 = graph()->NewNode(phi_op, true1, false1, if_false0); 3707 } 3708 3709 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0); 3710 return graph()->NewNode(phi_op, true0, false0, merge0); 3711 } 3712 3713 Node* SimplifiedLowering::Int32Sign(Node* const node) { 3714 Node* const minus_one = jsgraph()->Int32Constant(-1); 3715 Node* const zero = jsgraph()->Int32Constant(0); 3716 Node* const one = jsgraph()->Int32Constant(1); 3717 3718 Node* const input = node->InputAt(0); 3719 3720 return graph()->NewNode( 3721 common()->Select(MachineRepresentation::kWord32), 3722 graph()->NewNode(machine()->Int32LessThan(), input, zero), minus_one, 3723 graph()->NewNode( 3724 common()->Select(MachineRepresentation::kWord32), 3725 graph()->NewNode(machine()->Int32LessThan(), zero, input), one, 3726 zero)); 3727 } 3728 3729 Node* SimplifiedLowering::Uint32Div(Node* const node) { 3730 Uint32BinopMatcher m(node); 3731 Node* const zero = jsgraph()->Uint32Constant(0); 3732 Node* const lhs = m.left().node(); 3733 Node* const rhs = m.right().node(); 3734 3735 if (m.right().Is(0)) { 3736 return zero; 3737 } else if (machine()->Uint32DivIsSafe() || m.right().HasValue()) { 3738 return graph()->NewNode(machine()->Uint32Div(), lhs, rhs, graph()->start()); 3739 } 3740 3741 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero); 3742 Diamond d(graph(), common(), check, BranchHint::kFalse); 3743 Node* div = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, d.if_false); 3744 return d.Phi(MachineRepresentation::kWord32, zero, div); 3745 } 3746 3747 Node* SimplifiedLowering::Uint32Mod(Node* const node) { 3748 Uint32BinopMatcher m(node); 3749 Node* const minus_one = jsgraph()->Int32Constant(-1); 3750 Node* const zero = jsgraph()->Uint32Constant(0); 3751 Node* const lhs = m.left().node(); 3752 Node* const rhs = m.right().node(); 3753 3754 if (m.right().Is(0)) { 3755 return zero; 3756 } else if (m.right().HasValue()) { 3757 return graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, graph()->start()); 3758 } 3759 3760 // General case for unsigned integer modulus, with optimization for (unknown) 3761 // power of 2 right hand side. 3762 // 3763 // if rhs == 0 then 3764 // zero 3765 // else 3766 // msk = rhs - 1 3767 // if rhs & msk != 0 then 3768 // lhs % rhs 3769 // else 3770 // lhs & msk 3771 // 3772 // Note: We do not use the Diamond helper class here, because it really hurts 3773 // readability with nested diamonds. 3774 const Operator* const merge_op = common()->Merge(2); 3775 const Operator* const phi_op = 3776 common()->Phi(MachineRepresentation::kWord32, 2); 3777 3778 Node* check0 = graph()->NewNode(machine()->Word32Equal(), rhs, zero); 3779 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, 3780 graph()->start()); 3781 3782 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); 3783 Node* true0 = zero; 3784 3785 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); 3786 Node* false0; 3787 { 3788 Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one); 3789 3790 Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk); 3791 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); 3792 3793 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); 3794 Node* true1 = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, if_true1); 3795 3796 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); 3797 Node* false1 = graph()->NewNode(machine()->Word32And(), lhs, msk); 3798 3799 if_false0 = graph()->NewNode(merge_op, if_true1, if_false1); 3800 false0 = graph()->NewNode(phi_op, true1, false1, if_false0); 3801 } 3802 3803 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0); 3804 return graph()->NewNode(phi_op, true0, false0, merge0); 3805 } 3806 3807 void SimplifiedLowering::DoMax(Node* node, Operator const* op, 3808 MachineRepresentation rep) { 3809 Node* const lhs = node->InputAt(0); 3810 Node* const rhs = node->InputAt(1); 3811 3812 node->ReplaceInput(0, graph()->NewNode(op, lhs, rhs)); 3813 DCHECK_EQ(rhs, node->InputAt(1)); 3814 node->AppendInput(graph()->zone(), lhs); 3815 NodeProperties::ChangeOp(node, common()->Select(rep)); 3816 } 3817 3818 void SimplifiedLowering::DoMin(Node* node, Operator const* op, 3819 MachineRepresentation rep) { 3820 Node* const lhs = node->InputAt(0); 3821 Node* const rhs = node->InputAt(1); 3822 3823 node->InsertInput(graph()->zone(), 0, graph()->NewNode(op, lhs, rhs)); 3824 DCHECK_EQ(lhs, node->InputAt(1)); 3825 DCHECK_EQ(rhs, node->InputAt(2)); 3826 NodeProperties::ChangeOp(node, common()->Select(rep)); 3827 } 3828 3829 void SimplifiedLowering::DoShift(Node* node, Operator const* op, 3830 Type rhs_type) { 3831 if (!rhs_type.Is(type_cache_.kZeroToThirtyOne)) { 3832 Node* const rhs = NodeProperties::GetValueInput(node, 1); 3833 node->ReplaceInput(1, graph()->NewNode(machine()->Word32And(), rhs, 3834 jsgraph()->Int32Constant(0x1F))); 3835 } 3836 ChangeToPureOp(node, op); 3837 } 3838 3839 void SimplifiedLowering::DoIntegral32ToBit(Node* node) { 3840 Node* const input = node->InputAt(0); 3841 Node* const zero = jsgraph()->Int32Constant(0); 3842 Operator const* const op = machine()->Word32Equal(); 3843 3844 node->ReplaceInput(0, graph()->NewNode(op, input, zero)); 3845 node->AppendInput(graph()->zone(), zero); 3846 NodeProperties::ChangeOp(node, op); 3847 } 3848 3849 void SimplifiedLowering::DoOrderedNumberToBit(Node* node) { 3850 Node* const input = node->InputAt(0); 3851 3852 node->ReplaceInput(0, graph()->NewNode(machine()->Float64Equal(), input, 3853 jsgraph()->Float64Constant(0.0))); 3854 node->AppendInput(graph()->zone(), jsgraph()->Int32Constant(0)); 3855 NodeProperties::ChangeOp(node, machine()->Word32Equal()); 3856 } 3857 3858 void SimplifiedLowering::DoNumberToBit(Node* node) { 3859 Node* const input = node->InputAt(0); 3860 3861 node->ReplaceInput(0, jsgraph()->Float64Constant(0.0)); 3862 node->AppendInput(graph()->zone(), 3863 graph()->NewNode(machine()->Float64Abs(), input)); 3864 NodeProperties::ChangeOp(node, machine()->Float64LessThan()); 3865 } 3866 3867 void SimplifiedLowering::DoIntegerToUint8Clamped(Node* node) { 3868 Node* const input = node->InputAt(0); 3869 Node* const min = jsgraph()->Float64Constant(0.0); 3870 Node* const max = jsgraph()->Float64Constant(255.0); 3871 3872 node->ReplaceInput( 3873 0, graph()->NewNode(machine()->Float64LessThan(), min, input)); 3874 node->AppendInput( 3875 graph()->zone(), 3876 graph()->NewNode( 3877 common()->Select(MachineRepresentation::kFloat64), 3878 graph()->NewNode(machine()->Float64LessThan(), input, max), input, 3879 max)); 3880 node->AppendInput(graph()->zone(), min); 3881 NodeProperties::ChangeOp(node, 3882 common()->Select(MachineRepresentation::kFloat64)); 3883 } 3884 3885 void SimplifiedLowering::DoNumberToUint8Clamped(Node* node) { 3886 Node* const input = node->InputAt(0); 3887 Node* const min = jsgraph()->Float64Constant(0.0); 3888 Node* const max = jsgraph()->Float64Constant(255.0); 3889 3890 node->ReplaceInput( 3891 0, graph()->NewNode( 3892 common()->Select(MachineRepresentation::kFloat64), 3893 graph()->NewNode(machine()->Float64LessThan(), min, input), 3894 graph()->NewNode( 3895 common()->Select(MachineRepresentation::kFloat64), 3896 graph()->NewNode(machine()->Float64LessThan(), input, max), 3897 input, max), 3898 min)); 3899 NodeProperties::ChangeOp(node, 3900 machine()->Float64RoundTiesEven().placeholder()); 3901 } 3902 3903 void SimplifiedLowering::DoSigned32ToUint8Clamped(Node* node) { 3904 Node* const input = node->InputAt(0); 3905 Node* const min = jsgraph()->Int32Constant(0); 3906 Node* const max = jsgraph()->Int32Constant(255); 3907 3908 node->ReplaceInput( 3909 0, graph()->NewNode(machine()->Int32LessThanOrEqual(), input, max)); 3910 node->AppendInput( 3911 graph()->zone(), 3912 graph()->NewNode(common()->Select(MachineRepresentation::kWord32), 3913 graph()->NewNode(machine()->Int32LessThan(), input, min), 3914 min, input)); 3915 node->AppendInput(graph()->zone(), max); 3916 NodeProperties::ChangeOp(node, 3917 common()->Select(MachineRepresentation::kWord32)); 3918 } 3919 3920 void SimplifiedLowering::DoUnsigned32ToUint8Clamped(Node* node) { 3921 Node* const input = node->InputAt(0); 3922 Node* const max = jsgraph()->Uint32Constant(255u); 3923 3924 node->ReplaceInput( 3925 0, graph()->NewNode(machine()->Uint32LessThanOrEqual(), input, max)); 3926 node->AppendInput(graph()->zone(), input); 3927 node->AppendInput(graph()->zone(), max); 3928 NodeProperties::ChangeOp(node, 3929 common()->Select(MachineRepresentation::kWord32)); 3930 } 3931 3932 Node* SimplifiedLowering::ToNumberCode() { 3933 if (!to_number_code_.is_set()) { 3934 Callable callable = Builtins::CallableFor(isolate(), Builtins::kToNumber); 3935 to_number_code_.set(jsgraph()->HeapConstant(callable.code())); 3936 } 3937 return to_number_code_.get(); 3938 } 3939 3940 Node* SimplifiedLowering::ToNumberConvertBigIntCode() { 3941 if (!to_number_convert_big_int_code_.is_set()) { 3942 Callable callable = 3943 Builtins::CallableFor(isolate(), Builtins::kToNumberConvertBigInt); 3944 to_number_convert_big_int_code_.set( 3945 jsgraph()->HeapConstant(callable.code())); 3946 } 3947 return to_number_convert_big_int_code_.get(); 3948 } 3949 3950 Node* SimplifiedLowering::ToNumericCode() { 3951 if (!to_numeric_code_.is_set()) { 3952 Callable callable = Builtins::CallableFor(isolate(), Builtins::kToNumeric); 3953 to_number_code_.set(jsgraph()->HeapConstant(callable.code())); 3954 } 3955 return to_numeric_code_.get(); 3956 } 3957 3958 Operator const* SimplifiedLowering::ToNumberOperator() { 3959 if (!to_number_operator_.is_set()) { 3960 Callable callable = Builtins::CallableFor(isolate(), Builtins::kToNumber); 3961 CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState; 3962 auto call_descriptor = 3963 Linkage::GetStubCallDescriptor(graph()->zone(), callable.descriptor(), 3964 0, flags, Operator::kNoProperties); 3965 to_number_operator_.set(common()->Call(call_descriptor)); 3966 } 3967 return to_number_operator_.get(); 3968 } 3969 3970 Operator const* SimplifiedLowering::ToNumberConvertBigIntOperator() { 3971 if (!to_number_convert_big_int_operator_.is_set()) { 3972 Callable callable = 3973 Builtins::CallableFor(isolate(), Builtins::kToNumberConvertBigInt); 3974 CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState; 3975 auto call_descriptor = 3976 Linkage::GetStubCallDescriptor(graph()->zone(), callable.descriptor(), 3977 0, flags, Operator::kNoProperties); 3978 to_number_convert_big_int_operator_.set(common()->Call(call_descriptor)); 3979 } 3980 return to_number_convert_big_int_operator_.get(); 3981 } 3982 3983 Operator const* SimplifiedLowering::ToNumericOperator() { 3984 if (!to_numeric_operator_.is_set()) { 3985 Callable callable = Builtins::CallableFor(isolate(), Builtins::kToNumeric); 3986 CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState; 3987 auto call_descriptor = 3988 Linkage::GetStubCallDescriptor(graph()->zone(), callable.descriptor(), 3989 0, flags, Operator::kNoProperties); 3990 to_numeric_operator_.set(common()->Call(call_descriptor)); 3991 } 3992 return to_numeric_operator_.get(); 3993 } 3994 3995 #undef TRACE 3996 3997 } // namespace compiler 3998 } // namespace internal 3999 } // namespace v8 4000