LCOV - code coverage report
Current view: top level - src/compiler - effect-control-linearizer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1840 2038 90.3 %
Date: 2019-01-20 Functions: 159 177 89.8 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/effect-control-linearizer.h"
       6             : 
       7             : #include "src/code-factory.h"
       8             : #include "src/compiler/access-builder.h"
       9             : #include "src/compiler/compiler-source-position-table.h"
      10             : #include "src/compiler/js-graph.h"
      11             : #include "src/compiler/linkage.h"
      12             : #include "src/compiler/node-matchers.h"
      13             : #include "src/compiler/node-origin-table.h"
      14             : #include "src/compiler/node-properties.h"
      15             : #include "src/compiler/node.h"
      16             : #include "src/compiler/schedule.h"
      17             : #include "src/heap/factory-inl.h"
      18             : #include "src/objects/heap-number.h"
      19             : #include "src/objects/oddball.h"
      20             : 
      21             : namespace v8 {
      22             : namespace internal {
      23             : namespace compiler {
      24             : 
      25      456086 : EffectControlLinearizer::EffectControlLinearizer(
      26             :     JSGraph* js_graph, Schedule* schedule, Zone* temp_zone,
      27             :     SourcePositionTable* source_positions, NodeOriginTable* node_origins,
      28             :     MaskArrayIndexEnable mask_array_index)
      29             :     : js_graph_(js_graph),
      30             :       schedule_(schedule),
      31             :       temp_zone_(temp_zone),
      32             :       mask_array_index_(mask_array_index),
      33             :       source_positions_(source_positions),
      34             :       node_origins_(node_origins),
      35             :       graph_assembler_(js_graph, nullptr, nullptr, temp_zone),
      36      456086 :       frame_state_zapper_(nullptr) {}
      37             : 
      38     1750214 : Graph* EffectControlLinearizer::graph() const { return js_graph_->graph(); }
      39           0 : CommonOperatorBuilder* EffectControlLinearizer::common() const {
      40     1069451 :   return js_graph_->common();
      41             : }
      42           0 : SimplifiedOperatorBuilder* EffectControlLinearizer::simplified() const {
      43           0 :   return js_graph_->simplified();
      44             : }
      45           0 : MachineOperatorBuilder* EffectControlLinearizer::machine() const {
      46      336528 :   return js_graph_->machine();
      47             : }
      48             : 
      49             : namespace {
      50             : 
      51             : struct BlockEffectControlData {
      52             :   Node* current_effect = nullptr;       // New effect.
      53             :   Node* current_control = nullptr;      // New control.
      54             :   Node* current_frame_state = nullptr;  // New frame state.
      55             : };
      56             : 
      57             : class BlockEffectControlMap {
      58             :  public:
      59             :   explicit BlockEffectControlMap(Zone* temp_zone) : map_(temp_zone) {}
      60             : 
      61    18620640 :   BlockEffectControlData& For(BasicBlock* from, BasicBlock* to) {
      62    18620640 :     return map_[std::make_pair(from->rpo_number(), to->rpo_number())];
      63             :   }
      64             : 
      65             :   const BlockEffectControlData& For(BasicBlock* from, BasicBlock* to) const {
      66             :     return map_.at(std::make_pair(from->rpo_number(), to->rpo_number()));
      67             :   }
      68             : 
      69             :  private:
      70             :   typedef std::pair<int32_t, int32_t> Key;
      71             :   typedef ZoneMap<Key, BlockEffectControlData> Map;
      72             : 
      73             :   Map map_;
      74             : };
      75             : 
      76             : // Effect phis that need to be updated after the first pass.
      77             : struct PendingEffectPhi {
      78             :   Node* effect_phi;
      79             :   BasicBlock* block;
      80             : 
      81             :   PendingEffectPhi(Node* effect_phi, BasicBlock* block)
      82       40683 :       : effect_phi(effect_phi), block(block) {}
      83             : };
      84             : 
      85        2082 : void ConnectUnreachableToEnd(Node* effect, Node* control, JSGraph* jsgraph) {
      86        1041 :   Graph* graph = jsgraph->graph();
      87             :   CommonOperatorBuilder* common = jsgraph->common();
      88        2082 :   if (effect->opcode() == IrOpcode::kDead) return;
      89        1041 :   if (effect->opcode() != IrOpcode::kUnreachable) {
      90           0 :     effect = graph->NewNode(common->Unreachable(), effect, control);
      91             :   }
      92        1041 :   Node* throw_node = graph->NewNode(common->Throw(), effect, control);
      93        1041 :   NodeProperties::MergeControlToEnd(graph, common, throw_node);
      94             : }
      95             : 
      96     3305554 : void UpdateEffectPhi(Node* node, BasicBlock* block,
      97             :                      BlockEffectControlMap* block_effects, JSGraph* jsgraph) {
      98             :   // Update all inputs to an effect phi with the effects from the given
      99             :   // block->effect map.
     100             :   DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode());
     101             :   DCHECK_EQ(static_cast<size_t>(node->op()->EffectInputCount()),
     102             :             block->PredecessorCount());
     103     6785434 :   for (int i = 0; i < node->op()->EffectInputCount(); i++) {
     104             :     Node* input = node->InputAt(i);
     105     1739922 :     BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i));
     106             :     const BlockEffectControlData& block_effect =
     107             :         block_effects->For(predecessor, block);
     108     1739965 :     Node* effect = block_effect.current_effect;
     109     1739965 :     if (input != effect) {
     110      153833 :       node->ReplaceInput(i, effect);
     111             :     }
     112             :   }
     113      782825 : }
     114             : 
     115     4227938 : void UpdateBlockControl(BasicBlock* block,
     116             :                         BlockEffectControlMap* block_effects) {
     117    11991266 :   Node* control = block->NodeAt(0);
     118             :   DCHECK(NodeProperties::IsControl(control));
     119             : 
     120             :   // Do not rewire the end node.
     121     4227938 :   if (control->opcode() == IrOpcode::kEnd) return;
     122             : 
     123             :   // Update all inputs to the given control node with the correct control.
     124             :   DCHECK(control->opcode() == IrOpcode::kMerge ||
     125             :          static_cast<size_t>(control->op()->ControlInputCount()) ==
     126             :              block->PredecessorCount());
     127    11318793 :   if (static_cast<size_t>(control->op()->ControlInputCount()) !=
     128             :       block->PredecessorCount()) {
     129             :     return;  // We already re-wired the control inputs of this node.
     130             :   }
     131    19692815 :   for (int i = 0; i < control->op()->ControlInputCount(); i++) {
     132     4166191 :     Node* input = NodeProperties::GetControlInput(control, i);
     133     4166172 :     BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i));
     134             :     const BlockEffectControlData& block_effect =
     135             :         block_effects->For(predecessor, block);
     136     4166157 :     if (input != block_effect.current_control) {
     137             :       NodeProperties::ReplaceControlInput(control, block_effect.current_control,
     138       35328 :                                           i);
     139             :     }
     140             :   }
     141             : }
     142             : 
     143     6725501 : bool HasIncomingBackEdges(BasicBlock* block) {
     144    18369585 :   for (BasicBlock* pred : block->predecessors()) {
     145     6725501 :     if (pred->rpo_number() >= block->rpo_number()) {
     146             :       return true;
     147             :     }
     148             :   }
     149             :   return false;
     150             : }
     151             : 
     152      276494 : void RemoveRenameNode(Node* node) {
     153             :   DCHECK(IrOpcode::kFinishRegion == node->opcode() ||
     154             :          IrOpcode::kBeginRegion == node->opcode() ||
     155             :          IrOpcode::kTypeGuard == node->opcode());
     156             :   // Update the value/context uses to the value input of the finish node and
     157             :   // the effect uses to the effect input.
     158     3420229 :   for (Edge edge : node->use_edges()) {
     159             :     DCHECK(!edge.from()->IsDead());
     160     1433620 :     if (NodeProperties::IsEffectEdge(edge)) {
     161      277932 :       edge.UpdateTo(NodeProperties::GetEffectInput(node));
     162             :     } else {
     163             :       DCHECK(!NodeProperties::IsControlEdge(edge));
     164             :       DCHECK(!NodeProperties::IsFrameStateEdge(edge));
     165     1155689 :       edge.UpdateTo(node->InputAt(0));
     166             :     }
     167             :   }
     168      276495 :   node->Kill();
     169      276495 : }
     170             : 
     171     1146403 : void TryCloneBranch(Node* node, BasicBlock* block, Zone* temp_zone,
     172      828033 :                     Graph* graph, CommonOperatorBuilder* common,
     173             :                     BlockEffectControlMap* block_effects,
     174             :                     SourcePositionTable* source_positions,
     175             :                     NodeOriginTable* node_origins) {
     176             :   DCHECK_EQ(IrOpcode::kBranch, node->opcode());
     177             : 
     178             :   // This optimization is a special case of (super)block cloning. It takes an
     179             :   // input graph as shown below and clones the Branch node for every predecessor
     180             :   // to the Merge, essentially removing the Merge completely. This avoids
     181             :   // materializing the bit for the Phi and may offer potential for further
     182             :   // branch folding optimizations (i.e. because one or more inputs to the Phi is
     183             :   // a constant). Note that there may be more Phi nodes hanging off the Merge,
     184             :   // but we can only a certain subset of them currently (actually only Phi and
     185             :   // EffectPhi nodes whose uses have either the IfTrue or IfFalse as control
     186             :   // input).
     187             : 
     188             :   //   Control1 ... ControlN
     189             :   //      ^            ^
     190             :   //      |            |   Cond1 ... CondN
     191             :   //      +----+  +----+     ^         ^
     192             :   //           |  |          |         |
     193             :   //           |  |     +----+         |
     194             :   //          Merge<--+ | +------------+
     195             :   //            ^      \|/
     196             :   //            |      Phi
     197             :   //            |       |
     198             :   //          Branch----+
     199             :   //            ^
     200             :   //            |
     201             :   //      +-----+-----+
     202             :   //      |           |
     203             :   //    IfTrue     IfFalse
     204             :   //      ^           ^
     205             :   //      |           |
     206             : 
     207             :   // The resulting graph (modulo the Phi and EffectPhi nodes) looks like this:
     208             : 
     209             :   // Control1 Cond1 ... ControlN CondN
     210             :   //    ^      ^           ^      ^
     211             :   //    \      /           \      /
     212             :   //     Branch     ...     Branch
     213             :   //       ^                  ^
     214             :   //       |                  |
     215             :   //   +---+---+          +---+----+
     216             :   //   |       |          |        |
     217             :   // IfTrue IfFalse ... IfTrue  IfFalse
     218             :   //   ^       ^          ^        ^
     219             :   //   |       |          |        |
     220             :   //   +--+ +-------------+        |
     221             :   //      | |  +--------------+ +--+
     222             :   //      | |                 | |
     223             :   //     Merge               Merge
     224             :   //       ^                   ^
     225             :   //       |                   |
     226             : 
     227             :   SourcePositionTable::Scope scope(source_positions,
     228     1058512 :                                    source_positions->GetSourcePosition(node));
     229             :   NodeOriginTable::Scope origin_scope(node_origins, "clone branch", node);
     230       87890 :   Node* branch = node;
     231     2091527 :   Node* cond = NodeProperties::GetValueInput(branch, 0);
     232     2091529 :   if (!cond->OwnedBy(branch) || cond->opcode() != IrOpcode::kPhi) return;
     233      187749 :   Node* merge = NodeProperties::GetControlInput(branch);
     234      197557 :   if (merge->opcode() != IrOpcode::kMerge ||
     235       97699 :       NodeProperties::GetControlInput(cond) != merge) {
     236             :     return;
     237             :   }
     238             :   // Grab the IfTrue/IfFalse projections of the Branch.
     239       97624 :   BranchMatcher matcher(branch);
     240             :   // Check/collect other Phi/EffectPhi nodes hanging off the Merge.
     241             :   NodeVector phis(temp_zone);
     242      748500 :   for (Node* const use : merge->uses()) {
     243      281493 :     if (use == branch || use == cond) continue;
     244             :     // We cannot currently deal with non-Phi/EffectPhi nodes hanging off the
     245             :     // Merge. Ideally, we would just clone the nodes (and everything that
     246             :     // depends on it to some distant join point), but that requires knowledge
     247             :     // about dominance/post-dominance.
     248      104790 :     if (!NodeProperties::IsPhi(use)) return;
     249      184824 :     for (Edge edge : use->use_edges()) {
     250             :       // Right now we can only handle Phi/EffectPhi nodes whose uses are
     251             :       // directly control-dependend on either the IfTrue or the IfFalse
     252             :       // successor, because we know exactly how to update those uses.
     253       10487 :       if (edge.from()->op()->ControlInputCount() != 1) return;
     254        9215 :       Node* control = NodeProperties::GetControlInput(edge.from());
     255        9215 :       if (NodeProperties::IsPhi(edge.from())) {
     256         675 :         control = NodeProperties::GetControlInput(control, edge.index());
     257             :       }
     258        9215 :       if (control != matcher.IfTrue() && control != matcher.IfFalse()) return;
     259             :     }
     260       85324 :     phis.push_back(use);
     261             :   }
     262       87890 :   BranchHint const hint = BranchHintOf(branch->op());
     263       87891 :   int const input_count = merge->op()->ControlInputCount();
     264             :   DCHECK_LE(1, input_count);
     265       87891 :   Node** const inputs = graph->zone()->NewArray<Node*>(2 * input_count);
     266             :   Node** const merge_true_inputs = &inputs[0];
     267       87891 :   Node** const merge_false_inputs = &inputs[input_count];
     268      457962 :   for (int index = 0; index < input_count; ++index) {
     269      370071 :     Node* cond1 = NodeProperties::GetValueInput(cond, index);
     270      370071 :     Node* control1 = NodeProperties::GetControlInput(merge, index);
     271      370071 :     Node* branch1 = graph->NewNode(common->Branch(hint), cond1, control1);
     272      740142 :     merge_true_inputs[index] = graph->NewNode(common->IfTrue(), branch1);
     273      740142 :     merge_false_inputs[index] = graph->NewNode(common->IfFalse(), branch1);
     274             :   }
     275       87891 :   Node* const merge_true = matcher.IfTrue();
     276       87891 :   Node* const merge_false = matcher.IfFalse();
     277       87891 :   merge_true->TrimInputCount(0);
     278       87891 :   merge_false->TrimInputCount(0);
     279      457962 :   for (int i = 0; i < input_count; ++i) {
     280      740142 :     merge_true->AppendInput(graph->zone(), merge_true_inputs[i]);
     281      740142 :     merge_false->AppendInput(graph->zone(), merge_false_inputs[i]);
     282             :   }
     283             :   DCHECK_EQ(2u, block->SuccessorCount());
     284       87891 :   NodeProperties::ChangeOp(matcher.IfTrue(), common->Merge(input_count));
     285       87891 :   NodeProperties::ChangeOp(matcher.IfFalse(), common->Merge(input_count));
     286             :   int const true_index =
     287       87891 :       block->SuccessorAt(0)->NodeAt(0) == matcher.IfTrue() ? 0 : 1;
     288             :   BlockEffectControlData* true_block_data =
     289       87891 :       &block_effects->For(block, block->SuccessorAt(true_index));
     290             :   BlockEffectControlData* false_block_data =
     291       87891 :       &block_effects->For(block, block->SuccessorAt(true_index ^ 1));
     292      517078 :   for (Node* const phi : phis) {
     293      449931 :     for (int index = 0; index < input_count; ++index) {
     294      729214 :       inputs[index] = phi->InputAt(index);
     295             :     }
     296       85324 :     inputs[input_count] = merge_true;
     297      170648 :     Node* phi_true = graph->NewNode(phi->op(), input_count + 1, inputs);
     298       85324 :     inputs[input_count] = merge_false;
     299       85324 :     Node* phi_false = graph->NewNode(phi->op(), input_count + 1, inputs);
     300       85324 :     if (phi->UseCount() == 0) {
     301             :       DCHECK_EQ(phi->opcode(), IrOpcode::kEffectPhi);
     302             :     } else {
     303       24442 :       for (Edge edge : phi->use_edges()) {
     304        6766 :         Node* control = NodeProperties::GetControlInput(edge.from());
     305       13532 :         if (NodeProperties::IsPhi(edge.from())) {
     306         670 :           control = NodeProperties::GetControlInput(control, edge.index());
     307             :         }
     308             :         DCHECK(control == matcher.IfTrue() || control == matcher.IfFalse());
     309        6766 :         edge.UpdateTo((control == matcher.IfTrue()) ? phi_true : phi_false);
     310             :       }
     311             :     }
     312       85324 :     if (phi->opcode() == IrOpcode::kEffectPhi) {
     313       85324 :       true_block_data->current_effect = phi_true;
     314       85324 :       false_block_data->current_effect = phi_false;
     315             :     }
     316       85324 :     phi->Kill();
     317             :   }
     318             :   // Fix up IfTrue and IfFalse and kill all dead nodes.
     319       87891 :   if (branch == block->control_input()) {
     320       87891 :     true_block_data->current_control = merge_true;
     321       87891 :     false_block_data->current_control = merge_false;
     322             :   }
     323       87891 :   branch->Kill();
     324       87891 :   cond->Kill();
     325       87891 :   merge->Kill();
     326             : }
     327             : 
     328             : }  // namespace
     329             : 
     330     9665442 : void EffectControlLinearizer::Run() {
     331             :   BlockEffectControlMap block_effects(temp_zone());
     332             :   ZoneVector<PendingEffectPhi> pending_effect_phis(temp_zone());
     333             :   ZoneVector<BasicBlock*> pending_block_controls(temp_zone());
     334             :   NodeVector inputs_buffer(temp_zone());
     335             : 
     336     5140144 :   for (BasicBlock* block : *(schedule()->rpo_order())) {
     337             :     size_t instr = 0;
     338             : 
     339             :     // The control node should be the first.
     340    11412830 :     Node* control = block->NodeAt(instr);
     341             :     DCHECK(NodeProperties::IsControl(control));
     342             :     // Update the control inputs.
     343     4227943 :     if (HasIncomingBackEdges(block)) {
     344             :       // If there are back edges, we need to update later because we have not
     345             :       // computed the control yet. This should only happen for loops.
     346             :       DCHECK_EQ(IrOpcode::kLoop, control->opcode());
     347       40679 :       pending_block_controls.push_back(block);
     348             :     } else {
     349             :       // If there are no back edges, we can update now.
     350     4187264 :       UpdateBlockControl(block, &block_effects);
     351             :     }
     352             :     instr++;
     353             : 
     354             :     // Iterate over the phis and update the effect phis.
     355             :     Node* effect_phi = nullptr;
     356             :     Node* terminate = nullptr;
     357    10722926 :     for (; instr < block->NodeCount(); instr++) {
     358     3758130 :       Node* node = block->NodeAt(instr);
     359             :       // Only go through the phis and effect phis.
     360     3758130 :       if (node->opcode() == IrOpcode::kEffectPhi) {
     361             :         // There should be at most one effect phi in a block.
     362             :         DCHECK_NULL(effect_phi);
     363             :         // IfException blocks should not have effect phis.
     364             :         DCHECK_NE(IrOpcode::kIfException, control->opcode());
     365             :         effect_phi = node;
     366     2986200 :       } else if (node->opcode() == IrOpcode::kPhi) {
     367             :         // Just skip phis.
     368     2665344 :       } else if (node->opcode() == IrOpcode::kTerminate) {
     369             :         DCHECK_NULL(terminate);
     370             :         terminate = node;
     371             :       } else {
     372             :         break;
     373             :       }
     374             :     }
     375             : 
     376     4227940 :     if (effect_phi) {
     377             :       // Make sure we update the inputs to the incoming blocks' effects.
     378      771975 :       if (HasIncomingBackEdges(block)) {
     379             :         // In case of loops, we do not update the effect phi immediately
     380             :         // because the back predecessor has not been handled yet. We just
     381             :         // record the effect phi for later processing.
     382       40676 :         pending_effect_phis.push_back(PendingEffectPhi(effect_phi, block));
     383             :       } else {
     384      731299 :         UpdateEffectPhi(effect_phi, block, &block_effects, jsgraph());
     385             :       }
     386             :     }
     387             : 
     388     4227962 :     Node* effect = effect_phi;
     389     4227962 :     if (effect == nullptr) {
     390             :       // There was no effect phi.
     391     3455960 :       if (block == schedule()->start()) {
     392             :         // Start block => effect is start.
     393             :         DCHECK_EQ(graph()->start(), control);
     394      456089 :         effect = graph()->start();
     395     8544546 :       } else if (control->opcode() == IrOpcode::kEnd) {
     396             :         // End block is just a dummy, no effect needed.
     397             :         DCHECK_EQ(BasicBlock::kNone, block->control());
     398             :         DCHECK_EQ(1u, block->size());
     399      455013 :         effect = nullptr;
     400             :       } else {
     401             :         // If all the predecessors have the same effect, we can use it as our
     402             :         // current effect.
     403     7770928 :         for (size_t i = 0; i < block->PredecessorCount(); ++i) {
     404             :           const BlockEffectControlData& data =
     405             :               block_effects.For(block->PredecessorAt(i), block);
     406     2623879 :           if (!effect) effect = data.current_effect;
     407     2623879 :           if (data.current_effect != effect) {
     408       10844 :             effect = nullptr;
     409       10844 :             break;
     410             :           }
     411             :         }
     412     2544804 :         if (effect == nullptr) {
     413             :           DCHECK_NE(IrOpcode::kIfException, control->opcode());
     414             :           // The input blocks do not have the same effect. We have
     415             :           // to create an effect phi node.
     416             :           inputs_buffer.clear();
     417       21688 :           inputs_buffer.resize(block->PredecessorCount(), jsgraph()->Dead());
     418       10844 :           inputs_buffer.push_back(control);
     419             :           effect = graph()->NewNode(
     420       10844 :               common()->EffectPhi(static_cast<int>(block->PredecessorCount())),
     421       54220 :               static_cast<int>(inputs_buffer.size()), &(inputs_buffer.front()));
     422             :           // For loops, we update the effect phi node later to break cycles.
     423       21688 :           if (control->opcode() == IrOpcode::kLoop) {
     424          14 :             pending_effect_phis.push_back(PendingEffectPhi(effect, block));
     425             :           } else {
     426       10837 :             UpdateEffectPhi(effect, block, &block_effects, jsgraph());
     427             :           }
     428     5067920 :         } else if (control->opcode() == IrOpcode::kIfException) {
     429             :           // The IfException is connected into the effect chain, so we need
     430             :           // to update the effect here.
     431      164924 :           NodeProperties::ReplaceEffectInput(control, effect);
     432      164924 :           effect = control;
     433             :         }
     434             :       }
     435             :     }
     436             : 
     437             :     // Fixup the Terminate node.
     438     4227908 :     if (terminate != nullptr) {
     439       40682 :       NodeProperties::ReplaceEffectInput(terminate, effect);
     440             :     }
     441             : 
     442             :     // The frame state at block entry is determined by the frame states leaving
     443             :     // all predecessors. In case there is no frame state dominating this block,
     444             :     // we can rely on a checkpoint being present before the next deoptimization.
     445             :     // TODO(mstarzinger): Eventually we will need to go hunt for a frame state
     446             :     // once deoptimizing nodes roam freely through the schedule.
     447     4227908 :     Node* frame_state = nullptr;
     448     4227908 :     if (block != schedule()->start()) {
     449             :       // If all the predecessors have the same effect, we can use it
     450             :       // as our current effect.
     451             :       frame_state =
     452     3771823 :           block_effects.For(block->PredecessorAt(0), block).current_frame_state;
     453     9521998 :       for (size_t i = 1; i < block->PredecessorCount(); i++) {
     454     1132202 :         if (block_effects.For(block->PredecessorAt(i), block)
     455     1132202 :                 .current_frame_state != frame_state) {
     456      143026 :           frame_state = nullptr;
     457      143026 :           frame_state_zapper_ = graph()->end();
     458      143026 :           break;
     459             :         }
     460             :       }
     461             :     }
     462             : 
     463             :     // Process the ordinary instructions.
     464    64203261 :     for (; instr < block->NodeCount(); instr++) {
     465             :       Node* node = block->NodeAt(instr);
     466    29987693 :       ProcessNode(node, &frame_state, &effect, &control);
     467             :     }
     468             : 
     469     4227904 :     switch (block->control()) {
     470             :       case BasicBlock::kGoto:
     471             :       case BasicBlock::kNone:
     472             :         break;
     473             : 
     474             :       case BasicBlock::kCall:
     475             :       case BasicBlock::kTailCall:
     476             :       case BasicBlock::kSwitch:
     477             :       case BasicBlock::kReturn:
     478             :       case BasicBlock::kDeoptimize:
     479             :       case BasicBlock::kThrow:
     480      839914 :         ProcessNode(block->control_input(), &frame_state, &effect, &control);
     481      839915 :         break;
     482             : 
     483             :       case BasicBlock::kBranch:
     484     1058519 :         ProcessNode(block->control_input(), &frame_state, &effect, &control);
     485             :         TryCloneBranch(block->control_input(), block, temp_zone(), graph(),
     486             :                        common(), &block_effects, source_positions_,
     487     3175650 :                        node_origins_);
     488     1058544 :         break;
     489             :     }
     490             : 
     491             :     // Store the effect, control and frame state for later use.
     492    17694655 :     for (BasicBlock* successor : block->successors()) {
     493     5010831 :       BlockEffectControlData* data = &block_effects.For(block, successor);
     494     5010865 :       if (data->current_effect == nullptr) {
     495     4840185 :         data->current_effect = effect;
     496             :       }
     497     5010865 :       if (data->current_control == nullptr) {
     498     4835063 :         data->current_control = control;
     499             :       }
     500     5010865 :       data->current_frame_state = frame_state;
     501             :     }
     502             :   }
     503             : 
     504      952905 :   for (BasicBlock* pending_block_control : pending_block_controls) {
     505       40683 :     UpdateBlockControl(pending_block_control, &block_effects);
     506             :   }
     507             :   // Update the incoming edges of the effect phis that could not be processed
     508             :   // during the first pass (because they could have incoming back edges).
     509      952905 :   for (const PendingEffectPhi& pending_effect_phi : pending_effect_phis) {
     510             :     UpdateEffectPhi(pending_effect_phi.effect_phi, pending_effect_phi.block,
     511       40683 :                     &block_effects, jsgraph());
     512             :   }
     513      456116 : }
     514             : 
     515   162310626 : void EffectControlLinearizer::ProcessNode(Node* node, Node** frame_state,
     516        2082 :                                           Node** effect, Node** control) {
     517             :   SourcePositionTable::Scope scope(source_positions_,
     518    31886012 :                                    source_positions_->GetSourcePosition(node));
     519    31886062 :   NodeOriginTable::Scope origin_scope(node_origins_, "process node", node);
     520             : 
     521             :   // If the node needs to be wired into the effect/control chain, do this
     522             :   // here. Pass current frame state for lowering to eager deoptimization.
     523    31886062 :   if (TryWireInStateEffect(node, *frame_state, effect, control)) {
     524             :     return;
     525             :   }
     526             : 
     527             :   // If the node has a visible effect, then there must be a checkpoint in the
     528             :   // effect chain before we are allowed to place another eager deoptimization
     529             :   // point. We zap the frame state to ensure this invariant is maintained.
     530    60693423 :   if (region_observability_ == RegionObservability::kObservable &&
     531             :       !node->op()->HasProperty(Operator::kNoWrite)) {
     532     3280489 :     *frame_state = nullptr;
     533     3280489 :     frame_state_zapper_ = node;
     534             :   }
     535             : 
     536             :   // Remove the end markers of 'atomic' allocation region because the
     537             :   // region should be wired-in now.
     538    30824514 :   if (node->opcode() == IrOpcode::kFinishRegion) {
     539             :     // Reset the current region observability.
     540      128061 :     region_observability_ = RegionObservability::kObservable;
     541             :     // Update the value uses to the value input of the finish node and
     542             :     // the effect uses to the effect input.
     543      128061 :     return RemoveRenameNode(node);
     544             :   }
     545    30696453 :   if (node->opcode() == IrOpcode::kBeginRegion) {
     546             :     // Determine the observability for this region and use that for all
     547             :     // nodes inside the region (i.e. ignore the absence of kNoWrite on
     548             :     // StoreField and other operators).
     549             :     DCHECK_NE(RegionObservability::kNotObservable, region_observability_);
     550      128061 :     region_observability_ = RegionObservabilityOf(node->op());
     551             :     // Update the value uses to the value input of the finish node and
     552             :     // the effect uses to the effect input.
     553      128061 :     return RemoveRenameNode(node);
     554             :   }
     555    30568392 :   if (node->opcode() == IrOpcode::kTypeGuard) {
     556       20373 :     return RemoveRenameNode(node);
     557             :   }
     558             : 
     559             :   // Special treatment for checkpoint nodes.
     560    30548019 :   if (node->opcode() == IrOpcode::kCheckpoint) {
     561             :     // Unlink the check point; effect uses will be updated to the incoming
     562             :     // effect that is passed. The frame state is preserved for lowering.
     563             :     DCHECK_EQ(RegionObservability::kObservable, region_observability_);
     564     2493666 :     *frame_state = NodeProperties::GetFrameStateInput(node);
     565     2493668 :     return;
     566             :   }
     567             : 
     568             :   // The IfSuccess nodes should always start a basic block (and basic block
     569             :   // start nodes are not handled in the ProcessNode method).
     570             :   DCHECK_NE(IrOpcode::kIfSuccess, node->opcode());
     571             : 
     572             :   // If the node takes an effect, replace with the current one.
     573    56108706 :   if (node->op()->EffectInputCount() > 0) {
     574             :     DCHECK_EQ(1, node->op()->EffectInputCount());
     575     6512084 :     Node* input_effect = NodeProperties::GetEffectInput(node);
     576             : 
     577     6512084 :     if (input_effect != *effect) {
     578     2478916 :       NodeProperties::ReplaceEffectInput(node, *effect);
     579             :     }
     580             : 
     581             :     // If the node produces an effect, update our current effect. (However,
     582             :     // ignore new effect chains started with ValueEffect.)
     583    13024184 :     if (node->op()->EffectOutputCount() > 0) {
     584             :       DCHECK_EQ(1, node->op()->EffectOutputCount());
     585     5843179 :       *effect = node;
     586             :     }
     587             :   } else {
     588             :     // New effect chain is only started with a Start or ValueEffect node.
     589             :     DCHECK(node->op()->EffectOutputCount() == 0 ||
     590             :            node->opcode() == IrOpcode::kStart);
     591             :   }
     592             : 
     593             :   // Rewire control inputs.
     594    77439856 :   for (int i = 0; i < node->op()->ControlInputCount(); i++) {
     595     7110379 :     NodeProperties::ReplaceControlInput(node, *control, i);
     596             :   }
     597             :   // Update the current control.
     598    56108720 :   if (node->op()->ControlOutputCount() > 0) {
     599     4364394 :     *control = node;
     600             :   }
     601             : 
     602             :   // Break the effect chain on {Unreachable} and reconnect to the graph end.
     603             :   // Mark the following code for deletion by connecting to the {Dead} node.
     604    28054360 :   if (node->opcode() == IrOpcode::kUnreachable) {
     605        1041 :     ConnectUnreachableToEnd(*effect, *control, jsgraph());
     606        1041 :     *effect = *control = jsgraph()->Dead();
     607             :   }
     608             : }
     609             : 
     610    64833703 : bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
     611             :                                                    Node* frame_state,
     612             :                                                    Node** effect,
     613             :                                                    Node** control) {
     614    31886050 :   gasm()->Reset(*effect, *control);
     615             :   Node* result = nullptr;
     616    31886067 :   switch (node->opcode()) {
     617             :     case IrOpcode::kChangeBitToTagged:
     618       16462 :       result = LowerChangeBitToTagged(node);
     619       16462 :       break;
     620             :     case IrOpcode::kChangeInt31ToTaggedSigned:
     621       38566 :       result = LowerChangeInt31ToTaggedSigned(node);
     622       38566 :       break;
     623             :     case IrOpcode::kChangeInt32ToTagged:
     624       35400 :       result = LowerChangeInt32ToTagged(node);
     625       35400 :       break;
     626             :     case IrOpcode::kChangeInt64ToTagged:
     627         260 :       result = LowerChangeInt64ToTagged(node);
     628         260 :       break;
     629             :     case IrOpcode::kChangeUint32ToTagged:
     630         542 :       result = LowerChangeUint32ToTagged(node);
     631         542 :       break;
     632             :     case IrOpcode::kChangeUint64ToTagged:
     633          81 :       result = LowerChangeUint64ToTagged(node);
     634          81 :       break;
     635             :     case IrOpcode::kChangeFloat64ToTagged:
     636       52985 :       result = LowerChangeFloat64ToTagged(node);
     637       52986 :       break;
     638             :     case IrOpcode::kChangeFloat64ToTaggedPointer:
     639          91 :       result = LowerChangeFloat64ToTaggedPointer(node);
     640          91 :       break;
     641             :     case IrOpcode::kChangeTaggedSignedToInt32:
     642       52640 :       result = LowerChangeTaggedSignedToInt32(node);
     643       52640 :       break;
     644             :     case IrOpcode::kChangeTaggedSignedToInt64:
     645        1893 :       result = LowerChangeTaggedSignedToInt64(node);
     646        1893 :       break;
     647             :     case IrOpcode::kChangeTaggedToBit:
     648      127535 :       result = LowerChangeTaggedToBit(node);
     649      127535 :       break;
     650             :     case IrOpcode::kChangeTaggedToInt32:
     651        1882 :       result = LowerChangeTaggedToInt32(node);
     652        1882 :       break;
     653             :     case IrOpcode::kChangeTaggedToUint32:
     654         564 :       result = LowerChangeTaggedToUint32(node);
     655         564 :       break;
     656             :     case IrOpcode::kChangeTaggedToInt64:
     657          12 :       result = LowerChangeTaggedToInt64(node);
     658          12 :       break;
     659             :     case IrOpcode::kChangeTaggedToFloat64:
     660             :       result = LowerChangeTaggedToFloat64(node);
     661       10774 :       break;
     662             :     case IrOpcode::kChangeTaggedToTaggedSigned:
     663          15 :       result = LowerChangeTaggedToTaggedSigned(node);
     664          15 :       break;
     665             :     case IrOpcode::kTruncateTaggedToBit:
     666       40938 :       result = LowerTruncateTaggedToBit(node);
     667       40939 :       break;
     668             :     case IrOpcode::kTruncateTaggedPointerToBit:
     669         473 :       result = LowerTruncateTaggedPointerToBit(node);
     670         473 :       break;
     671             :     case IrOpcode::kTruncateTaggedToFloat64:
     672         743 :       result = LowerTruncateTaggedToFloat64(node);
     673         743 :       break;
     674             :     case IrOpcode::kPoisonIndex:
     675        1167 :       result = LowerPoisonIndex(node);
     676        1167 :       break;
     677             :     case IrOpcode::kCheckMaps:
     678       55458 :       LowerCheckMaps(node, frame_state);
     679       55459 :       break;
     680             :     case IrOpcode::kCompareMaps:
     681        5713 :       result = LowerCompareMaps(node);
     682        5713 :       break;
     683             :     case IrOpcode::kCheckNumber:
     684         519 :       result = LowerCheckNumber(node, frame_state);
     685         519 :       break;
     686             :     case IrOpcode::kCheckReceiver:
     687         815 :       result = LowerCheckReceiver(node, frame_state);
     688         815 :       break;
     689             :     case IrOpcode::kCheckReceiverOrNullOrUndefined:
     690          87 :       result = LowerCheckReceiverOrNullOrUndefined(node, frame_state);
     691          87 :       break;
     692             :     case IrOpcode::kCheckSymbol:
     693          37 :       result = LowerCheckSymbol(node, frame_state);
     694          37 :       break;
     695             :     case IrOpcode::kCheckString:
     696        6323 :       result = LowerCheckString(node, frame_state);
     697        6323 :       break;
     698             :     case IrOpcode::kCheckInternalizedString:
     699        1430 :       result = LowerCheckInternalizedString(node, frame_state);
     700        1430 :       break;
     701             :     case IrOpcode::kCheckIf:
     702       15244 :       LowerCheckIf(node, frame_state);
     703       15244 :       break;
     704             :     case IrOpcode::kCheckedInt32Add:
     705       56282 :       result = LowerCheckedInt32Add(node, frame_state);
     706       56284 :       break;
     707             :     case IrOpcode::kCheckedInt32Sub:
     708        7527 :       result = LowerCheckedInt32Sub(node, frame_state);
     709        7527 :       break;
     710             :     case IrOpcode::kCheckedInt32Div:
     711         243 :       result = LowerCheckedInt32Div(node, frame_state);
     712         243 :       break;
     713             :     case IrOpcode::kCheckedInt32Mod:
     714         856 :       result = LowerCheckedInt32Mod(node, frame_state);
     715         856 :       break;
     716             :     case IrOpcode::kCheckedUint32Div:
     717          49 :       result = LowerCheckedUint32Div(node, frame_state);
     718          49 :       break;
     719             :     case IrOpcode::kCheckedUint32Mod:
     720          37 :       result = LowerCheckedUint32Mod(node, frame_state);
     721          37 :       break;
     722             :     case IrOpcode::kCheckedInt32Mul:
     723        5673 :       result = LowerCheckedInt32Mul(node, frame_state);
     724        5673 :       break;
     725             :     case IrOpcode::kCheckedInt32ToTaggedSigned:
     726           0 :       result = LowerCheckedInt32ToTaggedSigned(node, frame_state);
     727           0 :       break;
     728             :     case IrOpcode::kCheckedInt64ToInt32:
     729           7 :       result = LowerCheckedInt64ToInt32(node, frame_state);
     730           7 :       break;
     731             :     case IrOpcode::kCheckedInt64ToTaggedSigned:
     732        1725 :       result = LowerCheckedInt64ToTaggedSigned(node, frame_state);
     733        1725 :       break;
     734             :     case IrOpcode::kCheckedUint32Bounds:
     735       44198 :       result = LowerCheckedUint32Bounds(node, frame_state);
     736       44198 :       break;
     737             :     case IrOpcode::kCheckedUint32ToInt32:
     738         253 :       result = LowerCheckedUint32ToInt32(node, frame_state);
     739         253 :       break;
     740             :     case IrOpcode::kCheckedUint32ToTaggedSigned:
     741          14 :       result = LowerCheckedUint32ToTaggedSigned(node, frame_state);
     742          14 :       break;
     743             :     case IrOpcode::kCheckedUint64Bounds:
     744         192 :       result = LowerCheckedUint64Bounds(node, frame_state);
     745         192 :       break;
     746             :     case IrOpcode::kCheckedUint64ToInt32:
     747           0 :       result = LowerCheckedUint64ToInt32(node, frame_state);
     748           0 :       break;
     749             :     case IrOpcode::kCheckedUint64ToTaggedSigned:
     750           0 :       result = LowerCheckedUint64ToTaggedSigned(node, frame_state);
     751           0 :       break;
     752             :     case IrOpcode::kCheckedFloat64ToInt32:
     753        2350 :       result = LowerCheckedFloat64ToInt32(node, frame_state);
     754        2350 :       break;
     755             :     case IrOpcode::kCheckedFloat64ToInt64:
     756          14 :       result = LowerCheckedFloat64ToInt64(node, frame_state);
     757          14 :       break;
     758             :     case IrOpcode::kCheckedTaggedSignedToInt32:
     759       24835 :       if (frame_state == nullptr) {
     760           0 :         FATAL("No frame state (zapped by #%d: %s)", frame_state_zapper_->id(),
     761           0 :               frame_state_zapper_->op()->mnemonic());
     762             :       }
     763       24835 :       result = LowerCheckedTaggedSignedToInt32(node, frame_state);
     764       24836 :       break;
     765             :     case IrOpcode::kCheckedTaggedToInt32:
     766        2400 :       result = LowerCheckedTaggedToInt32(node, frame_state);
     767        2400 :       break;
     768             :     case IrOpcode::kCheckedTaggedToInt64:
     769          70 :       result = LowerCheckedTaggedToInt64(node, frame_state);
     770          70 :       break;
     771             :     case IrOpcode::kCheckedTaggedToFloat64:
     772       58011 :       result = LowerCheckedTaggedToFloat64(node, frame_state);
     773       58011 :       break;
     774             :     case IrOpcode::kCheckedTaggedToTaggedSigned:
     775       19906 :       result = LowerCheckedTaggedToTaggedSigned(node, frame_state);
     776       19906 :       break;
     777             :     case IrOpcode::kCheckedTaggedToTaggedPointer:
     778       35936 :       result = LowerCheckedTaggedToTaggedPointer(node, frame_state);
     779       35937 :       break;
     780             :     case IrOpcode::kTruncateTaggedToWord32:
     781         423 :       result = LowerTruncateTaggedToWord32(node);
     782         423 :       break;
     783             :     case IrOpcode::kCheckedTruncateTaggedToWord32:
     784        1311 :       result = LowerCheckedTruncateTaggedToWord32(node, frame_state);
     785        1311 :       break;
     786             :     case IrOpcode::kNumberToString:
     787        1092 :       result = LowerNumberToString(node);
     788        1092 :       break;
     789             :     case IrOpcode::kObjectIsArrayBufferView:
     790          16 :       result = LowerObjectIsArrayBufferView(node);
     791          16 :       break;
     792             :     case IrOpcode::kObjectIsBigInt:
     793          25 :       result = LowerObjectIsBigInt(node);
     794          25 :       break;
     795             :     case IrOpcode::kObjectIsCallable:
     796          98 :       result = LowerObjectIsCallable(node);
     797          98 :       break;
     798             :     case IrOpcode::kObjectIsConstructor:
     799         206 :       result = LowerObjectIsConstructor(node);
     800         206 :       break;
     801             :     case IrOpcode::kObjectIsDetectableCallable:
     802       13424 :       result = LowerObjectIsDetectableCallable(node);
     803       13424 :       break;
     804             :     case IrOpcode::kObjectIsMinusZero:
     805          21 :       result = LowerObjectIsMinusZero(node);
     806          21 :       break;
     807             :     case IrOpcode::kNumberIsMinusZero:
     808          92 :       result = LowerNumberIsMinusZero(node);
     809          92 :       break;
     810             :     case IrOpcode::kObjectIsNaN:
     811         685 :       result = LowerObjectIsNaN(node);
     812         685 :       break;
     813             :     case IrOpcode::kNumberIsNaN:
     814       10327 :       result = LowerNumberIsNaN(node);
     815       10327 :       break;
     816             :     case IrOpcode::kObjectIsNonCallable:
     817        5753 :       result = LowerObjectIsNonCallable(node);
     818        5753 :       break;
     819             :     case IrOpcode::kObjectIsNumber:
     820        7213 :       result = LowerObjectIsNumber(node);
     821        7213 :       break;
     822             :     case IrOpcode::kObjectIsReceiver:
     823       18237 :       result = LowerObjectIsReceiver(node);
     824       18237 :       break;
     825             :     case IrOpcode::kObjectIsSmi:
     826        4720 :       result = LowerObjectIsSmi(node);
     827        4720 :       break;
     828             :     case IrOpcode::kObjectIsString:
     829        1921 :       result = LowerObjectIsString(node);
     830        1921 :       break;
     831             :     case IrOpcode::kObjectIsSymbol:
     832          20 :       result = LowerObjectIsSymbol(node);
     833          20 :       break;
     834             :     case IrOpcode::kObjectIsUndetectable:
     835        1303 :       result = LowerObjectIsUndetectable(node);
     836        1303 :       break;
     837             :     case IrOpcode::kArgumentsFrame:
     838       16640 :       result = LowerArgumentsFrame(node);
     839       16640 :       break;
     840             :     case IrOpcode::kArgumentsLength:
     841       16668 :       result = LowerArgumentsLength(node);
     842       16668 :       break;
     843             :     case IrOpcode::kToBoolean:
     844         218 :       result = LowerToBoolean(node);
     845         218 :       break;
     846             :     case IrOpcode::kTypeOf:
     847       18996 :       result = LowerTypeOf(node);
     848       18996 :       break;
     849             :     case IrOpcode::kNewDoubleElements:
     850          28 :       result = LowerNewDoubleElements(node);
     851          28 :       break;
     852             :     case IrOpcode::kNewSmiOrObjectElements:
     853         507 :       result = LowerNewSmiOrObjectElements(node);
     854         507 :       break;
     855             :     case IrOpcode::kNewArgumentsElements:
     856       16155 :       result = LowerNewArgumentsElements(node);
     857       16155 :       break;
     858             :     case IrOpcode::kNewConsString:
     859        3328 :       result = LowerNewConsString(node);
     860        3328 :       break;
     861             :     case IrOpcode::kSameValue:
     862          12 :       result = LowerSameValue(node);
     863          12 :       break;
     864             :     case IrOpcode::kDeadValue:
     865        1243 :       result = LowerDeadValue(node);
     866        1243 :       break;
     867             :     case IrOpcode::kStringConcat:
     868       18931 :       result = LowerStringConcat(node);
     869       18931 :       break;
     870             :     case IrOpcode::kStringFromSingleCharCode:
     871         966 :       result = LowerStringFromSingleCharCode(node);
     872         966 :       break;
     873             :     case IrOpcode::kStringFromSingleCodePoint:
     874         222 :       result = LowerStringFromSingleCodePoint(node);
     875         222 :       break;
     876             :     case IrOpcode::kStringIndexOf:
     877         289 :       result = LowerStringIndexOf(node);
     878         289 :       break;
     879             :     case IrOpcode::kStringLength:
     880       21117 :       result = LowerStringLength(node);
     881       21117 :       break;
     882             :     case IrOpcode::kStringToNumber:
     883         344 :       result = LowerStringToNumber(node);
     884         344 :       break;
     885             :     case IrOpcode::kStringCharCodeAt:
     886        2398 :       result = LowerStringCharCodeAt(node);
     887        2398 :       break;
     888             :     case IrOpcode::kStringCodePointAt:
     889         249 :       result = LowerStringCodePointAt(node, UnicodeEncodingOf(node->op()));
     890         249 :       break;
     891             :     case IrOpcode::kStringToLowerCaseIntl:
     892          88 :       result = LowerStringToLowerCaseIntl(node);
     893          88 :       break;
     894             :     case IrOpcode::kStringToUpperCaseIntl:
     895          28 :       result = LowerStringToUpperCaseIntl(node);
     896          28 :       break;
     897             :     case IrOpcode::kStringSubstring:
     898        1081 :       result = LowerStringSubstring(node);
     899        1081 :       break;
     900             :     case IrOpcode::kStringEqual:
     901       10236 :       result = LowerStringEqual(node);
     902       10236 :       break;
     903             :     case IrOpcode::kStringLessThan:
     904         251 :       result = LowerStringLessThan(node);
     905         251 :       break;
     906             :     case IrOpcode::kStringLessThanOrEqual:
     907         865 :       result = LowerStringLessThanOrEqual(node);
     908         865 :       break;
     909             :     case IrOpcode::kNumberIsFloat64Hole:
     910          66 :       result = LowerNumberIsFloat64Hole(node);
     911          66 :       break;
     912             :     case IrOpcode::kNumberIsFinite:
     913         141 :       result = LowerNumberIsFinite(node);
     914         141 :       break;
     915             :     case IrOpcode::kObjectIsFiniteNumber:
     916           7 :       result = LowerObjectIsFiniteNumber(node);
     917           7 :       break;
     918             :     case IrOpcode::kNumberIsInteger:
     919         119 :       result = LowerNumberIsInteger(node);
     920         119 :       break;
     921             :     case IrOpcode::kObjectIsInteger:
     922           7 :       result = LowerObjectIsInteger(node);
     923           7 :       break;
     924             :     case IrOpcode::kNumberIsSafeInteger:
     925           7 :       result = LowerNumberIsSafeInteger(node);
     926           7 :       break;
     927             :     case IrOpcode::kObjectIsSafeInteger:
     928           7 :       result = LowerObjectIsSafeInteger(node);
     929           7 :       break;
     930             :     case IrOpcode::kCheckFloat64Hole:
     931         471 :       result = LowerCheckFloat64Hole(node, frame_state);
     932         471 :       break;
     933             :     case IrOpcode::kCheckNotTaggedHole:
     934          93 :       result = LowerCheckNotTaggedHole(node, frame_state);
     935          93 :       break;
     936             :     case IrOpcode::kConvertTaggedHoleToUndefined:
     937        1507 :       result = LowerConvertTaggedHoleToUndefined(node);
     938        1507 :       break;
     939             :     case IrOpcode::kCheckEqualsInternalizedString:
     940          57 :       LowerCheckEqualsInternalizedString(node, frame_state);
     941          57 :       break;
     942             :     case IrOpcode::kAllocate:
     943      112045 :       result = LowerAllocate(node);
     944      112045 :       break;
     945             :     case IrOpcode::kCheckEqualsSymbol:
     946          19 :       LowerCheckEqualsSymbol(node, frame_state);
     947          19 :       break;
     948             :     case IrOpcode::kPlainPrimitiveToNumber:
     949          23 :       result = LowerPlainPrimitiveToNumber(node);
     950          23 :       break;
     951             :     case IrOpcode::kPlainPrimitiveToWord32:
     952           9 :       result = LowerPlainPrimitiveToWord32(node);
     953           9 :       break;
     954             :     case IrOpcode::kPlainPrimitiveToFloat64:
     955           0 :       result = LowerPlainPrimitiveToFloat64(node);
     956           0 :       break;
     957             :     case IrOpcode::kEnsureWritableFastElements:
     958        1746 :       result = LowerEnsureWritableFastElements(node);
     959        1746 :       break;
     960             :     case IrOpcode::kMaybeGrowFastElements:
     961        3665 :       result = LowerMaybeGrowFastElements(node, frame_state);
     962        3665 :       break;
     963             :     case IrOpcode::kTransitionElementsKind:
     964         592 :       LowerTransitionElementsKind(node);
     965         592 :       break;
     966             :     case IrOpcode::kLoadFieldByIndex:
     967        1036 :       result = LowerLoadFieldByIndex(node);
     968        1036 :       break;
     969             :     case IrOpcode::kLoadTypedElement:
     970        4594 :       result = LowerLoadTypedElement(node);
     971        4594 :       break;
     972             :     case IrOpcode::kLoadDataViewElement:
     973         268 :       result = LowerLoadDataViewElement(node);
     974         268 :       break;
     975             :     case IrOpcode::kStoreTypedElement:
     976        4162 :       LowerStoreTypedElement(node);
     977        4162 :       break;
     978             :     case IrOpcode::kStoreDataViewElement:
     979         197 :       LowerStoreDataViewElement(node);
     980         197 :       break;
     981             :     case IrOpcode::kStoreSignedSmallElement:
     982          78 :       LowerStoreSignedSmallElement(node);
     983          78 :       break;
     984             :     case IrOpcode::kFindOrderedHashMapEntry:
     985         190 :       result = LowerFindOrderedHashMapEntry(node);
     986         190 :       break;
     987             :     case IrOpcode::kFindOrderedHashMapEntryForInt32Key:
     988          15 :       result = LowerFindOrderedHashMapEntryForInt32Key(node);
     989          15 :       break;
     990             :     case IrOpcode::kTransitionAndStoreNumberElement:
     991          22 :       LowerTransitionAndStoreNumberElement(node);
     992          22 :       break;
     993             :     case IrOpcode::kTransitionAndStoreNonNumberElement:
     994          21 :       LowerTransitionAndStoreNonNumberElement(node);
     995          21 :       break;
     996             :     case IrOpcode::kTransitionAndStoreElement:
     997          81 :       LowerTransitionAndStoreElement(node);
     998          81 :       break;
     999             :     case IrOpcode::kRuntimeAbort:
    1000        2463 :       LowerRuntimeAbort(node);
    1001        2463 :       break;
    1002             :     case IrOpcode::kConvertReceiver:
    1003         892 :       result = LowerConvertReceiver(node);
    1004         892 :       break;
    1005             :     case IrOpcode::kFloat64RoundUp:
    1006       16446 :       if (!LowerFloat64RoundUp(node).To(&result)) {
    1007             :         return false;
    1008             :       }
    1009             :       break;
    1010             :     case IrOpcode::kFloat64RoundDown:
    1011       51816 :       if (!LowerFloat64RoundDown(node).To(&result)) {
    1012             :         return false;
    1013             :       }
    1014             :       break;
    1015             :     case IrOpcode::kFloat64RoundTruncate:
    1016       13824 :       if (!LowerFloat64RoundTruncate(node).To(&result)) {
    1017             :         return false;
    1018             :       }
    1019             :       break;
    1020             :     case IrOpcode::kFloat64RoundTiesEven:
    1021         532 :       if (!LowerFloat64RoundTiesEven(node).To(&result)) {
    1022             :         return false;
    1023             :       }
    1024             :       break;
    1025             :     case IrOpcode::kDateNow:
    1026           7 :       result = LowerDateNow(node);
    1027           7 :       break;
    1028             :     default:
    1029             :       return false;
    1030             :   }
    1031             : 
    1032     3184758 :   if ((result ? 1 : 0) != node->op()->ValueOutputCount()) {
    1033           0 :     FATAL(
    1034             :         "Effect control linearizer lowering of '%s':"
    1035             :         " value output count does not agree.",
    1036           0 :         node->op()->mnemonic());
    1037             :   }
    1038             : 
    1039     1061586 :   *effect = gasm()->ExtractCurrentEffect();
    1040     1061587 :   *control = gasm()->ExtractCurrentControl();
    1041     1061587 :   NodeProperties::ReplaceUses(node, result, *effect, *control);
    1042     1061587 :   return true;
    1043             : }
    1044             : 
    1045             : #define __ gasm()->
    1046             : 
    1047       52985 : Node* EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node) {
    1048       52985 :   CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
    1049             :   Node* value = node->InputAt(0);
    1050             : 
    1051       52986 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    1052       52986 :   auto if_heapnumber = __ MakeDeferredLabel();
    1053       52986 :   auto if_int32 = __ MakeLabel();
    1054             : 
    1055       52986 :   Node* value32 = __ RoundFloat64ToInt32(value);
    1056             :   __ GotoIf(__ Float64Equal(value, __ ChangeInt32ToFloat64(value32)),
    1057       52985 :             &if_int32);
    1058             :   __ Goto(&if_heapnumber);
    1059             : 
    1060             :   __ Bind(&if_int32);
    1061             :   {
    1062       52986 :     if (mode == CheckForMinusZeroMode::kCheckForMinusZero) {
    1063       40325 :       Node* zero = __ Int32Constant(0);
    1064       40325 :       auto if_zero = __ MakeDeferredLabel();
    1065       40325 :       auto if_smi = __ MakeLabel();
    1066             : 
    1067       40325 :       __ GotoIf(__ Word32Equal(value32, zero), &if_zero);
    1068             :       __ Goto(&if_smi);
    1069             : 
    1070             :       __ Bind(&if_zero);
    1071             :       {
    1072             :         // In case of 0, we need to check the high bits for the IEEE -0 pattern.
    1073             :         __ GotoIf(__ Int32LessThan(__ Float64ExtractHighWord32(value), zero),
    1074       40325 :                   &if_heapnumber);
    1075             :         __ Goto(&if_smi);
    1076             :       }
    1077             : 
    1078             :       __ Bind(&if_smi);
    1079             :     }
    1080             : 
    1081             :     if (SmiValuesAre32Bits()) {
    1082       52986 :       Node* value_smi = ChangeInt32ToSmi(value32);
    1083             :       __ Goto(&done, value_smi);
    1084             :     } else {
    1085             :       DCHECK(SmiValuesAre31Bits());
    1086             :       Node* add = __ Int32AddWithOverflow(value32, value32);
    1087             :       Node* ovf = __ Projection(1, add);
    1088             :       __ GotoIf(ovf, &if_heapnumber);
    1089             :       Node* value_smi = __ Projection(0, add);
    1090             :       value_smi = ChangeInt32ToIntPtr(value_smi);
    1091             :       __ Goto(&done, value_smi);
    1092             :     }
    1093             :   }
    1094             : 
    1095             :   __ Bind(&if_heapnumber);
    1096             :   {
    1097       52985 :     Node* value_number = AllocateHeapNumberWithValue(value);
    1098             :     __ Goto(&done, value_number);
    1099             :   }
    1100             : 
    1101             :   __ Bind(&done);
    1102       52986 :   return done.PhiAt(0);
    1103             : }
    1104             : 
    1105          91 : Node* EffectControlLinearizer::LowerChangeFloat64ToTaggedPointer(Node* node) {
    1106             :   Node* value = node->InputAt(0);
    1107          91 :   return AllocateHeapNumberWithValue(value);
    1108             : }
    1109             : 
    1110       16462 : Node* EffectControlLinearizer::LowerChangeBitToTagged(Node* node) {
    1111             :   Node* value = node->InputAt(0);
    1112             : 
    1113       16462 :   auto if_true = __ MakeLabel();
    1114       16462 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    1115             : 
    1116       16462 :   __ GotoIf(value, &if_true);
    1117       16462 :   __ Goto(&done, __ FalseConstant());
    1118             : 
    1119             :   __ Bind(&if_true);
    1120       16462 :   __ Goto(&done, __ TrueConstant());
    1121             : 
    1122             :   __ Bind(&done);
    1123       16462 :   return done.PhiAt(0);
    1124             : }
    1125             : 
    1126       38566 : Node* EffectControlLinearizer::LowerChangeInt31ToTaggedSigned(Node* node) {
    1127             :   Node* value = node->InputAt(0);
    1128       38566 :   return ChangeInt32ToSmi(value);
    1129             : }
    1130             : 
    1131       35400 : Node* EffectControlLinearizer::LowerChangeInt32ToTagged(Node* node) {
    1132             :   Node* value = node->InputAt(0);
    1133             : 
    1134             :   if (SmiValuesAre32Bits()) {
    1135       35400 :     return ChangeInt32ToSmi(value);
    1136             :   }
    1137             :   DCHECK(SmiValuesAre31Bits());
    1138             : 
    1139             :   auto if_overflow = __ MakeDeferredLabel();
    1140             :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    1141             : 
    1142             :   Node* add = __ Int32AddWithOverflow(value, value);
    1143             :   Node* ovf = __ Projection(1, add);
    1144             :   __ GotoIf(ovf, &if_overflow);
    1145             :   Node* value_smi = __ Projection(0, add);
    1146             :   value_smi = ChangeInt32ToIntPtr(value_smi);
    1147             :   __ Goto(&done, value_smi);
    1148             : 
    1149             :   __ Bind(&if_overflow);
    1150             :   Node* number = AllocateHeapNumberWithValue(__ ChangeInt32ToFloat64(value));
    1151             :   __ Goto(&done, number);
    1152             : 
    1153             :   __ Bind(&done);
    1154             :   return done.PhiAt(0);
    1155             : }
    1156             : 
    1157         260 : Node* EffectControlLinearizer::LowerChangeInt64ToTagged(Node* node) {
    1158             :   Node* value = node->InputAt(0);
    1159             : 
    1160         260 :   auto if_not_in_smi_range = __ MakeDeferredLabel();
    1161         260 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    1162             : 
    1163         260 :   Node* value32 = __ TruncateInt64ToInt32(value);
    1164             :   __ GotoIfNot(__ Word64Equal(__ ChangeInt32ToInt64(value32), value),
    1165         260 :                &if_not_in_smi_range);
    1166             : 
    1167             :   if (SmiValuesAre32Bits()) {
    1168             :     Node* value_smi = ChangeInt64ToSmi(value);
    1169             :     __ Goto(&done, value_smi);
    1170             :   } else {
    1171             :     Node* add = __ Int32AddWithOverflow(value32, value32);
    1172             :     Node* ovf = __ Projection(1, add);
    1173             :     __ GotoIf(ovf, &if_not_in_smi_range);
    1174             :     Node* value_smi = ChangeInt32ToIntPtr(__ Projection(0, add));
    1175             :     __ Goto(&done, value_smi);
    1176             :   }
    1177             : 
    1178             :   __ Bind(&if_not_in_smi_range);
    1179         260 :   Node* number = AllocateHeapNumberWithValue(__ ChangeInt64ToFloat64(value));
    1180             :   __ Goto(&done, number);
    1181             : 
    1182             :   __ Bind(&done);
    1183         260 :   return done.PhiAt(0);
    1184             : }
    1185             : 
    1186         542 : Node* EffectControlLinearizer::LowerChangeUint32ToTagged(Node* node) {
    1187             :   Node* value = node->InputAt(0);
    1188             : 
    1189         542 :   auto if_not_in_smi_range = __ MakeDeferredLabel();
    1190         542 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    1191             : 
    1192         542 :   Node* check = __ Uint32LessThanOrEqual(value, SmiMaxValueConstant());
    1193         542 :   __ GotoIfNot(check, &if_not_in_smi_range);
    1194         542 :   __ Goto(&done, ChangeUint32ToSmi(value));
    1195             : 
    1196             :   __ Bind(&if_not_in_smi_range);
    1197         542 :   Node* number = AllocateHeapNumberWithValue(__ ChangeUint32ToFloat64(value));
    1198             : 
    1199             :   __ Goto(&done, number);
    1200             :   __ Bind(&done);
    1201             : 
    1202         542 :   return done.PhiAt(0);
    1203             : }
    1204             : 
    1205          81 : Node* EffectControlLinearizer::LowerChangeUint64ToTagged(Node* node) {
    1206             :   Node* value = node->InputAt(0);
    1207             : 
    1208          81 :   auto if_not_in_smi_range = __ MakeDeferredLabel();
    1209          81 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    1210             : 
    1211             :   Node* check =
    1212          81 :       __ Uint64LessThanOrEqual(value, __ Int64Constant(Smi::kMaxValue));
    1213          81 :   __ GotoIfNot(check, &if_not_in_smi_range);
    1214             :   __ Goto(&done, ChangeInt64ToSmi(value));
    1215             : 
    1216             :   __ Bind(&if_not_in_smi_range);
    1217          81 :   Node* number = AllocateHeapNumberWithValue(__ ChangeInt64ToFloat64(value));
    1218             : 
    1219             :   __ Goto(&done, number);
    1220             :   __ Bind(&done);
    1221             : 
    1222          81 :   return done.PhiAt(0);
    1223             : }
    1224             : 
    1225       52640 : Node* EffectControlLinearizer::LowerChangeTaggedSignedToInt32(Node* node) {
    1226             :   Node* value = node->InputAt(0);
    1227       52640 :   return ChangeSmiToInt32(value);
    1228             : }
    1229             : 
    1230        1893 : Node* EffectControlLinearizer::LowerChangeTaggedSignedToInt64(Node* node) {
    1231             :   Node* value = node->InputAt(0);
    1232        1893 :   return ChangeSmiToInt64(value);
    1233             : }
    1234             : 
    1235      127535 : Node* EffectControlLinearizer::LowerChangeTaggedToBit(Node* node) {
    1236             :   Node* value = node->InputAt(0);
    1237      127535 :   return __ WordEqual(value, __ TrueConstant());
    1238             : }
    1239             : 
    1240       41411 : void EffectControlLinearizer::TruncateTaggedPointerToBit(
    1241             :     Node* node, GraphAssemblerLabel<1>* done) {
    1242             :   Node* value = node->InputAt(0);
    1243             : 
    1244       41411 :   auto if_heapnumber = __ MakeDeferredLabel();
    1245       41411 :   auto if_bigint = __ MakeDeferredLabel();
    1246             : 
    1247       41411 :   Node* zero = __ Int32Constant(0);
    1248       41411 :   Node* fzero = __ Float64Constant(0.0);
    1249             : 
    1250             :   // Check if {value} is false.
    1251       41412 :   __ GotoIf(__ WordEqual(value, __ FalseConstant()), done, zero);
    1252             : 
    1253             :   // Check if {value} is the empty string.
    1254       41412 :   __ GotoIf(__ WordEqual(value, __ EmptyStringConstant()), done, zero);
    1255             : 
    1256             :   // Load the map of {value}.
    1257       41412 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1258             : 
    1259             :   // Check if the {value} is undetectable and immediately return false.
    1260             :   // This includes undefined and null.
    1261             :   Node* value_map_bitfield =
    1262       41412 :       __ LoadField(AccessBuilder::ForMapBitField(), value_map);
    1263             :   __ GotoIfNot(
    1264             :       __ Word32Equal(
    1265             :           __ Word32And(value_map_bitfield,
    1266             :                        __ Int32Constant(Map::IsUndetectableBit::kMask)),
    1267             :           zero),
    1268       41412 :       done, zero);
    1269             : 
    1270             :   // Check if {value} is a HeapNumber.
    1271             :   __ GotoIf(__ WordEqual(value_map, __ HeapNumberMapConstant()),
    1272       41412 :             &if_heapnumber);
    1273             : 
    1274             :   // Check if {value} is a BigInt.
    1275             :   Node* value_instance_type =
    1276       41412 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1277             :   __ GotoIf(__ Word32Equal(value_instance_type, __ Int32Constant(BIGINT_TYPE)),
    1278       41412 :             &if_bigint);
    1279             : 
    1280             :   // All other values that reach here are true.
    1281       41412 :   __ Goto(done, __ Int32Constant(1));
    1282             : 
    1283             :   __ Bind(&if_heapnumber);
    1284             :   {
    1285             :     // For HeapNumber {value}, just check that its value is not 0.0, -0.0 or
    1286             :     // NaN.
    1287             :     Node* value_value =
    1288       41412 :         __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1289       41412 :     __ Goto(done, __ Float64LessThan(fzero, __ Float64Abs(value_value)));
    1290             :   }
    1291             : 
    1292             :   __ Bind(&if_bigint);
    1293             :   {
    1294       41412 :     Node* bitfield = __ LoadField(AccessBuilder::ForBigIntBitfield(), value);
    1295             :     Node* length_is_zero = __ Word32Equal(
    1296             :         __ Word32And(bitfield, __ Int32Constant(BigInt::LengthBits::kMask)),
    1297       41412 :         __ Int32Constant(0));
    1298       41412 :     __ Goto(done, __ Word32Equal(length_is_zero, zero));
    1299             :   }
    1300       41412 : }
    1301             : 
    1302       40938 : Node* EffectControlLinearizer::LowerTruncateTaggedToBit(Node* node) {
    1303       40938 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    1304       40938 :   auto if_smi = __ MakeDeferredLabel();
    1305             : 
    1306             :   Node* value = node->InputAt(0);
    1307       40938 :   __ GotoIf(ObjectIsSmi(value), &if_smi);
    1308             : 
    1309       40939 :   TruncateTaggedPointerToBit(node, &done);
    1310             : 
    1311             :   __ Bind(&if_smi);
    1312             :   {
    1313             :     // If {value} is a Smi, then we only need to check that it's not zero.
    1314             :     __ Goto(&done, __ Word32Equal(__ WordEqual(value, __ IntPtrConstant(0)),
    1315       40939 :                                   __ Int32Constant(0)));
    1316             :   }
    1317             : 
    1318             :   __ Bind(&done);
    1319       40939 :   return done.PhiAt(0);
    1320             : }
    1321             : 
    1322         473 : Node* EffectControlLinearizer::LowerTruncateTaggedPointerToBit(Node* node) {
    1323         473 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    1324             : 
    1325         473 :   TruncateTaggedPointerToBit(node, &done);
    1326             : 
    1327             :   __ Bind(&done);
    1328         473 :   return done.PhiAt(0);
    1329             : }
    1330             : 
    1331        1881 : Node* EffectControlLinearizer::LowerChangeTaggedToInt32(Node* node) {
    1332             :   Node* value = node->InputAt(0);
    1333             : 
    1334        1881 :   auto if_not_smi = __ MakeDeferredLabel();
    1335        1881 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    1336             : 
    1337        1881 :   Node* check = ObjectIsSmi(value);
    1338        1882 :   __ GotoIfNot(check, &if_not_smi);
    1339        1882 :   __ Goto(&done, ChangeSmiToInt32(value));
    1340             : 
    1341             :   __ Bind(&if_not_smi);
    1342             :   STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    1343        1882 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1344        1882 :   vfalse = __ ChangeFloat64ToInt32(vfalse);
    1345             :   __ Goto(&done, vfalse);
    1346             : 
    1347             :   __ Bind(&done);
    1348        1882 :   return done.PhiAt(0);
    1349             : }
    1350             : 
    1351         564 : Node* EffectControlLinearizer::LowerChangeTaggedToUint32(Node* node) {
    1352             :   Node* value = node->InputAt(0);
    1353             : 
    1354         564 :   auto if_not_smi = __ MakeDeferredLabel();
    1355         564 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    1356             : 
    1357         564 :   Node* check = ObjectIsSmi(value);
    1358         564 :   __ GotoIfNot(check, &if_not_smi);
    1359         564 :   __ Goto(&done, ChangeSmiToInt32(value));
    1360             : 
    1361             :   __ Bind(&if_not_smi);
    1362             :   STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    1363         564 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1364         564 :   vfalse = __ ChangeFloat64ToUint32(vfalse);
    1365             :   __ Goto(&done, vfalse);
    1366             : 
    1367             :   __ Bind(&done);
    1368         564 :   return done.PhiAt(0);
    1369             : }
    1370             : 
    1371          12 : Node* EffectControlLinearizer::LowerChangeTaggedToInt64(Node* node) {
    1372             :   Node* value = node->InputAt(0);
    1373             : 
    1374          12 :   auto if_not_smi = __ MakeDeferredLabel();
    1375          12 :   auto done = __ MakeLabel(MachineRepresentation::kWord64);
    1376             : 
    1377          12 :   Node* check = ObjectIsSmi(value);
    1378          12 :   __ GotoIfNot(check, &if_not_smi);
    1379          12 :   __ Goto(&done, ChangeSmiToInt64(value));
    1380             : 
    1381             :   __ Bind(&if_not_smi);
    1382             :   STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    1383          12 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1384          12 :   vfalse = __ ChangeFloat64ToInt64(vfalse);
    1385             :   __ Goto(&done, vfalse);
    1386             : 
    1387             :   __ Bind(&done);
    1388          12 :   return done.PhiAt(0);
    1389             : }
    1390             : 
    1391           0 : Node* EffectControlLinearizer::LowerChangeTaggedToFloat64(Node* node) {
    1392       10774 :   return LowerTruncateTaggedToFloat64(node);
    1393             : }
    1394             : 
    1395          15 : Node* EffectControlLinearizer::LowerChangeTaggedToTaggedSigned(Node* node) {
    1396             :   Node* value = node->InputAt(0);
    1397             : 
    1398          15 :   auto if_not_smi = __ MakeDeferredLabel();
    1399          15 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    1400             : 
    1401          15 :   Node* check = ObjectIsSmi(value);
    1402          15 :   __ GotoIfNot(check, &if_not_smi);
    1403             :   __ Goto(&done, value);
    1404             : 
    1405             :   __ Bind(&if_not_smi);
    1406             :   STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    1407          15 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1408          15 :   vfalse = __ ChangeFloat64ToInt32(vfalse);
    1409          15 :   vfalse = ChangeInt32ToSmi(vfalse);
    1410             :   __ Goto(&done, vfalse);
    1411             : 
    1412             :   __ Bind(&done);
    1413          15 :   return done.PhiAt(0);
    1414             : }
    1415             : 
    1416       11517 : Node* EffectControlLinearizer::LowerTruncateTaggedToFloat64(Node* node) {
    1417             :   Node* value = node->InputAt(0);
    1418             : 
    1419       11517 :   auto if_not_smi = __ MakeDeferredLabel();
    1420       11517 :   auto done = __ MakeLabel(MachineRepresentation::kFloat64);
    1421             : 
    1422       11517 :   Node* check = ObjectIsSmi(value);
    1423       11517 :   __ GotoIfNot(check, &if_not_smi);
    1424       11517 :   Node* vtrue = ChangeSmiToInt32(value);
    1425       11517 :   vtrue = __ ChangeInt32ToFloat64(vtrue);
    1426             :   __ Goto(&done, vtrue);
    1427             : 
    1428             :   __ Bind(&if_not_smi);
    1429             :   STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    1430       11517 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1431             :   __ Goto(&done, vfalse);
    1432             : 
    1433             :   __ Bind(&done);
    1434       11517 :   return done.PhiAt(0);
    1435             : }
    1436             : 
    1437        1167 : Node* EffectControlLinearizer::LowerPoisonIndex(Node* node) {
    1438             :   Node* index = node->InputAt(0);
    1439        1167 :   if (mask_array_index_ == kMaskArrayIndex) {
    1440           0 :     index = __ Word32PoisonOnSpeculation(index);
    1441             :   }
    1442        1167 :   return index;
    1443             : }
    1444             : 
    1445       55458 : void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
    1446       55458 :   CheckMapsParameters const& p = CheckMapsParametersOf(node->op());
    1447             :   Node* value = node->InputAt(0);
    1448             : 
    1449       55458 :   ZoneHandleSet<Map> const& maps = p.maps();
    1450             :   size_t const map_count = maps.size();
    1451             : 
    1452       55458 :   if (p.flags() & CheckMapsFlag::kTryMigrateInstance) {
    1453         707 :     auto done = __ MakeLabel();
    1454         707 :     auto migrate = __ MakeDeferredLabel();
    1455             : 
    1456             :     // Load the current map of the {value}.
    1457         707 :     Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1458             : 
    1459             :     // Perform the map checks.
    1460        1578 :     for (size_t i = 0; i < map_count; ++i) {
    1461         871 :       Node* map = __ HeapConstant(maps[i]);
    1462         871 :       Node* check = __ WordEqual(value_map, map);
    1463         871 :       if (i == map_count - 1) {
    1464         707 :         __ Branch(check, &done, &migrate, IsSafetyCheck::kCriticalSafetyCheck);
    1465             :       } else {
    1466         164 :         auto next_map = __ MakeLabel();
    1467         164 :         __ Branch(check, &done, &next_map, IsSafetyCheck::kCriticalSafetyCheck);
    1468             :         __ Bind(&next_map);
    1469             :       }
    1470             :     }
    1471             : 
    1472             :     // Perform the (deferred) instance migration.
    1473             :     __ Bind(&migrate);
    1474             :     {
    1475             :       // If map is not deprecated the migration attempt does not make sense.
    1476             :       Node* bitfield3 =
    1477         707 :           __ LoadField(AccessBuilder::ForMapBitField3(), value_map);
    1478             :       Node* if_not_deprecated = __ WordEqual(
    1479             :           __ Word32And(bitfield3,
    1480             :                        __ Int32Constant(Map::IsDeprecatedBit::kMask)),
    1481         707 :           __ Int32Constant(0));
    1482         707 :       __ DeoptimizeIf(DeoptimizeReason::kWrongMap, p.feedback(),
    1483             :                       if_not_deprecated, frame_state,
    1484         707 :                       IsSafetyCheck::kCriticalSafetyCheck);
    1485             : 
    1486         707 :       Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
    1487             :       Runtime::FunctionId id = Runtime::kTryMigrateInstance;
    1488             :       auto call_descriptor = Linkage::GetRuntimeCallDescriptor(
    1489         707 :           graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags);
    1490             :       Node* result = __ Call(call_descriptor, __ CEntryStubConstant(1), value,
    1491             :                              __ ExternalConstant(ExternalReference::Create(id)),
    1492         707 :                              __ Int32Constant(1), __ NoContextConstant());
    1493         707 :       Node* check = ObjectIsSmi(result);
    1494             :       __ DeoptimizeIf(DeoptimizeReason::kInstanceMigrationFailed, p.feedback(),
    1495         707 :                       check, frame_state, IsSafetyCheck::kCriticalSafetyCheck);
    1496             :     }
    1497             : 
    1498             :     // Reload the current map of the {value}.
    1499         707 :     value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1500             : 
    1501             :     // Perform the map checks again.
    1502        1578 :     for (size_t i = 0; i < map_count; ++i) {
    1503         871 :       Node* map = __ HeapConstant(maps[i]);
    1504         871 :       Node* check = __ WordEqual(value_map, map);
    1505         871 :       if (i == map_count - 1) {
    1506             :         __ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, p.feedback(), check,
    1507         707 :                            frame_state, IsSafetyCheck::kCriticalSafetyCheck);
    1508             :       } else {
    1509         164 :         auto next_map = __ MakeLabel();
    1510         164 :         __ Branch(check, &done, &next_map, IsSafetyCheck::kCriticalSafetyCheck);
    1511             :         __ Bind(&next_map);
    1512             :       }
    1513             :     }
    1514             : 
    1515             :     __ Goto(&done);
    1516             :     __ Bind(&done);
    1517             :   } else {
    1518       54751 :     auto done = __ MakeLabel();
    1519             : 
    1520             :     // Load the current map of the {value}.
    1521       54751 :     Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1522             : 
    1523      115254 :     for (size_t i = 0; i < map_count; ++i) {
    1524       60502 :       Node* map = __ HeapConstant(maps[i]);
    1525       60503 :       Node* check = __ WordEqual(value_map, map);
    1526       60502 :       if (i == map_count - 1) {
    1527       54751 :         __ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, p.feedback(), check,
    1528       54751 :                            frame_state, IsSafetyCheck::kCriticalSafetyCheck);
    1529             :       } else {
    1530        5751 :         auto next_map = __ MakeLabel();
    1531        5751 :         __ Branch(check, &done, &next_map, IsSafetyCheck::kCriticalSafetyCheck);
    1532             :         __ Bind(&next_map);
    1533             :       }
    1534             :     }
    1535             :     __ Goto(&done);
    1536             :     __ Bind(&done);
    1537             :   }
    1538       55459 : }
    1539             : 
    1540        5713 : Node* EffectControlLinearizer::LowerCompareMaps(Node* node) {
    1541        5713 :   ZoneHandleSet<Map> const& maps = CompareMapsParametersOf(node->op()).maps();
    1542             :   size_t const map_count = maps.size();
    1543             :   Node* value = node->InputAt(0);
    1544             : 
    1545        5713 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    1546             : 
    1547             :   // Load the current map of the {value}.
    1548        5713 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1549             : 
    1550       11482 :   for (size_t i = 0; i < map_count; ++i) {
    1551        5769 :     Node* map = __ HeapConstant(maps[i]);
    1552        5769 :     Node* check = __ WordEqual(value_map, map);
    1553        5769 :     auto next_map = __ MakeLabel();
    1554        5769 :     auto passed = __ MakeLabel();
    1555        5769 :     __ Branch(check, &passed, &next_map, IsSafetyCheck::kCriticalSafetyCheck);
    1556             : 
    1557             :     __ Bind(&passed);
    1558        5769 :     __ Goto(&done, __ Int32Constant(1));
    1559             : 
    1560             :     __ Bind(&next_map);
    1561             :   }
    1562        5713 :   __ Goto(&done, __ Int32Constant(0));
    1563             : 
    1564             :   __ Bind(&done);
    1565        5713 :   return done.PhiAt(0);
    1566             : }
    1567             : 
    1568        1038 : Node* EffectControlLinearizer::LowerCheckNumber(Node* node, Node* frame_state) {
    1569             :   Node* value = node->InputAt(0);
    1570         519 :   const CheckParameters& params = CheckParametersOf(node->op());
    1571             : 
    1572         519 :   auto if_not_smi = __ MakeDeferredLabel();
    1573         519 :   auto done = __ MakeLabel();
    1574             : 
    1575         519 :   Node* check0 = ObjectIsSmi(value);
    1576         519 :   __ GotoIfNot(check0, &if_not_smi);
    1577             :   __ Goto(&done);
    1578             : 
    1579             :   __ Bind(&if_not_smi);
    1580         519 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1581         519 :   Node* check1 = __ WordEqual(value_map, __ HeapNumberMapConstant());
    1582         519 :   __ DeoptimizeIfNot(DeoptimizeReason::kNotAHeapNumber, params.feedback(),
    1583         519 :                      check1, frame_state);
    1584             :   __ Goto(&done);
    1585             : 
    1586             :   __ Bind(&done);
    1587         519 :   return value;
    1588             : }
    1589             : 
    1590         815 : Node* EffectControlLinearizer::LowerCheckReceiver(Node* node,
    1591             :                                                   Node* frame_state) {
    1592             :   Node* value = node->InputAt(0);
    1593             : 
    1594         815 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1595             :   Node* value_instance_type =
    1596         815 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1597             : 
    1598             :   STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
    1599             :   Node* check = __ Uint32LessThanOrEqual(
    1600         815 :       __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type);
    1601             :   __ DeoptimizeIfNot(DeoptimizeReason::kNotAJavaScriptObject, VectorSlotPair(),
    1602         815 :                      check, frame_state);
    1603         815 :   return value;
    1604             : }
    1605             : 
    1606          87 : Node* EffectControlLinearizer::LowerCheckReceiverOrNullOrUndefined(
    1607             :     Node* node, Node* frame_state) {
    1608             :   Node* value = node->InputAt(0);
    1609             : 
    1610          87 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1611             :   Node* value_instance_type =
    1612          87 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1613             : 
    1614             :   // Rule out all primitives except oddballs (true, false, undefined, null).
    1615             :   STATIC_ASSERT(LAST_PRIMITIVE_TYPE == ODDBALL_TYPE);
    1616             :   STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
    1617             :   Node* check0 = __ Uint32LessThanOrEqual(__ Uint32Constant(ODDBALL_TYPE),
    1618          87 :                                           value_instance_type);
    1619             :   __ DeoptimizeIfNot(DeoptimizeReason::kNotAJavaScriptObjectOrNullOrUndefined,
    1620          87 :                      VectorSlotPair(), check0, frame_state);
    1621             : 
    1622             :   // Rule out booleans.
    1623          87 :   Node* check1 = __ WordEqual(value_map, __ BooleanMapConstant());
    1624             :   __ DeoptimizeIf(DeoptimizeReason::kNotAJavaScriptObjectOrNullOrUndefined,
    1625          87 :                   VectorSlotPair(), check1, frame_state);
    1626          87 :   return value;
    1627             : }
    1628             : 
    1629          37 : Node* EffectControlLinearizer::LowerCheckSymbol(Node* node, Node* frame_state) {
    1630             :   Node* value = node->InputAt(0);
    1631             : 
    1632          37 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1633             : 
    1634             :   Node* check =
    1635          37 :       __ WordEqual(value_map, __ HeapConstant(factory()->symbol_map()));
    1636             :   __ DeoptimizeIfNot(DeoptimizeReason::kNotASymbol, VectorSlotPair(), check,
    1637          37 :                      frame_state);
    1638          37 :   return value;
    1639             : }
    1640             : 
    1641       12646 : Node* EffectControlLinearizer::LowerCheckString(Node* node, Node* frame_state) {
    1642             :   Node* value = node->InputAt(0);
    1643        6323 :   const CheckParameters& params = CheckParametersOf(node->op());
    1644             : 
    1645        6323 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1646             :   Node* value_instance_type =
    1647        6323 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1648             : 
    1649             :   Node* check = __ Uint32LessThan(value_instance_type,
    1650        6323 :                                   __ Uint32Constant(FIRST_NONSTRING_TYPE));
    1651        6323 :   __ DeoptimizeIfNot(DeoptimizeReason::kNotAString, params.feedback(), check,
    1652        6323 :                      frame_state);
    1653        6323 :   return value;
    1654             : }
    1655             : 
    1656        1430 : Node* EffectControlLinearizer::LowerCheckInternalizedString(Node* node,
    1657             :                                                             Node* frame_state) {
    1658             :   Node* value = node->InputAt(0);
    1659             : 
    1660        1430 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1661             :   Node* value_instance_type =
    1662        1430 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1663             : 
    1664             :   Node* check = __ Word32Equal(
    1665             :       __ Word32And(value_instance_type,
    1666             :                    __ Int32Constant(kIsNotStringMask | kIsNotInternalizedMask)),
    1667        1430 :       __ Int32Constant(kInternalizedTag));
    1668             :   __ DeoptimizeIfNot(DeoptimizeReason::kWrongInstanceType, VectorSlotPair(),
    1669        1430 :                      check, frame_state);
    1670             : 
    1671        1430 :   return value;
    1672             : }
    1673             : 
    1674       30488 : void EffectControlLinearizer::LowerCheckIf(Node* node, Node* frame_state) {
    1675             :   Node* value = node->InputAt(0);
    1676       30488 :   const CheckIfParameters& p = CheckIfParametersOf(node->op());
    1677       30488 :   __ DeoptimizeIfNot(p.reason(), p.feedback(), value, frame_state);
    1678       15244 : }
    1679             : 
    1680       37862 : Node* EffectControlLinearizer::LowerStringConcat(Node* node) {
    1681             :   Node* lhs = node->InputAt(1);
    1682             :   Node* rhs = node->InputAt(2);
    1683             : 
    1684             :   Callable const callable =
    1685       18931 :       CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE);
    1686             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    1687             :       graph()->zone(), callable.descriptor(),
    1688             :       callable.descriptor().GetStackParameterCount(), CallDescriptor::kNoFlags,
    1689       37862 :       Operator::kNoDeopt | Operator::kNoWrite | Operator::kNoThrow);
    1690             : 
    1691             :   Node* value =
    1692             :       __ Call(call_descriptor, jsgraph()->HeapConstant(callable.code()), lhs,
    1693       37862 :               rhs, __ NoContextConstant());
    1694             : 
    1695       18931 :   return value;
    1696             : }
    1697             : 
    1698       56282 : Node* EffectControlLinearizer::LowerCheckedInt32Add(Node* node,
    1699             :                                                     Node* frame_state) {
    1700             :   Node* lhs = node->InputAt(0);
    1701             :   Node* rhs = node->InputAt(1);
    1702             : 
    1703       56282 :   Node* value = __ Int32AddWithOverflow(lhs, rhs);
    1704       56284 :   Node* check = __ Projection(1, value);
    1705             :   __ DeoptimizeIf(DeoptimizeReason::kOverflow, VectorSlotPair(), check,
    1706       56283 :                   frame_state);
    1707       56285 :   return __ Projection(0, value);
    1708             : }
    1709             : 
    1710        7527 : Node* EffectControlLinearizer::LowerCheckedInt32Sub(Node* node,
    1711             :                                                     Node* frame_state) {
    1712             :   Node* lhs = node->InputAt(0);
    1713             :   Node* rhs = node->InputAt(1);
    1714             : 
    1715        7527 :   Node* value = __ Int32SubWithOverflow(lhs, rhs);
    1716        7527 :   Node* check = __ Projection(1, value);
    1717             :   __ DeoptimizeIf(DeoptimizeReason::kOverflow, VectorSlotPair(), check,
    1718        7527 :                   frame_state);
    1719        7527 :   return __ Projection(0, value);
    1720             : }
    1721             : 
    1722         243 : Node* EffectControlLinearizer::LowerCheckedInt32Div(Node* node,
    1723             :                                                     Node* frame_state) {
    1724             :   Node* lhs = node->InputAt(0);
    1725             :   Node* rhs = node->InputAt(1);
    1726         243 :   Node* zero = __ Int32Constant(0);
    1727             : 
    1728             :   // Check if the {rhs} is a known power of two.
    1729             :   Int32Matcher m(rhs);
    1730         243 :   if (m.IsPowerOf2()) {
    1731             :     // Since we know that {rhs} is a power of two, we can perform a fast
    1732             :     // check to see if the relevant least significant bits of the {lhs}
    1733             :     // are all zero, and if so we know that we can perform a division
    1734             :     // safely (and fast by doing an arithmetic - aka sign preserving -
    1735             :     // right shift on {lhs}).
    1736             :     int32_t divisor = m.Value();
    1737         138 :     Node* mask = __ Int32Constant(divisor - 1);
    1738         138 :     Node* shift = __ Int32Constant(WhichPowerOf2(divisor));
    1739         138 :     Node* check = __ Word32Equal(__ Word32And(lhs, mask), zero);
    1740             :     __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, VectorSlotPair(),
    1741         138 :                        check, frame_state);
    1742         138 :     return __ Word32Sar(lhs, shift);
    1743             :   } else {
    1744         105 :     auto if_rhs_positive = __ MakeLabel();
    1745         105 :     auto if_rhs_negative = __ MakeDeferredLabel();
    1746         105 :     auto done = __ MakeLabel(MachineRepresentation::kWord32);
    1747             : 
    1748             :     // Check if {rhs} is positive (and not zero).
    1749         105 :     Node* check_rhs_positive = __ Int32LessThan(zero, rhs);
    1750         105 :     __ Branch(check_rhs_positive, &if_rhs_positive, &if_rhs_negative);
    1751             : 
    1752             :     __ Bind(&if_rhs_positive);
    1753             :     {
    1754             :       // Fast case, no additional checking required.
    1755         105 :       __ Goto(&done, __ Int32Div(lhs, rhs));
    1756             :     }
    1757             : 
    1758             :     __ Bind(&if_rhs_negative);
    1759             :     {
    1760         105 :       auto if_lhs_minint = __ MakeDeferredLabel();
    1761         105 :       auto if_lhs_notminint = __ MakeLabel();
    1762             : 
    1763             :       // Check if {rhs} is zero.
    1764         105 :       Node* check_rhs_zero = __ Word32Equal(rhs, zero);
    1765             :       __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, VectorSlotPair(),
    1766         105 :                       check_rhs_zero, frame_state);
    1767             : 
    1768             :       // Check if {lhs} is zero, as that would produce minus zero.
    1769         105 :       Node* check_lhs_zero = __ Word32Equal(lhs, zero);
    1770             :       __ DeoptimizeIf(DeoptimizeReason::kMinusZero, VectorSlotPair(),
    1771         105 :                       check_lhs_zero, frame_state);
    1772             : 
    1773             :       // Check if {lhs} is kMinInt and {rhs} is -1, in which case we'd have
    1774             :       // to return -kMinInt, which is not representable as Word32.
    1775             :       Node* check_lhs_minint = graph()->NewNode(machine()->Word32Equal(), lhs,
    1776         210 :                                                 __ Int32Constant(kMinInt));
    1777         105 :       __ Branch(check_lhs_minint, &if_lhs_minint, &if_lhs_notminint);
    1778             : 
    1779             :       __ Bind(&if_lhs_minint);
    1780             :       {
    1781             :         // Check that {rhs} is not -1, otherwise result would be -kMinInt.
    1782         105 :         Node* check_rhs_minusone = __ Word32Equal(rhs, __ Int32Constant(-1));
    1783             :         __ DeoptimizeIf(DeoptimizeReason::kOverflow, VectorSlotPair(),
    1784         105 :                         check_rhs_minusone, frame_state);
    1785             : 
    1786             :         // Perform the actual integer division.
    1787         105 :         __ Goto(&done, __ Int32Div(lhs, rhs));
    1788             :       }
    1789             : 
    1790             :       __ Bind(&if_lhs_notminint);
    1791             :       {
    1792             :         // Perform the actual integer division.
    1793         105 :         __ Goto(&done, __ Int32Div(lhs, rhs));
    1794             :       }
    1795             :     }
    1796             : 
    1797             :     __ Bind(&done);
    1798             :     Node* value = done.PhiAt(0);
    1799             : 
    1800             :     // Check if the remainder is non-zero.
    1801         105 :     Node* check = __ Word32Equal(lhs, __ Int32Mul(value, rhs));
    1802             :     __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, VectorSlotPair(),
    1803         105 :                        check, frame_state);
    1804             : 
    1805             :     return value;
    1806             :   }
    1807             : }
    1808             : 
    1809         893 : Node* EffectControlLinearizer::BuildUint32Mod(Node* lhs, Node* rhs) {
    1810         893 :   auto if_rhs_power_of_two = __ MakeLabel();
    1811         893 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    1812             : 
    1813             :   // Compute the mask for the {rhs}.
    1814         893 :   Node* one = __ Int32Constant(1);
    1815         893 :   Node* msk = __ Int32Sub(rhs, one);
    1816             : 
    1817             :   // Check if the {rhs} is a power of two.
    1818             :   __ GotoIf(__ Word32Equal(__ Word32And(rhs, msk), __ Int32Constant(0)),
    1819         893 :             &if_rhs_power_of_two);
    1820             :   {
    1821             :     // The {rhs} is not a power of two, do a generic Uint32Mod.
    1822         893 :     __ Goto(&done, __ Uint32Mod(lhs, rhs));
    1823             :   }
    1824             : 
    1825             :   __ Bind(&if_rhs_power_of_two);
    1826             :   {
    1827             :     // The {rhs} is a power of two, just do a fast bit masking.
    1828         893 :     __ Goto(&done, __ Word32And(lhs, msk));
    1829             :   }
    1830             : 
    1831             :   __ Bind(&done);
    1832         893 :   return done.PhiAt(0);
    1833             : }
    1834             : 
    1835         856 : Node* EffectControlLinearizer::LowerCheckedInt32Mod(Node* node,
    1836             :                                                     Node* frame_state) {
    1837             :   // General case for signed integer modulus, with optimization for (unknown)
    1838             :   // power of 2 right hand side.
    1839             :   //
    1840             :   //   if rhs <= 0 then
    1841             :   //     rhs = -rhs
    1842             :   //     deopt if rhs == 0
    1843             :   //   let msk = rhs - 1 in
    1844             :   //   if lhs < 0 then
    1845             :   //     let lhs_abs = -lsh in
    1846             :   //     let res = if rhs & msk == 0 then
    1847             :   //                 lhs_abs & msk
    1848             :   //               else
    1849             :   //                 lhs_abs % rhs in
    1850             :   //     if lhs < 0 then
    1851             :   //       deopt if res == 0
    1852             :   //       -res
    1853             :   //     else
    1854             :   //       res
    1855             :   //   else
    1856             :   //     if rhs & msk == 0 then
    1857             :   //       lhs & msk
    1858             :   //     else
    1859             :   //       lhs % rhs
    1860             :   //
    1861             :   Node* lhs = node->InputAt(0);
    1862             :   Node* rhs = node->InputAt(1);
    1863             : 
    1864         856 :   auto if_rhs_not_positive = __ MakeDeferredLabel();
    1865         856 :   auto if_lhs_negative = __ MakeDeferredLabel();
    1866             :   auto if_rhs_power_of_two = __ MakeLabel();
    1867         856 :   auto rhs_checked = __ MakeLabel(MachineRepresentation::kWord32);
    1868         856 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    1869             : 
    1870         856 :   Node* zero = __ Int32Constant(0);
    1871             : 
    1872             :   // Check if {rhs} is not strictly positive.
    1873         856 :   Node* check0 = __ Int32LessThanOrEqual(rhs, zero);
    1874         856 :   __ GotoIf(check0, &if_rhs_not_positive);
    1875             :   __ Goto(&rhs_checked, rhs);
    1876             : 
    1877             :   __ Bind(&if_rhs_not_positive);
    1878             :   {
    1879             :     // Negate {rhs}, might still produce a negative result in case of
    1880             :     // -2^31, but that is handled safely below.
    1881         856 :     Node* vtrue0 = __ Int32Sub(zero, rhs);
    1882             : 
    1883             :     // Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
    1884             :     __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, VectorSlotPair(),
    1885         856 :                     __ Word32Equal(vtrue0, zero), frame_state);
    1886             :     __ Goto(&rhs_checked, vtrue0);
    1887             :   }
    1888             : 
    1889             :   __ Bind(&rhs_checked);
    1890             :   rhs = rhs_checked.PhiAt(0);
    1891             : 
    1892         856 :   __ GotoIf(__ Int32LessThan(lhs, zero), &if_lhs_negative);
    1893             :   {
    1894             :     // The {lhs} is a non-negative integer.
    1895         856 :     __ Goto(&done, BuildUint32Mod(lhs, rhs));
    1896             :   }
    1897             : 
    1898             :   __ Bind(&if_lhs_negative);
    1899             :   {
    1900             :     // The {lhs} is a negative integer. This is very unlikely and
    1901             :     // we intentionally don't use the BuildUint32Mod() here, which
    1902             :     // would try to figure out whether {rhs} is a power of two,
    1903             :     // since this is intended to be a slow-path.
    1904         856 :     Node* res = __ Uint32Mod(__ Int32Sub(zero, lhs), rhs);
    1905             : 
    1906             :     // Check if we would have to return -0.
    1907             :     __ DeoptimizeIf(DeoptimizeReason::kMinusZero, VectorSlotPair(),
    1908         856 :                     __ Word32Equal(res, zero), frame_state);
    1909         856 :     __ Goto(&done, __ Int32Sub(zero, res));
    1910             :   }
    1911             : 
    1912             :   __ Bind(&done);
    1913         856 :   return done.PhiAt(0);
    1914             : }
    1915             : 
    1916          49 : Node* EffectControlLinearizer::LowerCheckedUint32Div(Node* node,
    1917             :                                                      Node* frame_state) {
    1918             :   Node* lhs = node->InputAt(0);
    1919             :   Node* rhs = node->InputAt(1);
    1920          49 :   Node* zero = __ Int32Constant(0);
    1921             : 
    1922             :   // Check if the {rhs} is a known power of two.
    1923             :   Uint32Matcher m(rhs);
    1924          49 :   if (m.IsPowerOf2()) {
    1925             :     // Since we know that {rhs} is a power of two, we can perform a fast
    1926             :     // check to see if the relevant least significant bits of the {lhs}
    1927             :     // are all zero, and if so we know that we can perform a division
    1928             :     // safely (and fast by doing a logical - aka zero extending - right
    1929             :     // shift on {lhs}).
    1930             :     uint32_t divisor = m.Value();
    1931          37 :     Node* mask = __ Uint32Constant(divisor - 1);
    1932          37 :     Node* shift = __ Uint32Constant(WhichPowerOf2(divisor));
    1933          37 :     Node* check = __ Word32Equal(__ Word32And(lhs, mask), zero);
    1934             :     __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, VectorSlotPair(),
    1935          37 :                        check, frame_state);
    1936          37 :     return __ Word32Shr(lhs, shift);
    1937             :   } else {
    1938             :     // Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
    1939          12 :     Node* check = __ Word32Equal(rhs, zero);
    1940             :     __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, VectorSlotPair(), check,
    1941          12 :                     frame_state);
    1942             : 
    1943             :     // Perform the actual unsigned integer division.
    1944          12 :     Node* value = __ Uint32Div(lhs, rhs);
    1945             : 
    1946             :     // Check if the remainder is non-zero.
    1947          12 :     check = __ Word32Equal(lhs, __ Int32Mul(rhs, value));
    1948             :     __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, VectorSlotPair(),
    1949          12 :                        check, frame_state);
    1950          12 :     return value;
    1951             :   }
    1952             : }
    1953             : 
    1954          37 : Node* EffectControlLinearizer::LowerCheckedUint32Mod(Node* node,
    1955             :                                                      Node* frame_state) {
    1956             :   Node* lhs = node->InputAt(0);
    1957             :   Node* rhs = node->InputAt(1);
    1958             : 
    1959          37 :   Node* zero = __ Int32Constant(0);
    1960             : 
    1961             :   // Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
    1962          37 :   Node* check = __ Word32Equal(rhs, zero);
    1963             :   __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, VectorSlotPair(), check,
    1964          37 :                   frame_state);
    1965             : 
    1966             :   // Perform the actual unsigned integer modulus.
    1967          37 :   return BuildUint32Mod(lhs, rhs);
    1968             : }
    1969             : 
    1970        5673 : Node* EffectControlLinearizer::LowerCheckedInt32Mul(Node* node,
    1971             :                                                     Node* frame_state) {
    1972        5673 :   CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
    1973             :   Node* lhs = node->InputAt(0);
    1974             :   Node* rhs = node->InputAt(1);
    1975             : 
    1976        5673 :   Node* projection = __ Int32MulWithOverflow(lhs, rhs);
    1977        5673 :   Node* check = __ Projection(1, projection);
    1978             :   __ DeoptimizeIf(DeoptimizeReason::kOverflow, VectorSlotPair(), check,
    1979        5673 :                   frame_state);
    1980             : 
    1981        5673 :   Node* value = __ Projection(0, projection);
    1982             : 
    1983        5673 :   if (mode == CheckForMinusZeroMode::kCheckForMinusZero) {
    1984        3931 :     auto if_zero = __ MakeDeferredLabel();
    1985        3931 :     auto check_done = __ MakeLabel();
    1986        3931 :     Node* zero = __ Int32Constant(0);
    1987        3931 :     Node* check_zero = __ Word32Equal(value, zero);
    1988        3931 :     __ GotoIf(check_zero, &if_zero);
    1989             :     __ Goto(&check_done);
    1990             : 
    1991             :     __ Bind(&if_zero);
    1992             :     // We may need to return negative zero.
    1993        3931 :     Node* check_or = __ Int32LessThan(__ Word32Or(lhs, rhs), zero);
    1994             :     __ DeoptimizeIf(DeoptimizeReason::kMinusZero, VectorSlotPair(), check_or,
    1995        3931 :                     frame_state);
    1996             :     __ Goto(&check_done);
    1997             : 
    1998             :     __ Bind(&check_done);
    1999             :   }
    2000             : 
    2001        5673 :   return value;
    2002             : }
    2003             : 
    2004           0 : Node* EffectControlLinearizer::LowerCheckedInt32ToTaggedSigned(
    2005           0 :     Node* node, Node* frame_state) {
    2006             :   DCHECK(SmiValuesAre31Bits());
    2007             :   Node* value = node->InputAt(0);
    2008           0 :   const CheckParameters& params = CheckParametersOf(node->op());
    2009             : 
    2010           0 :   Node* add = __ Int32AddWithOverflow(value, value);
    2011           0 :   Node* check = __ Projection(1, add);
    2012           0 :   __ DeoptimizeIf(DeoptimizeReason::kLostPrecision, params.feedback(), check,
    2013           0 :                   frame_state);
    2014           0 :   Node* result = __ Projection(0, add);
    2015             :   result = ChangeInt32ToIntPtr(result);
    2016           0 :   return result;
    2017             : }
    2018             : 
    2019          14 : Node* EffectControlLinearizer::LowerCheckedInt64ToInt32(Node* node,
    2020             :                                                         Node* frame_state) {
    2021             :   Node* value = node->InputAt(0);
    2022           7 :   const CheckParameters& params = CheckParametersOf(node->op());
    2023             : 
    2024           7 :   Node* value32 = __ TruncateInt64ToInt32(value);
    2025           7 :   Node* check = __ Word64Equal(__ ChangeInt32ToInt64(value32), value);
    2026           7 :   __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, params.feedback(), check,
    2027           7 :                      frame_state);
    2028           7 :   return value32;
    2029             : }
    2030             : 
    2031        1725 : Node* EffectControlLinearizer::LowerCheckedInt64ToTaggedSigned(
    2032        1725 :     Node* node, Node* frame_state) {
    2033             :   Node* value = node->InputAt(0);
    2034        1725 :   const CheckParameters& params = CheckParametersOf(node->op());
    2035             : 
    2036        1725 :   Node* value32 = __ TruncateInt64ToInt32(value);
    2037        1725 :   Node* check = __ Word64Equal(__ ChangeInt32ToInt64(value32), value);
    2038        1725 :   __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, params.feedback(), check,
    2039        1725 :                      frame_state);
    2040             : 
    2041             :   if (SmiValuesAre32Bits()) {
    2042             :     return ChangeInt64ToSmi(value);
    2043             :   } else {
    2044             :     Node* add = __ Int32AddWithOverflow(value32, value32);
    2045             :     Node* check = __ Projection(1, add);
    2046             :     __ DeoptimizeIf(DeoptimizeReason::kLostPrecision, params.feedback(), check,
    2047             :                     frame_state);
    2048             :     Node* result = __ Projection(0, add);
    2049             :     result = ChangeInt32ToIntPtr(result);
    2050             :     return result;
    2051             :   }
    2052             : }
    2053             : 
    2054       88396 : Node* EffectControlLinearizer::LowerCheckedUint32Bounds(Node* node,
    2055             :                                                         Node* frame_state) {
    2056             :   Node* index = node->InputAt(0);
    2057             :   Node* limit = node->InputAt(1);
    2058       44198 :   const CheckParameters& params = CheckParametersOf(node->op());
    2059             : 
    2060       44198 :   Node* check = __ Uint32LessThan(index, limit);
    2061       44198 :   __ DeoptimizeIfNot(DeoptimizeReason::kOutOfBounds, params.feedback(), check,
    2062       44198 :                      frame_state, IsSafetyCheck::kCriticalSafetyCheck);
    2063       44198 :   return index;
    2064             : }
    2065             : 
    2066         506 : Node* EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node,
    2067             :                                                          Node* frame_state) {
    2068             :   Node* value = node->InputAt(0);
    2069         253 :   const CheckParameters& params = CheckParametersOf(node->op());
    2070         253 :   Node* unsafe = __ Int32LessThan(value, __ Int32Constant(0));
    2071         253 :   __ DeoptimizeIf(DeoptimizeReason::kLostPrecision, params.feedback(), unsafe,
    2072         253 :                   frame_state);
    2073         253 :   return value;
    2074             : }
    2075             : 
    2076          14 : Node* EffectControlLinearizer::LowerCheckedUint32ToTaggedSigned(
    2077          14 :     Node* node, Node* frame_state) {
    2078             :   Node* value = node->InputAt(0);
    2079          14 :   const CheckParameters& params = CheckParametersOf(node->op());
    2080          14 :   Node* check = __ Uint32LessThanOrEqual(value, SmiMaxValueConstant());
    2081          14 :   __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, params.feedback(), check,
    2082          14 :                      frame_state);
    2083          14 :   return ChangeUint32ToSmi(value);
    2084             : }
    2085             : 
    2086         192 : Node* EffectControlLinearizer::LowerCheckedUint64Bounds(Node* node,
    2087             :                                                         Node* frame_state) {
    2088         192 :   CheckParameters const& params = CheckParametersOf(node->op());
    2089             :   Node* const index = node->InputAt(0);
    2090             :   Node* const limit = node->InputAt(1);
    2091             : 
    2092         192 :   Node* check = __ Uint64LessThan(index, limit);
    2093         192 :   __ DeoptimizeIfNot(DeoptimizeReason::kOutOfBounds, params.feedback(), check,
    2094         192 :                      frame_state, IsSafetyCheck::kCriticalSafetyCheck);
    2095         192 :   return index;
    2096             : }
    2097             : 
    2098           0 : Node* EffectControlLinearizer::LowerCheckedUint64ToInt32(Node* node,
    2099             :                                                          Node* frame_state) {
    2100             :   Node* value = node->InputAt(0);
    2101           0 :   const CheckParameters& params = CheckParametersOf(node->op());
    2102             : 
    2103           0 :   Node* check = __ Uint64LessThanOrEqual(value, __ Int64Constant(kMaxInt));
    2104           0 :   __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, params.feedback(), check,
    2105           0 :                      frame_state);
    2106           0 :   return __ TruncateInt64ToInt32(value);
    2107             : }
    2108             : 
    2109           0 : Node* EffectControlLinearizer::LowerCheckedUint64ToTaggedSigned(
    2110           0 :     Node* node, Node* frame_state) {
    2111             :   Node* value = node->InputAt(0);
    2112           0 :   const CheckParameters& params = CheckParametersOf(node->op());
    2113             : 
    2114             :   Node* check =
    2115           0 :       __ Uint64LessThanOrEqual(value, __ Int64Constant(Smi::kMaxValue));
    2116           0 :   __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, params.feedback(), check,
    2117           0 :                      frame_state);
    2118           0 :   return ChangeInt64ToSmi(value);
    2119             : }
    2120             : 
    2121        4750 : Node* EffectControlLinearizer::BuildCheckedFloat64ToInt32(
    2122             :     CheckForMinusZeroMode mode, const VectorSlotPair& feedback, Node* value,
    2123             :     Node* frame_state) {
    2124        4750 :   Node* value32 = __ RoundFloat64ToInt32(value);
    2125        4750 :   Node* check_same = __ Float64Equal(value, __ ChangeInt32ToFloat64(value32));
    2126             :   __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecisionOrNaN, feedback,
    2127        4750 :                      check_same, frame_state);
    2128             : 
    2129        4750 :   if (mode == CheckForMinusZeroMode::kCheckForMinusZero) {
    2130             :     // Check if {value} is -0.
    2131        2158 :     auto if_zero = __ MakeDeferredLabel();
    2132        2158 :     auto check_done = __ MakeLabel();
    2133             : 
    2134        2158 :     Node* check_zero = __ Word32Equal(value32, __ Int32Constant(0));
    2135        2158 :     __ GotoIf(check_zero, &if_zero);
    2136             :     __ Goto(&check_done);
    2137             : 
    2138             :     __ Bind(&if_zero);
    2139             :     // In case of 0, we need to check the high bits for the IEEE -0 pattern.
    2140             :     Node* check_negative = __ Int32LessThan(__ Float64ExtractHighWord32(value),
    2141        2158 :                                             __ Int32Constant(0));
    2142             :     __ DeoptimizeIf(DeoptimizeReason::kMinusZero, feedback, check_negative,
    2143        2158 :                     frame_state);
    2144             :     __ Goto(&check_done);
    2145             : 
    2146             :     __ Bind(&check_done);
    2147             :   }
    2148        4750 :   return value32;
    2149             : }
    2150             : 
    2151        2350 : Node* EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node,
    2152             :                                                           Node* frame_state) {
    2153        2350 :   const CheckMinusZeroParameters& params =
    2154        2350 :       CheckMinusZeroParametersOf(node->op());
    2155             :   Node* value = node->InputAt(0);
    2156        2350 :   return BuildCheckedFloat64ToInt32(params.mode(), params.feedback(), value,
    2157        2350 :                                     frame_state);
    2158             : }
    2159             : 
    2160          84 : Node* EffectControlLinearizer::BuildCheckedFloat64ToInt64(
    2161             :     CheckForMinusZeroMode mode, const VectorSlotPair& feedback, Node* value,
    2162             :     Node* frame_state) {
    2163          84 :   Node* value64 = __ TruncateFloat64ToInt64(value);
    2164          84 :   Node* check_same = __ Float64Equal(value, __ ChangeInt64ToFloat64(value64));
    2165             :   __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecisionOrNaN, feedback,
    2166          84 :                      check_same, frame_state);
    2167             : 
    2168          84 :   if (mode == CheckForMinusZeroMode::kCheckForMinusZero) {
    2169             :     // Check if {value} is -0.
    2170           0 :     auto if_zero = __ MakeDeferredLabel();
    2171           0 :     auto check_done = __ MakeLabel();
    2172             : 
    2173           0 :     Node* check_zero = __ Word64Equal(value64, __ Int64Constant(0));
    2174           0 :     __ GotoIf(check_zero, &if_zero);
    2175             :     __ Goto(&check_done);
    2176             : 
    2177             :     __ Bind(&if_zero);
    2178             :     // In case of 0, we need to check the high bits for the IEEE -0 pattern.
    2179             :     Node* check_negative = __ Int32LessThan(__ Float64ExtractHighWord32(value),
    2180           0 :                                             __ Int32Constant(0));
    2181             :     __ DeoptimizeIf(DeoptimizeReason::kMinusZero, feedback, check_negative,
    2182           0 :                     frame_state);
    2183             :     __ Goto(&check_done);
    2184             : 
    2185             :     __ Bind(&check_done);
    2186             :   }
    2187          84 :   return value64;
    2188             : }
    2189             : 
    2190          14 : Node* EffectControlLinearizer::LowerCheckedFloat64ToInt64(Node* node,
    2191             :                                                           Node* frame_state) {
    2192          14 :   const CheckMinusZeroParameters& params =
    2193          14 :       CheckMinusZeroParametersOf(node->op());
    2194             :   Node* value = node->InputAt(0);
    2195          14 :   return BuildCheckedFloat64ToInt64(params.mode(), params.feedback(), value,
    2196          14 :                                     frame_state);
    2197             : }
    2198             : 
    2199       24835 : Node* EffectControlLinearizer::LowerCheckedTaggedSignedToInt32(
    2200       24835 :     Node* node, Node* frame_state) {
    2201             :   Node* value = node->InputAt(0);
    2202       24835 :   const CheckParameters& params = CheckParametersOf(node->op());
    2203       24836 :   Node* check = ObjectIsSmi(value);
    2204       24836 :   __ DeoptimizeIfNot(DeoptimizeReason::kNotASmi, params.feedback(), check,
    2205       24836 :                      frame_state);
    2206       24836 :   return ChangeSmiToInt32(value);
    2207             : }
    2208             : 
    2209        2400 : Node* EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node,
    2210             :                                                          Node* frame_state) {
    2211        2400 :   const CheckMinusZeroParameters& params =
    2212        2400 :       CheckMinusZeroParametersOf(node->op());
    2213             :   Node* value = node->InputAt(0);
    2214             : 
    2215        2400 :   auto if_not_smi = __ MakeDeferredLabel();
    2216        2400 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    2217             : 
    2218        2400 :   Node* check = ObjectIsSmi(value);
    2219        2400 :   __ GotoIfNot(check, &if_not_smi);
    2220             :   // In the Smi case, just convert to int32.
    2221        2400 :   __ Goto(&done, ChangeSmiToInt32(value));
    2222             : 
    2223             :   // In the non-Smi case, check the heap numberness, load the number and convert
    2224             :   // to int32.
    2225             :   __ Bind(&if_not_smi);
    2226        2400 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2227        2400 :   Node* check_map = __ WordEqual(value_map, __ HeapNumberMapConstant());
    2228        2400 :   __ DeoptimizeIfNot(DeoptimizeReason::kNotAHeapNumber, params.feedback(),
    2229        2400 :                      check_map, frame_state);
    2230        2400 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    2231             :   vfalse = BuildCheckedFloat64ToInt32(params.mode(), params.feedback(), vfalse,
    2232        2400 :                                       frame_state);
    2233             :   __ Goto(&done, vfalse);
    2234             : 
    2235             :   __ Bind(&done);
    2236        2400 :   return done.PhiAt(0);
    2237             : }
    2238             : 
    2239          70 : Node* EffectControlLinearizer::LowerCheckedTaggedToInt64(Node* node,
    2240             :                                                          Node* frame_state) {
    2241          70 :   const CheckMinusZeroParameters& params =
    2242          70 :       CheckMinusZeroParametersOf(node->op());
    2243             :   Node* value = node->InputAt(0);
    2244             : 
    2245          70 :   auto if_not_smi = __ MakeDeferredLabel();
    2246          70 :   auto done = __ MakeLabel(MachineRepresentation::kWord64);
    2247             : 
    2248          70 :   Node* check = ObjectIsSmi(value);
    2249          70 :   __ GotoIfNot(check, &if_not_smi);
    2250             :   // In the Smi case, just convert to int64.
    2251          70 :   __ Goto(&done, ChangeSmiToInt64(value));
    2252             : 
    2253             :   // In the non-Smi case, check the heap numberness, load the number and convert
    2254             :   // to int64.
    2255             :   __ Bind(&if_not_smi);
    2256          70 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2257          70 :   Node* check_map = __ WordEqual(value_map, __ HeapNumberMapConstant());
    2258          70 :   __ DeoptimizeIfNot(DeoptimizeReason::kNotAHeapNumber, params.feedback(),
    2259          70 :                      check_map, frame_state);
    2260          70 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    2261             :   vfalse = BuildCheckedFloat64ToInt64(params.mode(), params.feedback(), vfalse,
    2262          70 :                                       frame_state);
    2263             :   __ Goto(&done, vfalse);
    2264             : 
    2265             :   __ Bind(&done);
    2266          70 :   return done.PhiAt(0);
    2267             : }
    2268             : 
    2269       59322 : Node* EffectControlLinearizer::BuildCheckedHeapNumberOrOddballToFloat64(
    2270             :     CheckTaggedInputMode mode, const VectorSlotPair& feedback, Node* value,
    2271             :     Node* frame_state) {
    2272       59322 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2273       59322 :   Node* check_number = __ WordEqual(value_map, __ HeapNumberMapConstant());
    2274       59322 :   switch (mode) {
    2275             :     case CheckTaggedInputMode::kNumber: {
    2276             :       __ DeoptimizeIfNot(DeoptimizeReason::kNotAHeapNumber, feedback,
    2277        8728 :                          check_number, frame_state);
    2278        8728 :       break;
    2279             :     }
    2280             :     case CheckTaggedInputMode::kNumberOrOddball: {
    2281       50594 :       auto check_done = __ MakeLabel();
    2282             : 
    2283       50594 :       __ GotoIf(check_number, &check_done);
    2284             :       // For oddballs also contain the numeric value, let us just check that
    2285             :       // we have an oddball here.
    2286             :       Node* instance_type =
    2287       50594 :           __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    2288             :       Node* check_oddball =
    2289       50594 :           __ Word32Equal(instance_type, __ Int32Constant(ODDBALL_TYPE));
    2290             :       __ DeoptimizeIfNot(DeoptimizeReason::kNotANumberOrOddball, feedback,
    2291       50594 :                          check_oddball, frame_state);
    2292             :       STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    2293             :       __ Goto(&check_done);
    2294             : 
    2295             :       __ Bind(&check_done);
    2296             :       break;
    2297             :     }
    2298             :   }
    2299       59322 :   return __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    2300             : }
    2301             : 
    2302       58011 : Node* EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node,
    2303             :                                                            Node* frame_state) {
    2304       58011 :   CheckTaggedInputParameters const& p =
    2305       58011 :       CheckTaggedInputParametersOf(node->op());
    2306             :   Node* value = node->InputAt(0);
    2307             : 
    2308       58011 :   auto if_smi = __ MakeLabel();
    2309       58011 :   auto done = __ MakeLabel(MachineRepresentation::kFloat64);
    2310             : 
    2311       58011 :   Node* check = ObjectIsSmi(value);
    2312       58011 :   __ GotoIf(check, &if_smi);
    2313             : 
    2314             :   // In the Smi case, just convert to int32 and then float64.
    2315             :   // Otherwise, check heap numberness and load the number.
    2316             :   Node* number = BuildCheckedHeapNumberOrOddballToFloat64(
    2317      116022 :       p.mode(), p.feedback(), value, frame_state);
    2318             :   __ Goto(&done, number);
    2319             : 
    2320             :   __ Bind(&if_smi);
    2321       58011 :   Node* from_smi = ChangeSmiToInt32(value);
    2322       58011 :   from_smi = __ ChangeInt32ToFloat64(from_smi);
    2323             :   __ Goto(&done, from_smi);
    2324             : 
    2325             :   __ Bind(&done);
    2326       58011 :   return done.PhiAt(0);
    2327             : }
    2328             : 
    2329       19906 : Node* EffectControlLinearizer::LowerCheckedTaggedToTaggedSigned(
    2330       19906 :     Node* node, Node* frame_state) {
    2331             :   Node* value = node->InputAt(0);
    2332       19906 :   const CheckParameters& params = CheckParametersOf(node->op());
    2333             : 
    2334       19906 :   Node* check = ObjectIsSmi(value);
    2335       19906 :   __ DeoptimizeIfNot(DeoptimizeReason::kNotASmi, params.feedback(), check,
    2336       19906 :                      frame_state);
    2337             : 
    2338       19906 :   return value;
    2339             : }
    2340             : 
    2341       35937 : Node* EffectControlLinearizer::LowerCheckedTaggedToTaggedPointer(
    2342       35937 :     Node* node, Node* frame_state) {
    2343             :   Node* value = node->InputAt(0);
    2344       35937 :   const CheckParameters& params = CheckParametersOf(node->op());
    2345             : 
    2346       35938 :   Node* check = ObjectIsSmi(value);
    2347       35938 :   __ DeoptimizeIf(DeoptimizeReason::kSmi, params.feedback(), check,
    2348       35938 :                   frame_state);
    2349       35938 :   return value;
    2350             : }
    2351             : 
    2352         423 : Node* EffectControlLinearizer::LowerTruncateTaggedToWord32(Node* node) {
    2353             :   Node* value = node->InputAt(0);
    2354             : 
    2355         423 :   auto if_not_smi = __ MakeDeferredLabel();
    2356         423 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    2357             : 
    2358         423 :   Node* check = ObjectIsSmi(value);
    2359         423 :   __ GotoIfNot(check, &if_not_smi);
    2360         423 :   __ Goto(&done, ChangeSmiToInt32(value));
    2361             : 
    2362             :   __ Bind(&if_not_smi);
    2363             :   STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    2364         423 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    2365         423 :   vfalse = __ TruncateFloat64ToWord32(vfalse);
    2366             :   __ Goto(&done, vfalse);
    2367             : 
    2368             :   __ Bind(&done);
    2369         423 :   return done.PhiAt(0);
    2370             : }
    2371             : 
    2372        1311 : Node* EffectControlLinearizer::LowerCheckedTruncateTaggedToWord32(
    2373        1311 :     Node* node, Node* frame_state) {
    2374        1311 :   const CheckTaggedInputParameters& params =
    2375        1311 :       CheckTaggedInputParametersOf(node->op());
    2376             :   Node* value = node->InputAt(0);
    2377             : 
    2378        1311 :   auto if_not_smi = __ MakeLabel();
    2379        1311 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    2380             : 
    2381        1311 :   Node* check = ObjectIsSmi(value);
    2382        1311 :   __ GotoIfNot(check, &if_not_smi);
    2383             :   // In the Smi case, just convert to int32.
    2384        1311 :   __ Goto(&done, ChangeSmiToInt32(value));
    2385             : 
    2386             :   // Otherwise, check that it's a heap number or oddball and truncate the value
    2387             :   // to int32.
    2388             :   __ Bind(&if_not_smi);
    2389             :   Node* number = BuildCheckedHeapNumberOrOddballToFloat64(
    2390        2622 :       params.mode(), params.feedback(), value, frame_state);
    2391        1311 :   number = __ TruncateFloat64ToWord32(number);
    2392             :   __ Goto(&done, number);
    2393             : 
    2394             :   __ Bind(&done);
    2395        1311 :   return done.PhiAt(0);
    2396             : }
    2397             : 
    2398      224090 : Node* EffectControlLinearizer::LowerAllocate(Node* node) {
    2399             :   Node* size = node->InputAt(0);
    2400      112045 :   PretenureFlag pretenure = PretenureFlagOf(node->op());
    2401      112045 :   Node* new_node = __ Allocate(pretenure, size);
    2402      112045 :   return new_node;
    2403             : }
    2404             : 
    2405        1092 : Node* EffectControlLinearizer::LowerNumberToString(Node* node) {
    2406             :   Node* argument = node->InputAt(0);
    2407             : 
    2408             :   Callable const callable =
    2409        1092 :       Builtins::CallableFor(isolate(), Builtins::kNumberToString);
    2410             :   Operator::Properties properties = Operator::kEliminatable;
    2411             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    2412             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    2413             :       graph()->zone(), callable.descriptor(),
    2414        2184 :       callable.descriptor().GetStackParameterCount(), flags, properties);
    2415             :   return __ Call(call_descriptor, __ HeapConstant(callable.code()), argument,
    2416        2184 :                  __ NoContextConstant());
    2417             : }
    2418             : 
    2419          16 : Node* EffectControlLinearizer::LowerObjectIsArrayBufferView(Node* node) {
    2420             :   Node* value = node->InputAt(0);
    2421             : 
    2422          16 :   auto if_smi = __ MakeDeferredLabel();
    2423          16 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2424             : 
    2425          16 :   Node* check = ObjectIsSmi(value);
    2426          16 :   __ GotoIf(check, &if_smi);
    2427             : 
    2428          16 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2429             :   Node* value_instance_type =
    2430          16 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    2431             :   STATIC_ASSERT(JS_TYPED_ARRAY_TYPE + 1 == JS_DATA_VIEW_TYPE);
    2432             :   Node* vfalse = __ Uint32LessThan(
    2433             :       __ Int32Sub(value_instance_type, __ Int32Constant(JS_TYPED_ARRAY_TYPE)),
    2434          16 :       __ Int32Constant(2));
    2435             :   __ Goto(&done, vfalse);
    2436             : 
    2437             :   __ Bind(&if_smi);
    2438          16 :   __ Goto(&done, __ Int32Constant(0));
    2439             : 
    2440             :   __ Bind(&done);
    2441          16 :   return done.PhiAt(0);
    2442             : }
    2443             : 
    2444          25 : Node* EffectControlLinearizer::LowerObjectIsBigInt(Node* node) {
    2445             :   Node* value = node->InputAt(0);
    2446             : 
    2447          25 :   auto if_smi = __ MakeDeferredLabel();
    2448          25 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2449             : 
    2450          25 :   Node* check = ObjectIsSmi(value);
    2451          25 :   __ GotoIf(check, &if_smi);
    2452          25 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2453             :   Node* value_instance_type =
    2454          25 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    2455             :   Node* vfalse =
    2456          25 :       __ Word32Equal(value_instance_type, __ Uint32Constant(BIGINT_TYPE));
    2457             :   __ Goto(&done, vfalse);
    2458             : 
    2459             :   __ Bind(&if_smi);
    2460          25 :   __ Goto(&done, __ Int32Constant(0));
    2461             : 
    2462             :   __ Bind(&done);
    2463          25 :   return done.PhiAt(0);
    2464             : }
    2465             : 
    2466          98 : Node* EffectControlLinearizer::LowerObjectIsCallable(Node* node) {
    2467             :   Node* value = node->InputAt(0);
    2468             : 
    2469          98 :   auto if_smi = __ MakeDeferredLabel();
    2470          98 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2471             : 
    2472          98 :   Node* check = ObjectIsSmi(value);
    2473          98 :   __ GotoIf(check, &if_smi);
    2474             : 
    2475          98 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2476             :   Node* value_bit_field =
    2477          98 :       __ LoadField(AccessBuilder::ForMapBitField(), value_map);
    2478             :   Node* vfalse =
    2479             :       __ Word32Equal(__ Int32Constant(Map::IsCallableBit::kMask),
    2480             :                      __ Word32And(value_bit_field,
    2481          98 :                                   __ Int32Constant(Map::IsCallableBit::kMask)));
    2482             :   __ Goto(&done, vfalse);
    2483             : 
    2484             :   __ Bind(&if_smi);
    2485          98 :   __ Goto(&done, __ Int32Constant(0));
    2486             : 
    2487             :   __ Bind(&done);
    2488          98 :   return done.PhiAt(0);
    2489             : }
    2490             : 
    2491         206 : Node* EffectControlLinearizer::LowerObjectIsConstructor(Node* node) {
    2492             :   Node* value = node->InputAt(0);
    2493             : 
    2494         206 :   auto if_smi = __ MakeDeferredLabel();
    2495         206 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2496             : 
    2497         206 :   Node* check = ObjectIsSmi(value);
    2498         206 :   __ GotoIf(check, &if_smi);
    2499             : 
    2500         206 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2501             :   Node* value_bit_field =
    2502         206 :       __ LoadField(AccessBuilder::ForMapBitField(), value_map);
    2503             :   Node* vfalse = __ Word32Equal(
    2504             :       __ Int32Constant(Map::IsConstructorBit::kMask),
    2505             :       __ Word32And(value_bit_field,
    2506         206 :                    __ Int32Constant(Map::IsConstructorBit::kMask)));
    2507             :   __ Goto(&done, vfalse);
    2508             : 
    2509             :   __ Bind(&if_smi);
    2510         206 :   __ Goto(&done, __ Int32Constant(0));
    2511             : 
    2512             :   __ Bind(&done);
    2513         206 :   return done.PhiAt(0);
    2514             : }
    2515             : 
    2516       13423 : Node* EffectControlLinearizer::LowerObjectIsDetectableCallable(Node* node) {
    2517             :   Node* value = node->InputAt(0);
    2518             : 
    2519       13423 :   auto if_smi = __ MakeDeferredLabel();
    2520       13423 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2521             : 
    2522       13423 :   Node* check = ObjectIsSmi(value);
    2523       13424 :   __ GotoIf(check, &if_smi);
    2524             : 
    2525       13423 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2526             :   Node* value_bit_field =
    2527       13424 :       __ LoadField(AccessBuilder::ForMapBitField(), value_map);
    2528             :   Node* vfalse = __ Word32Equal(
    2529             :       __ Int32Constant(Map::IsCallableBit::kMask),
    2530             :       __ Word32And(value_bit_field,
    2531             :                    __ Int32Constant((Map::IsCallableBit::kMask) |
    2532       13424 :                                     (Map::IsUndetectableBit::kMask))));
    2533             :   __ Goto(&done, vfalse);
    2534             : 
    2535             :   __ Bind(&if_smi);
    2536       13424 :   __ Goto(&done, __ Int32Constant(0));
    2537             : 
    2538             :   __ Bind(&done);
    2539       13424 :   return done.PhiAt(0);
    2540             : }
    2541             : 
    2542          66 : Node* EffectControlLinearizer::LowerNumberIsFloat64Hole(Node* node) {
    2543             :   Node* value = node->InputAt(0);
    2544             :   Node* check = __ Word32Equal(__ Float64ExtractHighWord32(value),
    2545          66 :                                __ Int32Constant(kHoleNanUpper32));
    2546          66 :   return check;
    2547             : }
    2548             : 
    2549         141 : Node* EffectControlLinearizer::LowerNumberIsFinite(Node* node) {
    2550             :   Node* number = node->InputAt(0);
    2551         141 :   Node* diff = __ Float64Sub(number, number);
    2552         141 :   Node* check = __ Float64Equal(diff, diff);
    2553         141 :   return check;
    2554             : }
    2555             : 
    2556           7 : Node* EffectControlLinearizer::LowerObjectIsFiniteNumber(Node* node) {
    2557             :   Node* object = node->InputAt(0);
    2558           7 :   Node* zero = __ Int32Constant(0);
    2559           7 :   Node* one = __ Int32Constant(1);
    2560             : 
    2561           7 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2562             : 
    2563             :   // Check if {object} is a Smi.
    2564           7 :   __ GotoIf(ObjectIsSmi(object), &done, one);
    2565             : 
    2566             :   // Check if {object} is a HeapNumber.
    2567           7 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), object);
    2568             :   __ GotoIfNot(__ WordEqual(value_map, __ HeapNumberMapConstant()), &done,
    2569           7 :                zero);
    2570             : 
    2571             :   // {object} is a HeapNumber.
    2572           7 :   Node* value = __ LoadField(AccessBuilder::ForHeapNumberValue(), object);
    2573           7 :   Node* diff = __ Float64Sub(value, value);
    2574           7 :   Node* check = __ Float64Equal(diff, diff);
    2575             :   __ Goto(&done, check);
    2576             : 
    2577             :   __ Bind(&done);
    2578           7 :   return done.PhiAt(0);
    2579             : }
    2580             : 
    2581         119 : Node* EffectControlLinearizer::LowerNumberIsInteger(Node* node) {
    2582             :   Node* number = node->InputAt(0);
    2583         119 :   Node* trunc = BuildFloat64RoundTruncate(number);
    2584         119 :   Node* diff = __ Float64Sub(number, trunc);
    2585         119 :   Node* check = __ Float64Equal(diff, __ Float64Constant(0));
    2586         119 :   return check;
    2587             : }
    2588             : 
    2589           7 : Node* EffectControlLinearizer::LowerObjectIsInteger(Node* node) {
    2590             :   Node* object = node->InputAt(0);
    2591           7 :   Node* zero = __ Int32Constant(0);
    2592           7 :   Node* one = __ Int32Constant(1);
    2593             : 
    2594           7 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2595             : 
    2596             :   // Check if {object} is a Smi.
    2597           7 :   __ GotoIf(ObjectIsSmi(object), &done, one);
    2598             : 
    2599             :   // Check if {object} is a HeapNumber.
    2600           7 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), object);
    2601             :   __ GotoIfNot(__ WordEqual(value_map, __ HeapNumberMapConstant()), &done,
    2602           7 :                zero);
    2603             : 
    2604             :   // {object} is a HeapNumber.
    2605           7 :   Node* value = __ LoadField(AccessBuilder::ForHeapNumberValue(), object);
    2606           7 :   Node* trunc = BuildFloat64RoundTruncate(value);
    2607           7 :   Node* diff = __ Float64Sub(value, trunc);
    2608           7 :   Node* check = __ Float64Equal(diff, __ Float64Constant(0));
    2609             :   __ Goto(&done, check);
    2610             : 
    2611             :   __ Bind(&done);
    2612           7 :   return done.PhiAt(0);
    2613             : }
    2614             : 
    2615           7 : Node* EffectControlLinearizer::LowerNumberIsSafeInteger(Node* node) {
    2616             :   Node* number = node->InputAt(0);
    2617           7 :   Node* zero = __ Int32Constant(0);
    2618           7 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2619             : 
    2620           7 :   Node* trunc = BuildFloat64RoundTruncate(number);
    2621           7 :   Node* diff = __ Float64Sub(number, trunc);
    2622           7 :   Node* check = __ Float64Equal(diff, __ Float64Constant(0));
    2623           7 :   __ GotoIfNot(check, &done, zero);
    2624             :   Node* in_range = __ Float64LessThanOrEqual(
    2625           7 :       __ Float64Abs(trunc), __ Float64Constant(kMaxSafeInteger));
    2626             :   __ Goto(&done, in_range);
    2627             : 
    2628             :   __ Bind(&done);
    2629           7 :   return done.PhiAt(0);
    2630             : }
    2631             : 
    2632           7 : Node* EffectControlLinearizer::LowerObjectIsSafeInteger(Node* node) {
    2633             :   Node* object = node->InputAt(0);
    2634           7 :   Node* zero = __ Int32Constant(0);
    2635           7 :   Node* one = __ Int32Constant(1);
    2636             : 
    2637           7 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2638             : 
    2639             :   // Check if {object} is a Smi.
    2640           7 :   __ GotoIf(ObjectIsSmi(object), &done, one);
    2641             : 
    2642             :   // Check if {object} is a HeapNumber.
    2643           7 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), object);
    2644             :   __ GotoIfNot(__ WordEqual(value_map, __ HeapNumberMapConstant()), &done,
    2645           7 :                zero);
    2646             : 
    2647             :   // {object} is a HeapNumber.
    2648           7 :   Node* value = __ LoadField(AccessBuilder::ForHeapNumberValue(), object);
    2649           7 :   Node* trunc = BuildFloat64RoundTruncate(value);
    2650           7 :   Node* diff = __ Float64Sub(value, trunc);
    2651           7 :   Node* check = __ Float64Equal(diff, __ Float64Constant(0));
    2652           7 :   __ GotoIfNot(check, &done, zero);
    2653             :   Node* in_range = __ Float64LessThanOrEqual(
    2654           7 :       __ Float64Abs(trunc), __ Float64Constant(kMaxSafeInteger));
    2655             :   __ Goto(&done, in_range);
    2656             : 
    2657             :   __ Bind(&done);
    2658           7 :   return done.PhiAt(0);
    2659             : }
    2660             : 
    2661             : namespace {
    2662             : 
    2663       61289 : const int64_t kMinusZeroBits = bit_cast<int64_t>(-0.0);
    2664       61289 : const int32_t kMinusZeroLoBits = static_cast<int32_t>(kMinusZeroBits);
    2665       61289 : const int32_t kMinusZeroHiBits = static_cast<int32_t>(kMinusZeroBits >> 32);
    2666             : 
    2667             : }  // namespace
    2668             : 
    2669          21 : Node* EffectControlLinearizer::LowerObjectIsMinusZero(Node* node) {
    2670             :   Node* value = node->InputAt(0);
    2671          21 :   Node* zero = __ Int32Constant(0);
    2672             : 
    2673          21 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2674             : 
    2675             :   // Check if {value} is a Smi.
    2676          21 :   __ GotoIf(ObjectIsSmi(value), &done, zero);
    2677             : 
    2678             :   // Check if {value} is a HeapNumber.
    2679          21 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2680             :   __ GotoIfNot(__ WordEqual(value_map, __ HeapNumberMapConstant()), &done,
    2681          21 :                zero);
    2682             : 
    2683             :   // Check if {value} contains -0.
    2684          21 :   Node* value_value = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    2685          21 :   if (machine()->Is64()) {
    2686          21 :     Node* value64 = __ BitcastFloat64ToInt64(value_value);
    2687          21 :     __ Goto(&done, __ Word64Equal(value64, __ Int64Constant(kMinusZeroBits)));
    2688             :   } else {
    2689           0 :     Node* value_lo = __ Float64ExtractLowWord32(value_value);
    2690             :     __ GotoIfNot(__ Word32Equal(value_lo, __ Int32Constant(kMinusZeroLoBits)),
    2691           0 :                  &done, zero);
    2692           0 :     Node* value_hi = __ Float64ExtractHighWord32(value_value);
    2693             :     __ Goto(&done,
    2694           0 :             __ Word32Equal(value_hi, __ Int32Constant(kMinusZeroHiBits)));
    2695             :   }
    2696             : 
    2697             :   __ Bind(&done);
    2698          21 :   return done.PhiAt(0);
    2699             : }
    2700             : 
    2701          92 : Node* EffectControlLinearizer::LowerNumberIsMinusZero(Node* node) {
    2702             :   Node* value = node->InputAt(0);
    2703             : 
    2704          92 :   if (machine()->Is64()) {
    2705          92 :     Node* value64 = __ BitcastFloat64ToInt64(value);
    2706          92 :     return __ Word64Equal(value64, __ Int64Constant(kMinusZeroBits));
    2707             :   } else {
    2708           0 :     auto done = __ MakeLabel(MachineRepresentation::kBit);
    2709             : 
    2710           0 :     Node* value_lo = __ Float64ExtractLowWord32(value);
    2711             :     __ GotoIfNot(__ Word32Equal(value_lo, __ Int32Constant(kMinusZeroLoBits)),
    2712           0 :                  &done, __ Int32Constant(0));
    2713           0 :     Node* value_hi = __ Float64ExtractHighWord32(value);
    2714             :     __ Goto(&done,
    2715           0 :             __ Word32Equal(value_hi, __ Int32Constant(kMinusZeroHiBits)));
    2716             : 
    2717             :     __ Bind(&done);
    2718             :     return done.PhiAt(0);
    2719             :   }
    2720             : }
    2721             : 
    2722         685 : Node* EffectControlLinearizer::LowerObjectIsNaN(Node* node) {
    2723             :   Node* value = node->InputAt(0);
    2724         685 :   Node* zero = __ Int32Constant(0);
    2725             : 
    2726         685 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2727             : 
    2728             :   // Check if {value} is a Smi.
    2729         685 :   __ GotoIf(ObjectIsSmi(value), &done, zero);
    2730             : 
    2731             :   // Check if {value} is a HeapNumber.
    2732         685 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2733             :   __ GotoIfNot(__ WordEqual(value_map, __ HeapNumberMapConstant()), &done,
    2734         685 :                zero);
    2735             : 
    2736             :   // Check if {value} contains a NaN.
    2737         685 :   Node* value_value = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    2738             :   __ Goto(&done,
    2739         685 :           __ Word32Equal(__ Float64Equal(value_value, value_value), zero));
    2740             : 
    2741             :   __ Bind(&done);
    2742         685 :   return done.PhiAt(0);
    2743             : }
    2744             : 
    2745       10327 : Node* EffectControlLinearizer::LowerNumberIsNaN(Node* node) {
    2746             :   Node* number = node->InputAt(0);
    2747       10327 :   Node* diff = __ Float64Equal(number, number);
    2748       10327 :   Node* check = __ Word32Equal(diff, __ Int32Constant(0));
    2749       10327 :   return check;
    2750             : }
    2751             : 
    2752        5753 : Node* EffectControlLinearizer::LowerObjectIsNonCallable(Node* node) {
    2753             :   Node* value = node->InputAt(0);
    2754             : 
    2755        5753 :   auto if_primitive = __ MakeDeferredLabel();
    2756        5753 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2757             : 
    2758        5753 :   Node* check0 = ObjectIsSmi(value);
    2759        5753 :   __ GotoIf(check0, &if_primitive);
    2760             : 
    2761        5753 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2762             :   Node* value_instance_type =
    2763        5753 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    2764             :   STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
    2765             :   Node* check1 = __ Uint32LessThanOrEqual(
    2766        5753 :       __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type);
    2767        5753 :   __ GotoIfNot(check1, &if_primitive);
    2768             : 
    2769             :   Node* value_bit_field =
    2770        5753 :       __ LoadField(AccessBuilder::ForMapBitField(), value_map);
    2771             :   Node* check2 =
    2772             :       __ Word32Equal(__ Int32Constant(0),
    2773             :                      __ Word32And(value_bit_field,
    2774        5753 :                                   __ Int32Constant(Map::IsCallableBit::kMask)));
    2775             :   __ Goto(&done, check2);
    2776             : 
    2777             :   __ Bind(&if_primitive);
    2778        5753 :   __ Goto(&done, __ Int32Constant(0));
    2779             : 
    2780             :   __ Bind(&done);
    2781        5753 :   return done.PhiAt(0);
    2782             : }
    2783             : 
    2784        7213 : Node* EffectControlLinearizer::LowerObjectIsNumber(Node* node) {
    2785             :   Node* value = node->InputAt(0);
    2786             : 
    2787        7213 :   auto if_smi = __ MakeLabel();
    2788        7213 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2789             : 
    2790        7213 :   __ GotoIf(ObjectIsSmi(value), &if_smi);
    2791        7213 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2792        7213 :   __ Goto(&done, __ WordEqual(value_map, __ HeapNumberMapConstant()));
    2793             : 
    2794             :   __ Bind(&if_smi);
    2795        7213 :   __ Goto(&done, __ Int32Constant(1));
    2796             : 
    2797             :   __ Bind(&done);
    2798        7213 :   return done.PhiAt(0);
    2799             : }
    2800             : 
    2801       18235 : Node* EffectControlLinearizer::LowerObjectIsReceiver(Node* node) {
    2802             :   Node* value = node->InputAt(0);
    2803             : 
    2804       18235 :   auto if_smi = __ MakeDeferredLabel();
    2805       18235 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2806             : 
    2807       18235 :   __ GotoIf(ObjectIsSmi(value), &if_smi);
    2808             : 
    2809             :   STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
    2810       18237 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2811             :   Node* value_instance_type =
    2812       18237 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    2813             :   Node* result = __ Uint32LessThanOrEqual(
    2814       18236 :       __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type);
    2815             :   __ Goto(&done, result);
    2816             : 
    2817             :   __ Bind(&if_smi);
    2818       18237 :   __ Goto(&done, __ Int32Constant(0));
    2819             : 
    2820             :   __ Bind(&done);
    2821       18237 :   return done.PhiAt(0);
    2822             : }
    2823             : 
    2824        4720 : Node* EffectControlLinearizer::LowerObjectIsSmi(Node* node) {
    2825             :   Node* value = node->InputAt(0);
    2826        4720 :   return ObjectIsSmi(value);
    2827             : }
    2828             : 
    2829        1921 : Node* EffectControlLinearizer::LowerObjectIsString(Node* node) {
    2830             :   Node* value = node->InputAt(0);
    2831             : 
    2832        1921 :   auto if_smi = __ MakeDeferredLabel();
    2833        1921 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2834             : 
    2835        1921 :   Node* check = ObjectIsSmi(value);
    2836        1921 :   __ GotoIf(check, &if_smi);
    2837        1921 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2838             :   Node* value_instance_type =
    2839        1921 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    2840             :   Node* vfalse = __ Uint32LessThan(value_instance_type,
    2841        1921 :                                    __ Uint32Constant(FIRST_NONSTRING_TYPE));
    2842             :   __ Goto(&done, vfalse);
    2843             : 
    2844             :   __ Bind(&if_smi);
    2845        1921 :   __ Goto(&done, __ Int32Constant(0));
    2846             : 
    2847             :   __ Bind(&done);
    2848        1921 :   return done.PhiAt(0);
    2849             : }
    2850             : 
    2851          20 : Node* EffectControlLinearizer::LowerObjectIsSymbol(Node* node) {
    2852             :   Node* value = node->InputAt(0);
    2853             : 
    2854          20 :   auto if_smi = __ MakeDeferredLabel();
    2855          20 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2856             : 
    2857          20 :   Node* check = ObjectIsSmi(value);
    2858          20 :   __ GotoIf(check, &if_smi);
    2859          20 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2860             :   Node* value_instance_type =
    2861          20 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    2862             :   Node* vfalse =
    2863          20 :       __ Word32Equal(value_instance_type, __ Uint32Constant(SYMBOL_TYPE));
    2864             :   __ Goto(&done, vfalse);
    2865             : 
    2866             :   __ Bind(&if_smi);
    2867          20 :   __ Goto(&done, __ Int32Constant(0));
    2868             : 
    2869             :   __ Bind(&done);
    2870          20 :   return done.PhiAt(0);
    2871             : }
    2872             : 
    2873        1303 : Node* EffectControlLinearizer::LowerObjectIsUndetectable(Node* node) {
    2874             :   Node* value = node->InputAt(0);
    2875             : 
    2876        1303 :   auto if_smi = __ MakeDeferredLabel();
    2877        1303 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2878             : 
    2879        1303 :   Node* check = ObjectIsSmi(value);
    2880        1303 :   __ GotoIf(check, &if_smi);
    2881             : 
    2882        1303 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2883             :   Node* value_bit_field =
    2884        1303 :       __ LoadField(AccessBuilder::ForMapBitField(), value_map);
    2885             :   Node* vfalse = __ Word32Equal(
    2886             :       __ Word32Equal(
    2887             :           __ Int32Constant(0),
    2888             :           __ Word32And(value_bit_field,
    2889             :                        __ Int32Constant(Map::IsUndetectableBit::kMask))),
    2890        1303 :       __ Int32Constant(0));
    2891             :   __ Goto(&done, vfalse);
    2892             : 
    2893             :   __ Bind(&if_smi);
    2894        1303 :   __ Goto(&done, __ Int32Constant(0));
    2895             : 
    2896             :   __ Bind(&done);
    2897        1303 :   return done.PhiAt(0);
    2898             : }
    2899             : 
    2900       18996 : Node* EffectControlLinearizer::LowerTypeOf(Node* node) {
    2901             :   Node* obj = node->InputAt(0);
    2902       18996 :   Callable const callable = Builtins::CallableFor(isolate(), Builtins::kTypeof);
    2903             :   Operator::Properties const properties = Operator::kEliminatable;
    2904             :   CallDescriptor::Flags const flags = CallDescriptor::kNoAllocate;
    2905             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    2906             :       graph()->zone(), callable.descriptor(),
    2907       37992 :       callable.descriptor().GetStackParameterCount(), flags, properties);
    2908             :   return __ Call(call_descriptor, __ HeapConstant(callable.code()), obj,
    2909       37992 :                  __ NoContextConstant());
    2910             : }
    2911             : 
    2912         218 : Node* EffectControlLinearizer::LowerToBoolean(Node* node) {
    2913             :   Node* obj = node->InputAt(0);
    2914             :   Callable const callable =
    2915         218 :       Builtins::CallableFor(isolate(), Builtins::kToBoolean);
    2916             :   Operator::Properties const properties = Operator::kEliminatable;
    2917             :   CallDescriptor::Flags const flags = CallDescriptor::kNoAllocate;
    2918             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    2919             :       graph()->zone(), callable.descriptor(),
    2920         436 :       callable.descriptor().GetStackParameterCount(), flags, properties);
    2921             :   return __ Call(call_descriptor, __ HeapConstant(callable.code()), obj,
    2922         436 :                  __ NoContextConstant());
    2923             : }
    2924             : 
    2925       50004 : Node* EffectControlLinearizer::LowerArgumentsLength(Node* node) {
    2926       16668 :   Node* arguments_frame = NodeProperties::GetValueInput(node, 0);
    2927       16668 :   int formal_parameter_count = FormalParameterCountOf(node->op());
    2928       16668 :   bool is_rest_length = IsRestLengthOf(node->op());
    2929             :   DCHECK_LE(0, formal_parameter_count);
    2930             : 
    2931       16668 :   if (is_rest_length) {
    2932             :     // The ArgumentsLength node is computing the number of rest parameters,
    2933             :     // which is max(0, actual_parameter_count - formal_parameter_count).
    2934             :     // We have to distinguish the case, when there is an arguments adaptor frame
    2935             :     // (i.e., arguments_frame != LoadFramePointer()).
    2936         233 :     auto if_adaptor_frame = __ MakeLabel();
    2937         233 :     auto done = __ MakeLabel(MachineRepresentation::kTaggedSigned);
    2938             : 
    2939         233 :     Node* frame = __ LoadFramePointer();
    2940         233 :     __ GotoIf(__ WordEqual(arguments_frame, frame), &done, __ SmiConstant(0));
    2941             :     __ Goto(&if_adaptor_frame);
    2942             : 
    2943             :     __ Bind(&if_adaptor_frame);
    2944             :     Node* arguments_length = __ Load(
    2945             :         MachineType::TaggedSigned(), arguments_frame,
    2946         233 :         __ IntPtrConstant(ArgumentsAdaptorFrameConstants::kLengthOffset));
    2947             : 
    2948             :     Node* rest_length =
    2949         233 :         __ IntSub(arguments_length, __ SmiConstant(formal_parameter_count));
    2950             :     __ GotoIf(__ IntLessThan(rest_length, __ SmiConstant(0)), &done,
    2951         233 :               __ SmiConstant(0));
    2952             :     __ Goto(&done, rest_length);
    2953             : 
    2954             :     __ Bind(&done);
    2955             :     return done.PhiAt(0);
    2956             :   } else {
    2957             :     // The ArgumentsLength node is computing the actual number of arguments.
    2958             :     // We have to distinguish the case when there is an arguments adaptor frame
    2959             :     // (i.e., arguments_frame != LoadFramePointer()).
    2960       16435 :     auto if_adaptor_frame = __ MakeLabel();
    2961       16435 :     auto done = __ MakeLabel(MachineRepresentation::kTaggedSigned);
    2962             : 
    2963       16435 :     Node* frame = __ LoadFramePointer();
    2964             :     __ GotoIf(__ WordEqual(arguments_frame, frame), &done,
    2965       16435 :               __ SmiConstant(formal_parameter_count));
    2966             :     __ Goto(&if_adaptor_frame);
    2967             : 
    2968             :     __ Bind(&if_adaptor_frame);
    2969             :     Node* arguments_length = __ Load(
    2970             :         MachineType::TaggedSigned(), arguments_frame,
    2971       16435 :         __ IntPtrConstant(ArgumentsAdaptorFrameConstants::kLengthOffset));
    2972             :     __ Goto(&done, arguments_length);
    2973             : 
    2974             :     __ Bind(&done);
    2975             :     return done.PhiAt(0);
    2976             :   }
    2977             : }
    2978             : 
    2979       16640 : Node* EffectControlLinearizer::LowerArgumentsFrame(Node* node) {
    2980       16640 :   auto done = __ MakeLabel(MachineType::PointerRepresentation());
    2981             : 
    2982       16640 :   Node* frame = __ LoadFramePointer();
    2983             :   Node* parent_frame =
    2984             :       __ Load(MachineType::Pointer(), frame,
    2985       16640 :               __ IntPtrConstant(StandardFrameConstants::kCallerFPOffset));
    2986             :   Node* parent_frame_type = __ Load(
    2987             :       MachineType::AnyTagged(), parent_frame,
    2988       16640 :       __ IntPtrConstant(CommonFrameConstants::kContextOrFrameTypeOffset));
    2989             :   __ GotoIf(__ WordEqual(parent_frame_type,
    2990             :                          __ IntPtrConstant(StackFrame::TypeToMarker(
    2991             :                              StackFrame::ARGUMENTS_ADAPTOR))),
    2992       16640 :             &done, parent_frame);
    2993             :   __ Goto(&done, frame);
    2994             : 
    2995             :   __ Bind(&done);
    2996       16640 :   return done.PhiAt(0);
    2997             : }
    2998             : 
    2999          28 : Node* EffectControlLinearizer::LowerNewDoubleElements(Node* node) {
    3000          28 :   PretenureFlag const pretenure = PretenureFlagOf(node->op());
    3001             :   Node* length = node->InputAt(0);
    3002             : 
    3003          28 :   auto done = __ MakeLabel(MachineRepresentation::kTaggedPointer);
    3004          28 :   Node* zero_length = __ Word32Equal(length, __ Int32Constant(0));
    3005             :   __ GotoIf(zero_length, &done,
    3006          28 :             jsgraph()->HeapConstant(factory()->empty_fixed_array()));
    3007             : 
    3008             :   // Compute the effective size of the backing store.
    3009             :   Node* size =
    3010             :       __ Int32Add(__ Word32Shl(length, __ Int32Constant(kDoubleSizeLog2)),
    3011          28 :                   __ Int32Constant(FixedDoubleArray::kHeaderSize));
    3012             : 
    3013             :   // Allocate the result and initialize the header.
    3014          28 :   Node* result = __ Allocate(pretenure, size);
    3015             :   __ StoreField(AccessBuilder::ForMap(), result,
    3016          28 :                 __ FixedDoubleArrayMapConstant());
    3017             :   __ StoreField(AccessBuilder::ForFixedArrayLength(), result,
    3018          28 :                 ChangeInt32ToSmi(length));
    3019             : 
    3020             :   // Initialize the backing store with holes.
    3021             :   STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    3022             :   Node* limit = ChangeUint32ToUintPtr(length);
    3023             :   Node* the_hole =
    3024          28 :       __ LoadField(AccessBuilder::ForHeapNumberValue(), __ TheHoleConstant());
    3025          28 :   auto loop = __ MakeLoopLabel(MachineType::PointerRepresentation());
    3026          28 :   __ Goto(&loop, __ IntPtrConstant(0));
    3027             :   __ Bind(&loop);
    3028             :   {
    3029             :     // Check if we've initialized everything.
    3030             :     Node* index = loop.PhiAt(0);
    3031          28 :     Node* check = __ UintLessThan(index, limit);
    3032          28 :     __ GotoIfNot(check, &done, result);
    3033             : 
    3034             :     // Storing "the_hole" doesn't need a write barrier.
    3035             :     StoreRepresentation rep(MachineRepresentation::kFloat64, kNoWriteBarrier);
    3036             :     Node* offset = __ IntAdd(
    3037             :         __ WordShl(index, __ IntPtrConstant(kDoubleSizeLog2)),
    3038          28 :         __ IntPtrConstant(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
    3039          28 :     __ Store(rep, result, offset, the_hole);
    3040             : 
    3041             :     // Advance the {index}.
    3042          28 :     index = __ IntAdd(index, __ IntPtrConstant(1));
    3043             :     __ Goto(&loop, index);
    3044             :   }
    3045             : 
    3046             :   __ Bind(&done);
    3047          28 :   return done.PhiAt(0);
    3048             : }
    3049             : 
    3050         507 : Node* EffectControlLinearizer::LowerNewSmiOrObjectElements(Node* node) {
    3051         507 :   PretenureFlag const pretenure = PretenureFlagOf(node->op());
    3052             :   Node* length = node->InputAt(0);
    3053             : 
    3054         507 :   auto done = __ MakeLabel(MachineRepresentation::kTaggedPointer);
    3055         507 :   Node* zero_length = __ Word32Equal(length, __ Int32Constant(0));
    3056             :   __ GotoIf(zero_length, &done,
    3057         507 :             jsgraph()->HeapConstant(factory()->empty_fixed_array()));
    3058             : 
    3059             :   // Compute the effective size of the backing store.
    3060             :   Node* size =
    3061             :       __ Int32Add(__ Word32Shl(length, __ Int32Constant(kTaggedSizeLog2)),
    3062         507 :                   __ Int32Constant(FixedArray::kHeaderSize));
    3063             : 
    3064             :   // Allocate the result and initialize the header.
    3065         507 :   Node* result = __ Allocate(pretenure, size);
    3066         507 :   __ StoreField(AccessBuilder::ForMap(), result, __ FixedArrayMapConstant());
    3067             :   __ StoreField(AccessBuilder::ForFixedArrayLength(), result,
    3068         507 :                 ChangeInt32ToSmi(length));
    3069             : 
    3070             :   // Initialize the backing store with holes.
    3071             :   Node* limit = ChangeUint32ToUintPtr(length);
    3072         507 :   Node* the_hole = __ TheHoleConstant();
    3073         507 :   auto loop = __ MakeLoopLabel(MachineType::PointerRepresentation());
    3074         507 :   __ Goto(&loop, __ IntPtrConstant(0));
    3075             :   __ Bind(&loop);
    3076             :   {
    3077             :     // Check if we've initialized everything.
    3078             :     Node* index = loop.PhiAt(0);
    3079         507 :     Node* check = __ UintLessThan(index, limit);
    3080         507 :     __ GotoIfNot(check, &done, result);
    3081             : 
    3082             :     // Storing "the_hole" doesn't need a write barrier.
    3083             :     StoreRepresentation rep(MachineRepresentation::kTagged, kNoWriteBarrier);
    3084             :     Node* offset =
    3085             :         __ IntAdd(__ WordShl(index, __ IntPtrConstant(kTaggedSizeLog2)),
    3086         507 :                   __ IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag));
    3087         507 :     __ Store(rep, result, offset, the_hole);
    3088             : 
    3089             :     // Advance the {index}.
    3090         507 :     index = __ IntAdd(index, __ IntPtrConstant(1));
    3091             :     __ Goto(&loop, index);
    3092             :   }
    3093             : 
    3094             :   __ Bind(&done);
    3095         507 :   return done.PhiAt(0);
    3096             : }
    3097             : 
    3098       48465 : Node* EffectControlLinearizer::LowerNewArgumentsElements(Node* node) {
    3099       16155 :   Node* frame = NodeProperties::GetValueInput(node, 0);
    3100       16155 :   Node* length = NodeProperties::GetValueInput(node, 1);
    3101       16155 :   int mapped_count = NewArgumentsElementsMappedCountOf(node->op());
    3102             : 
    3103             :   Callable const callable =
    3104       16155 :       Builtins::CallableFor(isolate(), Builtins::kNewArgumentsElements);
    3105       16155 :   Operator::Properties const properties = node->op()->properties();
    3106             :   CallDescriptor::Flags const flags = CallDescriptor::kNoFlags;
    3107             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    3108             :       graph()->zone(), callable.descriptor(),
    3109       32310 :       callable.descriptor().GetStackParameterCount(), flags, properties);
    3110             :   return __ Call(call_descriptor, __ HeapConstant(callable.code()), frame,
    3111       32310 :                  length, __ SmiConstant(mapped_count), __ NoContextConstant());
    3112             : }
    3113             : 
    3114        3328 : Node* EffectControlLinearizer::LowerNewConsString(Node* node) {
    3115             :   Node* length = node->InputAt(0);
    3116             :   Node* first = node->InputAt(1);
    3117             :   Node* second = node->InputAt(2);
    3118             : 
    3119             :   // Determine the instance types of {first} and {second}.
    3120        3328 :   Node* first_map = __ LoadField(AccessBuilder::ForMap(), first);
    3121             :   Node* first_instance_type =
    3122        3328 :       __ LoadField(AccessBuilder::ForMapInstanceType(), first_map);
    3123        3328 :   Node* second_map = __ LoadField(AccessBuilder::ForMap(), second);
    3124             :   Node* second_instance_type =
    3125        3328 :       __ LoadField(AccessBuilder::ForMapInstanceType(), second_map);
    3126             : 
    3127             :   // Determine the proper map for the resulting ConsString.
    3128             :   // If both {first} and {second} are one-byte strings, we
    3129             :   // create a new ConsOneByteString, otherwise we create a
    3130             :   // new ConsString instead.
    3131        3328 :   auto if_onebyte = __ MakeLabel();
    3132        3328 :   auto if_twobyte = __ MakeLabel();
    3133        3328 :   auto done = __ MakeLabel(MachineRepresentation::kTaggedPointer);
    3134             :   STATIC_ASSERT(kOneByteStringTag != 0);
    3135             :   STATIC_ASSERT(kTwoByteStringTag == 0);
    3136        3328 :   Node* instance_type = __ Word32And(first_instance_type, second_instance_type);
    3137             :   Node* encoding =
    3138        3328 :       __ Word32And(instance_type, __ Int32Constant(kStringEncodingMask));
    3139             :   __ Branch(__ Word32Equal(encoding, __ Int32Constant(kTwoByteStringTag)),
    3140        3328 :             &if_twobyte, &if_onebyte);
    3141             :   __ Bind(&if_onebyte);
    3142             :   __ Goto(&done,
    3143        6656 :           jsgraph()->HeapConstant(factory()->cons_one_byte_string_map()));
    3144             :   __ Bind(&if_twobyte);
    3145        6656 :   __ Goto(&done, jsgraph()->HeapConstant(factory()->cons_string_map()));
    3146             :   __ Bind(&done);
    3147             :   Node* result_map = done.PhiAt(0);
    3148             : 
    3149             :   // Allocate the resulting ConsString.
    3150        3328 :   Node* result = __ Allocate(NOT_TENURED, __ Int32Constant(ConsString::kSize));
    3151        3328 :   __ StoreField(AccessBuilder::ForMap(), result, result_map);
    3152             :   __ StoreField(AccessBuilder::ForNameHashField(), result,
    3153        3328 :                 __ Int32Constant(Name::kEmptyHashField));
    3154        3328 :   __ StoreField(AccessBuilder::ForStringLength(), result, length);
    3155        3328 :   __ StoreField(AccessBuilder::ForConsStringFirst(), result, first);
    3156        3328 :   __ StoreField(AccessBuilder::ForConsStringSecond(), result, second);
    3157        3328 :   return result;
    3158             : }
    3159             : 
    3160          12 : Node* EffectControlLinearizer::LowerSameValue(Node* node) {
    3161             :   Node* lhs = node->InputAt(0);
    3162             :   Node* rhs = node->InputAt(1);
    3163             : 
    3164             :   Callable const callable =
    3165          12 :       Builtins::CallableFor(isolate(), Builtins::kSameValue);
    3166             :   Operator::Properties properties = Operator::kEliminatable;
    3167             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    3168             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    3169             :       graph()->zone(), callable.descriptor(),
    3170          24 :       callable.descriptor().GetStackParameterCount(), flags, properties);
    3171             :   return __ Call(call_descriptor, __ HeapConstant(callable.code()), lhs, rhs,
    3172          24 :                  __ NoContextConstant());
    3173             : }
    3174             : 
    3175        1243 : Node* EffectControlLinearizer::LowerDeadValue(Node* node) {
    3176        1243 :   Node* input = NodeProperties::GetValueInput(node, 0);
    3177        1243 :   if (input->opcode() != IrOpcode::kUnreachable) {
    3178         959 :     Node* unreachable = __ Unreachable();
    3179         959 :     NodeProperties::ReplaceValueInput(node, unreachable, 0);
    3180             :   }
    3181        1243 :   return node;
    3182             : }
    3183             : 
    3184         344 : Node* EffectControlLinearizer::LowerStringToNumber(Node* node) {
    3185             :   Node* string = node->InputAt(0);
    3186             : 
    3187             :   Callable const callable =
    3188         344 :       Builtins::CallableFor(isolate(), Builtins::kStringToNumber);
    3189             :   Operator::Properties properties = Operator::kEliminatable;
    3190             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    3191             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    3192             :       graph()->zone(), callable.descriptor(),
    3193         688 :       callable.descriptor().GetStackParameterCount(), flags, properties);
    3194             :   return __ Call(call_descriptor, __ HeapConstant(callable.code()), string,
    3195         688 :                  __ NoContextConstant());
    3196             : }
    3197             : 
    3198        2398 : Node* EffectControlLinearizer::LowerStringCharCodeAt(Node* node) {
    3199             :   Node* receiver = node->InputAt(0);
    3200             :   Node* position = node->InputAt(1);
    3201             : 
    3202             :   // We need a loop here to properly deal with indirect strings
    3203             :   // (SlicedString, ConsString and ThinString).
    3204             :   auto loop = __ MakeLoopLabel(MachineRepresentation::kTagged,
    3205        2398 :                                MachineType::PointerRepresentation());
    3206             :   auto loop_next = __ MakeLabel(MachineRepresentation::kTagged,
    3207        2398 :                                 MachineType::PointerRepresentation());
    3208        2398 :   auto loop_done = __ MakeLabel(MachineRepresentation::kWord32);
    3209        2398 :   __ Goto(&loop, receiver, position);
    3210             :   __ Bind(&loop);
    3211             :   {
    3212             :     Node* receiver = loop.PhiAt(0);
    3213             :     Node* position = loop.PhiAt(1);
    3214        2398 :     Node* receiver_map = __ LoadField(AccessBuilder::ForMap(), receiver);
    3215             :     Node* receiver_instance_type =
    3216        2398 :         __ LoadField(AccessBuilder::ForMapInstanceType(), receiver_map);
    3217             :     Node* receiver_representation = __ Word32And(
    3218        2398 :         receiver_instance_type, __ Int32Constant(kStringRepresentationMask));
    3219             : 
    3220             :     // Dispatch on the current {receiver}s string representation.
    3221        2398 :     auto if_seqstring = __ MakeLabel();
    3222        2398 :     auto if_consstring = __ MakeLabel();
    3223        2398 :     auto if_thinstring = __ MakeLabel();
    3224        2398 :     auto if_externalstring = __ MakeLabel();
    3225        2398 :     auto if_slicedstring = __ MakeLabel();
    3226        2398 :     auto if_runtime = __ MakeDeferredLabel();
    3227             :     __ GotoIf(__ Word32Equal(receiver_representation,
    3228             :                              __ Int32Constant(kSeqStringTag)),
    3229        2398 :               &if_seqstring);
    3230             :     __ GotoIf(__ Word32Equal(receiver_representation,
    3231             :                              __ Int32Constant(kConsStringTag)),
    3232        2398 :               &if_consstring);
    3233             :     __ GotoIf(__ Word32Equal(receiver_representation,
    3234             :                              __ Int32Constant(kThinStringTag)),
    3235        2398 :               &if_thinstring);
    3236             :     __ GotoIf(__ Word32Equal(receiver_representation,
    3237             :                              __ Int32Constant(kExternalStringTag)),
    3238        2398 :               &if_externalstring);
    3239             :     __ Branch(__ Word32Equal(receiver_representation,
    3240             :                              __ Int32Constant(kSlicedStringTag)),
    3241        2398 :               &if_slicedstring, &if_runtime);
    3242             : 
    3243             :     __ Bind(&if_seqstring);
    3244             :     {
    3245             :       Node* receiver_is_onebyte = __ Word32Equal(
    3246             :           __ Word32Equal(__ Word32And(receiver_instance_type,
    3247             :                                       __ Int32Constant(kStringEncodingMask)),
    3248             :                          __ Int32Constant(kTwoByteStringTag)),
    3249        2398 :           __ Int32Constant(0));
    3250        2398 :       Node* result = LoadFromSeqString(receiver, position, receiver_is_onebyte);
    3251             :       __ Goto(&loop_done, result);
    3252             :     }
    3253             : 
    3254             :     __ Bind(&if_thinstring);
    3255             :     {
    3256             :       Node* receiver_actual =
    3257        2398 :           __ LoadField(AccessBuilder::ForThinStringActual(), receiver);
    3258             :       __ Goto(&loop_next, receiver_actual, position);
    3259             :     }
    3260             : 
    3261             :     __ Bind(&if_consstring);
    3262             :     {
    3263             :       Node* receiver_second =
    3264        2398 :           __ LoadField(AccessBuilder::ForConsStringSecond(), receiver);
    3265             :       __ GotoIfNot(__ WordEqual(receiver_second, __ EmptyStringConstant()),
    3266        2398 :                    &if_runtime);
    3267             :       Node* receiver_first =
    3268        2398 :           __ LoadField(AccessBuilder::ForConsStringFirst(), receiver);
    3269             :       __ Goto(&loop_next, receiver_first, position);
    3270             :     }
    3271             : 
    3272             :     __ Bind(&if_externalstring);
    3273             :     {
    3274             :       // We need to bailout to the runtime for uncached external strings.
    3275             :       __ GotoIf(__ Word32Equal(
    3276             :                     __ Word32And(receiver_instance_type,
    3277             :                                  __ Int32Constant(kUncachedExternalStringMask)),
    3278             :                     __ Int32Constant(kUncachedExternalStringTag)),
    3279        2398 :                 &if_runtime);
    3280             : 
    3281             :       Node* receiver_data = __ LoadField(
    3282        2398 :           AccessBuilder::ForExternalStringResourceData(), receiver);
    3283             : 
    3284        2398 :       auto if_onebyte = __ MakeLabel();
    3285        2398 :       auto if_twobyte = __ MakeLabel();
    3286             :       __ Branch(
    3287             :           __ Word32Equal(__ Word32And(receiver_instance_type,
    3288             :                                       __ Int32Constant(kStringEncodingMask)),
    3289             :                          __ Int32Constant(kTwoByteStringTag)),
    3290        2398 :           &if_twobyte, &if_onebyte);
    3291             : 
    3292             :       __ Bind(&if_onebyte);
    3293             :       {
    3294        2398 :         Node* result = __ Load(MachineType::Uint8(), receiver_data, position);
    3295             :         __ Goto(&loop_done, result);
    3296             :       }
    3297             : 
    3298             :       __ Bind(&if_twobyte);
    3299             :       {
    3300             :         Node* result = __ Load(MachineType::Uint16(), receiver_data,
    3301        2398 :                                __ WordShl(position, __ IntPtrConstant(1)));
    3302             :         __ Goto(&loop_done, result);
    3303             :       }
    3304             :     }
    3305             : 
    3306             :     __ Bind(&if_slicedstring);
    3307             :     {
    3308             :       Node* receiver_offset =
    3309        2398 :           __ LoadField(AccessBuilder::ForSlicedStringOffset(), receiver);
    3310             :       Node* receiver_parent =
    3311        2398 :           __ LoadField(AccessBuilder::ForSlicedStringParent(), receiver);
    3312             :       __ Goto(&loop_next, receiver_parent,
    3313        2398 :               __ IntAdd(position, ChangeSmiToIntPtr(receiver_offset)));
    3314             :     }
    3315             : 
    3316             :     __ Bind(&if_runtime);
    3317             :     {
    3318        2398 :       Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
    3319             :       Runtime::FunctionId id = Runtime::kStringCharCodeAt;
    3320             :       auto call_descriptor = Linkage::GetRuntimeCallDescriptor(
    3321        2398 :           graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags);
    3322             :       Node* result = __ Call(call_descriptor, __ CEntryStubConstant(1),
    3323             :                              receiver, ChangeIntPtrToSmi(position),
    3324             :                              __ ExternalConstant(ExternalReference::Create(id)),
    3325        2398 :                              __ Int32Constant(2), __ NoContextConstant());
    3326        2398 :       __ Goto(&loop_done, ChangeSmiToInt32(result));
    3327             :     }
    3328             : 
    3329             :     __ Bind(&loop_next);
    3330             :     __ Goto(&loop, loop_next.PhiAt(0), loop_next.PhiAt(1));
    3331             :   }
    3332             :   __ Bind(&loop_done);
    3333        2398 :   return loop_done.PhiAt(0);
    3334             : }
    3335             : 
    3336         249 : Node* EffectControlLinearizer::LowerStringCodePointAt(
    3337             :     Node* node, UnicodeEncoding encoding) {
    3338             :   Node* receiver = node->InputAt(0);
    3339             :   Node* position = node->InputAt(1);
    3340             : 
    3341             :   Builtins::Name builtin = encoding == UnicodeEncoding::UTF16
    3342             :                                ? Builtins::kStringCodePointAtUTF16
    3343         249 :                                : Builtins::kStringCodePointAtUTF32;
    3344             : 
    3345         249 :   Callable const callable = Builtins::CallableFor(isolate(), builtin);
    3346         249 :   Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite;
    3347             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    3348             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    3349             :       graph()->zone(), callable.descriptor(),
    3350         498 :       callable.descriptor().GetStackParameterCount(), flags, properties);
    3351             :   return __ Call(call_descriptor, __ HeapConstant(callable.code()), receiver,
    3352         498 :                  position, __ NoContextConstant());
    3353             : }
    3354             : 
    3355        2398 : Node* EffectControlLinearizer::LoadFromSeqString(Node* receiver, Node* position,
    3356             :                                                  Node* is_one_byte) {
    3357        2398 :   auto one_byte_load = __ MakeLabel();
    3358        2398 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    3359        2398 :   __ GotoIf(is_one_byte, &one_byte_load);
    3360             :   Node* two_byte_result = __ LoadElement(
    3361        2398 :       AccessBuilder::ForSeqTwoByteStringCharacter(), receiver, position);
    3362             :   __ Goto(&done, two_byte_result);
    3363             : 
    3364             :   __ Bind(&one_byte_load);
    3365             :   Node* one_byte_element = __ LoadElement(
    3366        2398 :       AccessBuilder::ForSeqOneByteStringCharacter(), receiver, position);
    3367             :   __ Goto(&done, one_byte_element);
    3368             : 
    3369             :   __ Bind(&done);
    3370        2398 :   return done.PhiAt(0);
    3371             : }
    3372             : 
    3373         966 : Node* EffectControlLinearizer::LowerStringFromSingleCharCode(Node* node) {
    3374             :   Node* value = node->InputAt(0);
    3375         966 :   Node* code = __ Word32And(value, __ Uint32Constant(0xFFFF));
    3376             : 
    3377         966 :   auto if_not_one_byte = __ MakeDeferredLabel();
    3378         966 :   auto cache_miss = __ MakeDeferredLabel();
    3379         966 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    3380             : 
    3381             :   // Check if the {code} is a one byte character
    3382             :   Node* check1 = __ Uint32LessThanOrEqual(
    3383         966 :       code, __ Uint32Constant(String::kMaxOneByteCharCode));
    3384         966 :   __ GotoIfNot(check1, &if_not_one_byte);
    3385             :   {
    3386             :     // Load the isolate wide single character string cache.
    3387         966 :     Node* cache = __ HeapConstant(factory()->single_character_string_cache());
    3388             : 
    3389             :     // Compute the {cache} index for {code}.
    3390         966 :     Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code);
    3391             : 
    3392             :     // Check if we have an entry for the {code} in the single character string
    3393             :     // cache already.
    3394             :     Node* entry =
    3395         966 :         __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index);
    3396             : 
    3397         966 :     Node* check2 = __ WordEqual(entry, __ UndefinedConstant());
    3398         966 :     __ GotoIf(check2, &cache_miss);
    3399             : 
    3400             :     // Use the {entry} from the {cache}.
    3401             :     __ Goto(&done, entry);
    3402             : 
    3403             :     __ Bind(&cache_miss);
    3404             :     {
    3405             :       // Allocate a new SeqOneByteString for {code}.
    3406             :       Node* vtrue2 = __ Allocate(
    3407         966 :           NOT_TENURED, __ Int32Constant(SeqOneByteString::SizeFor(1)));
    3408             :       __ StoreField(AccessBuilder::ForMap(), vtrue2,
    3409         966 :                     __ HeapConstant(factory()->one_byte_string_map()));
    3410             :       __ StoreField(AccessBuilder::ForNameHashField(), vtrue2,
    3411         966 :                     __ Int32Constant(Name::kEmptyHashField));
    3412             :       __ StoreField(AccessBuilder::ForStringLength(), vtrue2,
    3413         966 :                     __ Int32Constant(1));
    3414             :       __ Store(
    3415             :           StoreRepresentation(MachineRepresentation::kWord8, kNoWriteBarrier),
    3416             :           vtrue2,
    3417             :           __ IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag),
    3418        1932 :           code);
    3419             : 
    3420             :       // Remember it in the {cache}.
    3421             :       __ StoreElement(AccessBuilder::ForFixedArrayElement(), cache, index,
    3422         966 :                       vtrue2);
    3423             :       __ Goto(&done, vtrue2);
    3424             :     }
    3425             :   }
    3426             : 
    3427             :   __ Bind(&if_not_one_byte);
    3428             :   {
    3429             :     // Allocate a new SeqTwoByteString for {code}.
    3430             :     Node* vfalse1 = __ Allocate(NOT_TENURED,
    3431         966 :                                 __ Int32Constant(SeqTwoByteString::SizeFor(1)));
    3432             :     __ StoreField(AccessBuilder::ForMap(), vfalse1,
    3433         966 :                   __ HeapConstant(factory()->string_map()));
    3434             :     __ StoreField(AccessBuilder::ForNameHashField(), vfalse1,
    3435         966 :                   __ Int32Constant(Name::kEmptyHashField));
    3436             :     __ StoreField(AccessBuilder::ForStringLength(), vfalse1,
    3437         966 :                   __ Int32Constant(1));
    3438             :     __ Store(
    3439             :         StoreRepresentation(MachineRepresentation::kWord16, kNoWriteBarrier),
    3440             :         vfalse1,
    3441             :         __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag),
    3442        1932 :         code);
    3443             :     __ Goto(&done, vfalse1);
    3444             :   }
    3445             : 
    3446             :   __ Bind(&done);
    3447         966 :   return done.PhiAt(0);
    3448             : }
    3449             : 
    3450             : #ifdef V8_INTL_SUPPORT
    3451             : 
    3452          88 : Node* EffectControlLinearizer::LowerStringToLowerCaseIntl(Node* node) {
    3453             :   Node* receiver = node->InputAt(0);
    3454             : 
    3455             :   Callable callable =
    3456          88 :       Builtins::CallableFor(isolate(), Builtins::kStringToLowerCaseIntl);
    3457          88 :   Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
    3458             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    3459             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    3460             :       graph()->zone(), callable.descriptor(),
    3461         176 :       callable.descriptor().GetStackParameterCount(), flags, properties);
    3462             :   return __ Call(call_descriptor, __ HeapConstant(callable.code()), receiver,
    3463         176 :                  __ NoContextConstant());
    3464             : }
    3465             : 
    3466          28 : Node* EffectControlLinearizer::LowerStringToUpperCaseIntl(Node* node) {
    3467             :   Node* receiver = node->InputAt(0);
    3468          28 :   Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
    3469             :   Runtime::FunctionId id = Runtime::kStringToUpperCaseIntl;
    3470             :   auto call_descriptor = Linkage::GetRuntimeCallDescriptor(
    3471          28 :       graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags);
    3472             :   return __ Call(call_descriptor, __ CEntryStubConstant(1), receiver,
    3473             :                  __ ExternalConstant(ExternalReference::Create(id)),
    3474          28 :                  __ Int32Constant(1), __ NoContextConstant());
    3475             : }
    3476             : 
    3477             : #else
    3478             : 
    3479             : Node* EffectControlLinearizer::LowerStringToLowerCaseIntl(Node* node) {
    3480             :   UNREACHABLE();
    3481             :   return nullptr;
    3482             : }
    3483             : 
    3484             : Node* EffectControlLinearizer::LowerStringToUpperCaseIntl(Node* node) {
    3485             :   UNREACHABLE();
    3486             :   return nullptr;
    3487             : }
    3488             : 
    3489             : #endif  // V8_INTL_SUPPORT
    3490             : 
    3491         444 : Node* EffectControlLinearizer::LowerStringFromSingleCodePoint(Node* node) {
    3492             :   Node* value = node->InputAt(0);
    3493             :   Node* code = value;
    3494             : 
    3495         222 :   auto if_not_single_code = __ MakeDeferredLabel();
    3496         222 :   auto if_not_one_byte = __ MakeDeferredLabel();
    3497         222 :   auto cache_miss = __ MakeDeferredLabel();
    3498         222 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    3499             : 
    3500             :   // Check if the {code} is a single code unit
    3501         222 :   Node* check0 = __ Uint32LessThanOrEqual(code, __ Uint32Constant(0xFFFF));
    3502         222 :   __ GotoIfNot(check0, &if_not_single_code);
    3503             : 
    3504             :   {
    3505             :     // Check if the {code} is a one byte character
    3506             :     Node* check1 = __ Uint32LessThanOrEqual(
    3507         222 :         code, __ Uint32Constant(String::kMaxOneByteCharCode));
    3508         222 :     __ GotoIfNot(check1, &if_not_one_byte);
    3509             :     {
    3510             :       // Load the isolate wide single character string cache.
    3511         222 :       Node* cache = __ HeapConstant(factory()->single_character_string_cache());
    3512             : 
    3513             :       // Compute the {cache} index for {code}.
    3514         222 :       Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code);
    3515             : 
    3516             :       // Check if we have an entry for the {code} in the single character string
    3517             :       // cache already.
    3518             :       Node* entry =
    3519         222 :           __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index);
    3520             : 
    3521         222 :       Node* check2 = __ WordEqual(entry, __ UndefinedConstant());
    3522         222 :       __ GotoIf(check2, &cache_miss);
    3523             : 
    3524             :       // Use the {entry} from the {cache}.
    3525             :       __ Goto(&done, entry);
    3526             : 
    3527             :       __ Bind(&cache_miss);
    3528             :       {
    3529             :         // Allocate a new SeqOneByteString for {code}.
    3530             :         Node* vtrue2 = __ Allocate(
    3531         222 :             NOT_TENURED, __ Int32Constant(SeqOneByteString::SizeFor(1)));
    3532             :         __ StoreField(AccessBuilder::ForMap(), vtrue2,
    3533         222 :                       __ HeapConstant(factory()->one_byte_string_map()));
    3534             :         __ StoreField(AccessBuilder::ForNameHashField(), vtrue2,
    3535         222 :                       __ Int32Constant(Name::kEmptyHashField));
    3536             :         __ StoreField(AccessBuilder::ForStringLength(), vtrue2,
    3537         222 :                       __ Int32Constant(1));
    3538             :         __ Store(
    3539             :             StoreRepresentation(MachineRepresentation::kWord8, kNoWriteBarrier),
    3540             :             vtrue2,
    3541             :             __ IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag),
    3542         444 :             code);
    3543             : 
    3544             :         // Remember it in the {cache}.
    3545             :         __ StoreElement(AccessBuilder::ForFixedArrayElement(), cache, index,
    3546         222 :                         vtrue2);
    3547             :         __ Goto(&done, vtrue2);
    3548             :       }
    3549             :     }
    3550             : 
    3551             :     __ Bind(&if_not_one_byte);
    3552             :     {
    3553             :       // Allocate a new SeqTwoByteString for {code}.
    3554             :       Node* vfalse1 = __ Allocate(
    3555         222 :           NOT_TENURED, __ Int32Constant(SeqTwoByteString::SizeFor(1)));
    3556             :       __ StoreField(AccessBuilder::ForMap(), vfalse1,
    3557         222 :                     __ HeapConstant(factory()->string_map()));
    3558             :       __ StoreField(AccessBuilder::ForNameHashField(), vfalse1,
    3559         222 :                     __ IntPtrConstant(Name::kEmptyHashField));
    3560             :       __ StoreField(AccessBuilder::ForStringLength(), vfalse1,
    3561         222 :                     __ Int32Constant(1));
    3562             :       __ Store(
    3563             :           StoreRepresentation(MachineRepresentation::kWord16, kNoWriteBarrier),
    3564             :           vfalse1,
    3565             :           __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag),
    3566         444 :           code);
    3567             :       __ Goto(&done, vfalse1);
    3568             :     }
    3569             :   }
    3570             : 
    3571             :   __ Bind(&if_not_single_code);
    3572             :   // Generate surrogate pair string
    3573             :   {
    3574         222 :     switch (UnicodeEncodingOf(node->op())) {
    3575             :       case UnicodeEncoding::UTF16:
    3576             :         break;
    3577             : 
    3578             :       case UnicodeEncoding::UTF32: {
    3579             :         // Convert UTF32 to UTF16 code units, and store as a 32 bit word.
    3580          99 :         Node* lead_offset = __ Int32Constant(0xD800 - (0x10000 >> 10));
    3581             : 
    3582             :         // lead = (codepoint >> 10) + LEAD_OFFSET
    3583             :         Node* lead =
    3584          99 :             __ Int32Add(__ Word32Shr(code, __ Int32Constant(10)), lead_offset);
    3585             : 
    3586             :         // trail = (codepoint & 0x3FF) + 0xDC00;
    3587             :         Node* trail = __ Int32Add(__ Word32And(code, __ Int32Constant(0x3FF)),
    3588          99 :                                   __ Int32Constant(0xDC00));
    3589             : 
    3590             :         // codpoint = (trail << 16) | lead;
    3591             : #if V8_TARGET_BIG_ENDIAN
    3592             :         code = __ Word32Or(__ Word32Shl(lead, __ Int32Constant(16)), trail);
    3593             : #else
    3594          99 :         code = __ Word32Or(__ Word32Shl(trail, __ Int32Constant(16)), lead);
    3595             : #endif
    3596          99 :         break;
    3597             :       }
    3598             :     }
    3599             : 
    3600             :     // Allocate a new SeqTwoByteString for {code}.
    3601             :     Node* vfalse0 = __ Allocate(NOT_TENURED,
    3602         222 :                                 __ Int32Constant(SeqTwoByteString::SizeFor(2)));
    3603             :     __ StoreField(AccessBuilder::ForMap(), vfalse0,
    3604         222 :                   __ HeapConstant(factory()->string_map()));
    3605             :     __ StoreField(AccessBuilder::ForNameHashField(), vfalse0,
    3606         222 :                   __ Int32Constant(Name::kEmptyHashField));
    3607             :     __ StoreField(AccessBuilder::ForStringLength(), vfalse0,
    3608         222 :                   __ Int32Constant(2));
    3609             :     __ Store(
    3610             :         StoreRepresentation(MachineRepresentation::kWord32, kNoWriteBarrier),
    3611             :         vfalse0,
    3612             :         __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag),
    3613         444 :         code);
    3614             :     __ Goto(&done, vfalse0);
    3615             :   }
    3616             : 
    3617             :   __ Bind(&done);
    3618         222 :   return done.PhiAt(0);
    3619             : }
    3620             : 
    3621         289 : Node* EffectControlLinearizer::LowerStringIndexOf(Node* node) {
    3622             :   Node* subject = node->InputAt(0);
    3623             :   Node* search_string = node->InputAt(1);
    3624             :   Node* position = node->InputAt(2);
    3625             : 
    3626             :   Callable callable =
    3627         289 :       Builtins::CallableFor(isolate(), Builtins::kStringIndexOf);
    3628             :   Operator::Properties properties = Operator::kEliminatable;
    3629             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    3630             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    3631             :       graph()->zone(), callable.descriptor(),
    3632         578 :       callable.descriptor().GetStackParameterCount(), flags, properties);
    3633             :   return __ Call(call_descriptor, __ HeapConstant(callable.code()), subject,
    3634         578 :                  search_string, position, __ NoContextConstant());
    3635             : }
    3636             : 
    3637       21117 : Node* EffectControlLinearizer::LowerStringLength(Node* node) {
    3638             :   Node* subject = node->InputAt(0);
    3639             : 
    3640       21117 :   return __ LoadField(AccessBuilder::ForStringLength(), subject);
    3641             : }
    3642             : 
    3643       11352 : Node* EffectControlLinearizer::LowerStringComparison(Callable const& callable,
    3644             :                                                      Node* node) {
    3645             :   Node* lhs = node->InputAt(0);
    3646             :   Node* rhs = node->InputAt(1);
    3647             : 
    3648             :   Operator::Properties properties = Operator::kEliminatable;
    3649             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    3650             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    3651             :       graph()->zone(), callable.descriptor(),
    3652       22704 :       callable.descriptor().GetStackParameterCount(), flags, properties);
    3653             :   return __ Call(call_descriptor, __ HeapConstant(callable.code()), lhs, rhs,
    3654       22704 :                  __ NoContextConstant());
    3655             : }
    3656             : 
    3657        1081 : Node* EffectControlLinearizer::LowerStringSubstring(Node* node) {
    3658             :   Node* receiver = node->InputAt(0);
    3659             :   Node* start = ChangeInt32ToIntPtr(node->InputAt(1));
    3660             :   Node* end = ChangeInt32ToIntPtr(node->InputAt(2));
    3661             : 
    3662             :   Callable callable =
    3663        1081 :       Builtins::CallableFor(isolate(), Builtins::kStringSubstring);
    3664             :   Operator::Properties properties = Operator::kEliminatable;
    3665             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    3666             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    3667             :       graph()->zone(), callable.descriptor(),
    3668        2162 :       callable.descriptor().GetStackParameterCount(), flags, properties);
    3669             :   return __ Call(call_descriptor, __ HeapConstant(callable.code()), receiver,
    3670        2162 :                  start, end, __ NoContextConstant());
    3671             : }
    3672             : 
    3673       10236 : Node* EffectControlLinearizer::LowerStringEqual(Node* node) {
    3674             :   return LowerStringComparison(
    3675       10236 :       Builtins::CallableFor(isolate(), Builtins::kStringEqual), node);
    3676             : }
    3677             : 
    3678         251 : Node* EffectControlLinearizer::LowerStringLessThan(Node* node) {
    3679             :   return LowerStringComparison(
    3680         251 :       Builtins::CallableFor(isolate(), Builtins::kStringLessThan), node);
    3681             : }
    3682             : 
    3683         865 : Node* EffectControlLinearizer::LowerStringLessThanOrEqual(Node* node) {
    3684             :   return LowerStringComparison(
    3685         865 :       Builtins::CallableFor(isolate(), Builtins::kStringLessThanOrEqual), node);
    3686             : }
    3687             : 
    3688         471 : Node* EffectControlLinearizer::LowerCheckFloat64Hole(Node* node,
    3689             :                                                      Node* frame_state) {
    3690             :   // If we reach this point w/o eliminating the {node} that's marked
    3691             :   // with allow-return-hole, we cannot do anything, so just deoptimize
    3692             :   // in case of the hole NaN.
    3693             :   CheckFloat64HoleParameters const& params =
    3694         471 :       CheckFloat64HoleParametersOf(node->op());
    3695             :   Node* value = node->InputAt(0);
    3696             : 
    3697         471 :   auto if_nan = __ MakeDeferredLabel();
    3698         471 :   auto done = __ MakeLabel();
    3699             : 
    3700             :   // First check whether {value} is a NaN at all...
    3701         471 :   __ Branch(__ Float64Equal(value, value), &done, &if_nan);
    3702             : 
    3703             :   __ Bind(&if_nan);
    3704             :   {
    3705             :     // ...and only if {value} is a NaN, perform the expensive bit
    3706             :     // check. See http://crbug.com/v8/8264 for details.
    3707             :     Node* check = __ Word32Equal(__ Float64ExtractHighWord32(value),
    3708         471 :                                  __ Int32Constant(kHoleNanUpper32));
    3709         471 :     __ DeoptimizeIf(DeoptimizeReason::kHole, params.feedback(), check,
    3710         471 :                     frame_state);
    3711             :     __ Goto(&done);
    3712             :   }
    3713             : 
    3714             :   __ Bind(&done);
    3715         471 :   return value;
    3716             : }
    3717             : 
    3718          93 : Node* EffectControlLinearizer::LowerCheckNotTaggedHole(Node* node,
    3719             :                                                        Node* frame_state) {
    3720             :   Node* value = node->InputAt(0);
    3721          93 :   Node* check = __ WordEqual(value, __ TheHoleConstant());
    3722             :   __ DeoptimizeIf(DeoptimizeReason::kHole, VectorSlotPair(), check,
    3723          93 :                   frame_state);
    3724          93 :   return value;
    3725             : }
    3726             : 
    3727        1507 : Node* EffectControlLinearizer::LowerConvertTaggedHoleToUndefined(Node* node) {
    3728             :   Node* value = node->InputAt(0);
    3729             : 
    3730        1507 :   auto if_is_hole = __ MakeDeferredLabel();
    3731        1507 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    3732             : 
    3733        1507 :   Node* check = __ WordEqual(value, __ TheHoleConstant());
    3734        1507 :   __ GotoIf(check, &if_is_hole);
    3735             :   __ Goto(&done, value);
    3736             : 
    3737             :   __ Bind(&if_is_hole);
    3738        1507 :   __ Goto(&done, __ UndefinedConstant());
    3739             : 
    3740             :   __ Bind(&done);
    3741        1507 :   return done.PhiAt(0);
    3742             : }
    3743             : 
    3744          57 : void EffectControlLinearizer::LowerCheckEqualsInternalizedString(
    3745             :     Node* node, Node* frame_state) {
    3746             :   Node* exp = node->InputAt(0);
    3747             :   Node* val = node->InputAt(1);
    3748             : 
    3749          57 :   auto if_same = __ MakeLabel();
    3750          57 :   auto if_notsame = __ MakeDeferredLabel();
    3751          57 :   auto if_thinstring = __ MakeLabel();
    3752          57 :   auto if_notthinstring = __ MakeLabel();
    3753             : 
    3754             :   // Check if {exp} and {val} are the same, which is the likely case.
    3755          57 :   __ Branch(__ WordEqual(exp, val), &if_same, &if_notsame);
    3756             : 
    3757             :   __ Bind(&if_notsame);
    3758             :   {
    3759             :     // Now {val} could still be a non-internalized String that matches {exp}.
    3760             :     __ DeoptimizeIf(DeoptimizeReason::kWrongName, VectorSlotPair(),
    3761          57 :                     ObjectIsSmi(val), frame_state);
    3762          57 :     Node* val_map = __ LoadField(AccessBuilder::ForMap(), val);
    3763             :     Node* val_instance_type =
    3764          57 :         __ LoadField(AccessBuilder::ForMapInstanceType(), val_map);
    3765             : 
    3766             :     // Check for the common case of ThinString first.
    3767             :     __ GotoIf(__ Word32Equal(val_instance_type,
    3768             :                              __ Int32Constant(THIN_ONE_BYTE_STRING_TYPE)),
    3769          57 :               &if_thinstring);
    3770             :     __ Branch(
    3771             :         __ Word32Equal(val_instance_type, __ Int32Constant(THIN_STRING_TYPE)),
    3772          57 :         &if_thinstring, &if_notthinstring);
    3773             : 
    3774             :     __ Bind(&if_notthinstring);
    3775             :     {
    3776             :       // Check that the {val} is a non-internalized String, if it's anything
    3777             :       // else it cannot match the recorded feedback {exp} anyways.
    3778             :       __ DeoptimizeIfNot(
    3779             :           DeoptimizeReason::kWrongName, VectorSlotPair(),
    3780             :           __ Word32Equal(__ Word32And(val_instance_type,
    3781             :                                       __ Int32Constant(kIsNotStringMask |
    3782             :                                                        kIsNotInternalizedMask)),
    3783             :                          __ Int32Constant(kStringTag | kNotInternalizedTag)),
    3784          57 :           frame_state);
    3785             : 
    3786             :       // Try to find the {val} in the string table.
    3787          57 :       MachineSignature::Builder builder(graph()->zone(), 1, 2);
    3788             :       builder.AddReturn(MachineType::AnyTagged());
    3789             :       builder.AddParam(MachineType::Pointer());
    3790             :       builder.AddParam(MachineType::AnyTagged());
    3791             :       Node* try_internalize_string_function = __ ExternalConstant(
    3792          57 :           ExternalReference::try_internalize_string_function());
    3793             :       Node* const isolate_ptr =
    3794          57 :           __ ExternalConstant(ExternalReference::isolate_address(isolate()));
    3795             :       auto call_descriptor =
    3796         114 :           Linkage::GetSimplifiedCDescriptor(graph()->zone(), builder.Build());
    3797             :       Node* val_internalized =
    3798             :           __ Call(common()->Call(call_descriptor),
    3799          57 :                   try_internalize_string_function, isolate_ptr, val);
    3800             : 
    3801             :       // Now see if the results match.
    3802             :       __ DeoptimizeIfNot(DeoptimizeReason::kWrongName, VectorSlotPair(),
    3803          57 :                          __ WordEqual(exp, val_internalized), frame_state);
    3804             :       __ Goto(&if_same);
    3805             :     }
    3806             : 
    3807             :     __ Bind(&if_thinstring);
    3808             :     {
    3809             :       // The {val} is a ThinString, let's check the actual value.
    3810             :       Node* val_actual =
    3811          57 :           __ LoadField(AccessBuilder::ForThinStringActual(), val);
    3812             :       __ DeoptimizeIfNot(DeoptimizeReason::kWrongName, VectorSlotPair(),
    3813          57 :                          __ WordEqual(exp, val_actual), frame_state);
    3814             :       __ Goto(&if_same);
    3815             :     }
    3816             :   }
    3817             : 
    3818             :   __ Bind(&if_same);
    3819          57 : }
    3820             : 
    3821          19 : void EffectControlLinearizer::LowerCheckEqualsSymbol(Node* node,
    3822             :                                                      Node* frame_state) {
    3823             :   Node* exp = node->InputAt(0);
    3824             :   Node* val = node->InputAt(1);
    3825          19 :   Node* check = __ WordEqual(exp, val);
    3826             :   __ DeoptimizeIfNot(DeoptimizeReason::kWrongName, VectorSlotPair(), check,
    3827          19 :                      frame_state);
    3828          19 : }
    3829             : 
    3830       54995 : Node* EffectControlLinearizer::AllocateHeapNumberWithValue(Node* value) {
    3831       54995 :   Node* result = __ Allocate(NOT_TENURED, __ Int32Constant(HeapNumber::kSize));
    3832       54996 :   __ StoreField(AccessBuilder::ForMap(), result, __ HeapNumberMapConstant());
    3833       54996 :   __ StoreField(AccessBuilder::ForHeapNumberValue(), result, value);
    3834       54996 :   return result;
    3835             : }
    3836             : 
    3837      135708 : Node* EffectControlLinearizer::ChangeIntPtrToSmi(Node* value) {
    3838             :   // Do shift on 32bit values if Smis are stored in the lower word.
    3839             :   if (machine()->Is64() && SmiValuesAre31Bits()) {
    3840             :     return __ ChangeInt32ToInt64(
    3841             :         __ Word32Shl(__ TruncateInt64ToInt32(value), SmiShiftBitsConstant()));
    3842             :   }
    3843      135708 :   return __ WordShl(value, SmiShiftBitsConstant());
    3844             : }
    3845             : 
    3846           0 : Node* EffectControlLinearizer::ChangeInt32ToIntPtr(Node* value) {
    3847      133406 :   if (machine()->Is64()) {
    3848      133406 :     value = __ ChangeInt32ToInt64(value);
    3849             :   }
    3850           0 :   return value;
    3851             : }
    3852             : 
    3853           0 : Node* EffectControlLinearizer::ChangeIntPtrToInt32(Node* value) {
    3854           0 :   if (machine()->Is64()) {
    3855           0 :     value = __ TruncateInt64ToInt32(value);
    3856             :   }
    3857           0 :   return value;
    3858             : }
    3859             : 
    3860      131244 : Node* EffectControlLinearizer::ChangeInt32ToSmi(Node* value) {
    3861             :   // Do shift on 32bit values if Smis are stored in the lower word.
    3862             :   if (machine()->Is64() && SmiValuesAre31Bits()) {
    3863             :     return __ ChangeInt32ToInt64(__ Word32Shl(value, SmiShiftBitsConstant()));
    3864             :   }
    3865      131245 :   return ChangeIntPtrToSmi(ChangeInt32ToIntPtr(value));
    3866             : }
    3867             : 
    3868           0 : Node* EffectControlLinearizer::ChangeInt64ToSmi(Node* value) {
    3869             :   DCHECK(machine()->Is64());
    3870        2066 :   return ChangeIntPtrToSmi(value);
    3871             : }
    3872             : 
    3873           0 : Node* EffectControlLinearizer::ChangeUint32ToUintPtr(Node* value) {
    3874        1106 :   if (machine()->Is64()) {
    3875        1106 :     value = __ ChangeUint32ToUint64(value);
    3876             :   }
    3877           0 :   return value;
    3878             : }
    3879             : 
    3880         556 : Node* EffectControlLinearizer::ChangeUint32ToSmi(Node* value) {
    3881             :   // Do shift on 32bit values if Smis are stored in the lower word.
    3882             :   if (machine()->Is64() && SmiValuesAre31Bits()) {
    3883             :     return __ ChangeUint32ToUint64(__ Word32Shl(value, SmiShiftBitsConstant()));
    3884             :   } else {
    3885         556 :     return __ WordShl(ChangeUint32ToUintPtr(value), SmiShiftBitsConstant());
    3886             :   }
    3887             : }
    3888             : 
    3889      160513 : Node* EffectControlLinearizer::ChangeSmiToIntPtr(Node* value) {
    3890             :   // Do shift on 32bit values if Smis are stored in the lower word.
    3891             :   if (machine()->Is64() && SmiValuesAre31Bits()) {
    3892             :     return __ ChangeInt32ToInt64(
    3893             :         __ Word32Sar(__ TruncateInt64ToInt32(value), SmiShiftBitsConstant()));
    3894             :   }
    3895      160514 :   return __ WordSar(value, SmiShiftBitsConstant());
    3896             : }
    3897             : 
    3898      156095 : Node* EffectControlLinearizer::ChangeSmiToInt32(Node* value) {
    3899             :   // Do shift on 32bit values if Smis are stored in the lower word.
    3900             :   if (machine()->Is64() && SmiValuesAre31Bits()) {
    3901             :     return __ Word32Sar(__ TruncateInt64ToInt32(value), SmiShiftBitsConstant());
    3902             :   }
    3903      156095 :   if (machine()->Is64()) {
    3904      156095 :     return __ TruncateInt64ToInt32(ChangeSmiToIntPtr(value));
    3905             :   }
    3906           0 :   return ChangeSmiToIntPtr(value);
    3907             : }
    3908             : 
    3909        1975 : Node* EffectControlLinearizer::ChangeSmiToInt64(Node* value) {
    3910        1975 :   CHECK(machine()->Is64());
    3911        1975 :   return ChangeSmiToIntPtr(value);
    3912             : }
    3913             : 
    3914      257516 : Node* EffectControlLinearizer::ObjectIsSmi(Node* value) {
    3915             :   return __ WordEqual(__ WordAnd(value, __ IntPtrConstant(kSmiTagMask)),
    3916      257516 :                       __ IntPtrConstant(kSmiTag));
    3917             : }
    3918             : 
    3919           0 : Node* EffectControlLinearizer::SmiMaxValueConstant() {
    3920         556 :   return __ Int32Constant(Smi::kMaxValue);
    3921             : }
    3922             : 
    3923           0 : Node* EffectControlLinearizer::SmiShiftBitsConstant() {
    3924             :   if (machine()->Is64() && SmiValuesAre31Bits()) {
    3925             :     return __ Int32Constant(kSmiShiftSize + kSmiTagSize);
    3926             :   }
    3927      296777 :   return __ IntPtrConstant(kSmiShiftSize + kSmiTagSize);
    3928             : }
    3929             : 
    3930          23 : Node* EffectControlLinearizer::LowerPlainPrimitiveToNumber(Node* node) {
    3931             :   Node* value = node->InputAt(0);
    3932          23 :   return __ ToNumber(value);
    3933             : }
    3934             : 
    3935           9 : Node* EffectControlLinearizer::LowerPlainPrimitiveToWord32(Node* node) {
    3936             :   Node* value = node->InputAt(0);
    3937             : 
    3938           9 :   auto if_not_smi = __ MakeDeferredLabel();
    3939           9 :   auto if_to_number_smi = __ MakeLabel();
    3940           9 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    3941             : 
    3942           9 :   Node* check0 = ObjectIsSmi(value);
    3943           9 :   __ GotoIfNot(check0, &if_not_smi);
    3944           9 :   __ Goto(&done, ChangeSmiToInt32(value));
    3945             : 
    3946             :   __ Bind(&if_not_smi);
    3947           9 :   Node* to_number = __ ToNumber(value);
    3948             : 
    3949           9 :   Node* check1 = ObjectIsSmi(to_number);
    3950           9 :   __ GotoIf(check1, &if_to_number_smi);
    3951           9 :   Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), to_number);
    3952           9 :   __ Goto(&done, __ TruncateFloat64ToWord32(number));
    3953             : 
    3954             :   __ Bind(&if_to_number_smi);
    3955           9 :   __ Goto(&done, ChangeSmiToInt32(to_number));
    3956             : 
    3957             :   __ Bind(&done);
    3958           9 :   return done.PhiAt(0);
    3959             : }
    3960             : 
    3961           0 : Node* EffectControlLinearizer::LowerPlainPrimitiveToFloat64(Node* node) {
    3962             :   Node* value = node->InputAt(0);
    3963             : 
    3964           0 :   auto if_not_smi = __ MakeDeferredLabel();
    3965           0 :   auto if_to_number_smi = __ MakeLabel();
    3966           0 :   auto done = __ MakeLabel(MachineRepresentation::kFloat64);
    3967             : 
    3968           0 :   Node* check0 = ObjectIsSmi(value);
    3969           0 :   __ GotoIfNot(check0, &if_not_smi);
    3970           0 :   Node* from_smi = ChangeSmiToInt32(value);
    3971           0 :   __ Goto(&done, __ ChangeInt32ToFloat64(from_smi));
    3972             : 
    3973             :   __ Bind(&if_not_smi);
    3974           0 :   Node* to_number = __ ToNumber(value);
    3975           0 :   Node* check1 = ObjectIsSmi(to_number);
    3976           0 :   __ GotoIf(check1, &if_to_number_smi);
    3977             : 
    3978           0 :   Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), to_number);
    3979             :   __ Goto(&done, number);
    3980             : 
    3981             :   __ Bind(&if_to_number_smi);
    3982           0 :   Node* number_from_smi = ChangeSmiToInt32(to_number);
    3983           0 :   number_from_smi = __ ChangeInt32ToFloat64(number_from_smi);
    3984             :   __ Goto(&done, number_from_smi);
    3985             : 
    3986             :   __ Bind(&done);
    3987           0 :   return done.PhiAt(0);
    3988             : }
    3989             : 
    3990        1746 : Node* EffectControlLinearizer::LowerEnsureWritableFastElements(Node* node) {
    3991             :   Node* object = node->InputAt(0);
    3992             :   Node* elements = node->InputAt(1);
    3993             : 
    3994        1746 :   auto if_not_fixed_array = __ MakeDeferredLabel();
    3995        1746 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    3996             : 
    3997             :   // Load the current map of {elements}.
    3998        1746 :   Node* elements_map = __ LoadField(AccessBuilder::ForMap(), elements);
    3999             : 
    4000             :   // Check if {elements} is not a copy-on-write FixedArray.
    4001        1746 :   Node* check = __ WordEqual(elements_map, __ FixedArrayMapConstant());
    4002        1746 :   __ GotoIfNot(check, &if_not_fixed_array);
    4003             :   // Nothing to do if the {elements} are not copy-on-write.
    4004             :   __ Goto(&done, elements);
    4005             : 
    4006             :   __ Bind(&if_not_fixed_array);
    4007             :   // We need to take a copy of the {elements} and set them up for {object}.
    4008             :   Operator::Properties properties = Operator::kEliminatable;
    4009             :   Callable callable =
    4010        1746 :       Builtins::CallableFor(isolate(), Builtins::kCopyFastSmiOrObjectElements);
    4011             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    4012             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    4013             :       graph()->zone(), callable.descriptor(),
    4014        3492 :       callable.descriptor().GetStackParameterCount(), flags, properties);
    4015             :   Node* result = __ Call(call_descriptor, __ HeapConstant(callable.code()),
    4016        3492 :                          object, __ NoContextConstant());
    4017             :   __ Goto(&done, result);
    4018             : 
    4019             :   __ Bind(&done);
    4020        1746 :   return done.PhiAt(0);
    4021             : }
    4022             : 
    4023        3665 : Node* EffectControlLinearizer::LowerMaybeGrowFastElements(Node* node,
    4024             :                                                           Node* frame_state) {
    4025        3665 :   GrowFastElementsParameters params = GrowFastElementsParametersOf(node->op());
    4026             :   Node* object = node->InputAt(0);
    4027             :   Node* elements = node->InputAt(1);
    4028             :   Node* index = node->InputAt(2);
    4029             :   Node* elements_length = node->InputAt(3);
    4030             : 
    4031        3665 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    4032        3665 :   auto if_grow = __ MakeDeferredLabel();
    4033             :   auto if_not_grow = __ MakeLabel();
    4034             : 
    4035             :   // Check if we need to grow the {elements} backing store.
    4036        3665 :   Node* check = __ Uint32LessThan(index, elements_length);
    4037        3665 :   __ GotoIfNot(check, &if_grow);
    4038             :   __ Goto(&done, elements);
    4039             : 
    4040             :   __ Bind(&if_grow);
    4041             :   // We need to grow the {elements} for {object}.
    4042             :   Operator::Properties properties = Operator::kEliminatable;
    4043             :   Callable callable =
    4044        3665 :       (params.mode() == GrowFastElementsMode::kDoubleElements)
    4045             :           ? Builtins::CallableFor(isolate(), Builtins::kGrowFastDoubleElements)
    4046             :           : Builtins::CallableFor(isolate(),
    4047        7330 :                                   Builtins::kGrowFastSmiOrObjectElements);
    4048             :   CallDescriptor::Flags call_flags = CallDescriptor::kNoFlags;
    4049             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    4050             :       graph()->zone(), callable.descriptor(),
    4051        7330 :       callable.descriptor().GetStackParameterCount(), call_flags, properties);
    4052             :   Node* new_elements =
    4053             :       __ Call(call_descriptor, __ HeapConstant(callable.code()), object,
    4054        7330 :               ChangeInt32ToSmi(index), __ NoContextConstant());
    4055             : 
    4056             :   // Ensure that we were able to grow the {elements}.
    4057             :   __ DeoptimizeIf(DeoptimizeReason::kCouldNotGrowElements, params.feedback(),
    4058        3665 :                   ObjectIsSmi(new_elements), frame_state);
    4059             :   __ Goto(&done, new_elements);
    4060             : 
    4061             :   __ Bind(&done);
    4062        3665 :   return done.PhiAt(0);
    4063             : }
    4064             : 
    4065         592 : void EffectControlLinearizer::LowerTransitionElementsKind(Node* node) {
    4066         592 :   ElementsTransition const transition = ElementsTransitionOf(node->op());
    4067             :   Node* object = node->InputAt(0);
    4068             : 
    4069         592 :   auto if_map_same = __ MakeDeferredLabel();
    4070         592 :   auto done = __ MakeLabel();
    4071             : 
    4072         592 :   Node* source_map = __ HeapConstant(transition.source());
    4073         592 :   Node* target_map = __ HeapConstant(transition.target());
    4074             : 
    4075             :   // Load the current map of {object}.
    4076         592 :   Node* object_map = __ LoadField(AccessBuilder::ForMap(), object);
    4077             : 
    4078             :   // Check if {object_map} is the same as {source_map}.
    4079         592 :   Node* check = __ WordEqual(object_map, source_map);
    4080         592 :   __ GotoIf(check, &if_map_same);
    4081             :   __ Goto(&done);
    4082             : 
    4083             :   __ Bind(&if_map_same);
    4084         592 :   switch (transition.mode()) {
    4085             :     case ElementsTransition::kFastTransition:
    4086             :       // In-place migration of {object}, just store the {target_map}.
    4087         214 :       __ StoreField(AccessBuilder::ForMap(), object, target_map);
    4088         214 :       break;
    4089             :     case ElementsTransition::kSlowTransition: {
    4090             :       // Instance migration, call out to the runtime for {object}.
    4091         378 :       Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
    4092             :       Runtime::FunctionId id = Runtime::kTransitionElementsKind;
    4093             :       auto call_descriptor = Linkage::GetRuntimeCallDescriptor(
    4094         378 :           graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags);
    4095             :       __ Call(call_descriptor, __ CEntryStubConstant(1), object, target_map,
    4096             :               __ ExternalConstant(ExternalReference::Create(id)),
    4097         378 :               __ Int32Constant(2), __ NoContextConstant());
    4098             :       break;
    4099             :     }
    4100             :   }
    4101             :   __ Goto(&done);
    4102             : 
    4103             :   __ Bind(&done);
    4104         592 : }
    4105             : 
    4106        1036 : Node* EffectControlLinearizer::LowerLoadFieldByIndex(Node* node) {
    4107             :   Node* object = node->InputAt(0);
    4108             :   Node* index = node->InputAt(1);
    4109        1036 :   Node* zero = __ IntPtrConstant(0);
    4110        1036 :   Node* one = __ IntPtrConstant(1);
    4111             : 
    4112             :   // Sign-extend the {index} on 64-bit architectures.
    4113        1036 :   if (machine()->Is64()) {
    4114        1036 :     index = __ ChangeInt32ToInt64(index);
    4115             :   }
    4116             : 
    4117        1036 :   auto if_double = __ MakeDeferredLabel();
    4118        1036 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    4119             : 
    4120             :   // Check if field is a mutable double field.
    4121        1036 :   __ GotoIfNot(__ WordEqual(__ WordAnd(index, one), zero), &if_double);
    4122             : 
    4123             :   // The field is a proper Tagged field on {object}. The {index} is shifted
    4124             :   // to the left by one in the code below.
    4125             :   {
    4126             :     // Check if field is in-object or out-of-object.
    4127        1036 :     auto if_outofobject = __ MakeLabel();
    4128        1036 :     __ GotoIf(__ IntLessThan(index, zero), &if_outofobject);
    4129             : 
    4130             :     // The field is located in the {object} itself.
    4131             :     {
    4132             :       Node* offset =
    4133             :           __ IntAdd(__ WordShl(index, __ IntPtrConstant(kTaggedSizeLog2 - 1)),
    4134        1036 :                     __ IntPtrConstant(JSObject::kHeaderSize - kHeapObjectTag));
    4135        1036 :       Node* result = __ Load(MachineType::AnyTagged(), object, offset);
    4136             :       __ Goto(&done, result);
    4137             :     }
    4138             : 
    4139             :     // The field is located in the properties backing store of {object}.
    4140             :     // The {index} is equal to the negated out of property index plus 1.
    4141             :     __ Bind(&if_outofobject);
    4142             :     {
    4143             :       Node* properties =
    4144        1036 :           __ LoadField(AccessBuilder::ForJSObjectPropertiesOrHash(), object);
    4145             :       Node* offset =
    4146             :           __ IntAdd(__ WordShl(__ IntSub(zero, index),
    4147             :                                __ IntPtrConstant(kTaggedSizeLog2 - 1)),
    4148             :                     __ IntPtrConstant((FixedArray::kHeaderSize - kTaggedSize) -
    4149        1036 :                                       kHeapObjectTag));
    4150        1036 :       Node* result = __ Load(MachineType::AnyTagged(), properties, offset);
    4151             :       __ Goto(&done, result);
    4152             :     }
    4153             :   }
    4154             : 
    4155             :   // The field is a Double field, either unboxed in the object on 64-bit
    4156             :   // architectures, or as MutableHeapNumber.
    4157             :   __ Bind(&if_double);
    4158             :   {
    4159        1036 :     auto done_double = __ MakeLabel(MachineRepresentation::kFloat64);
    4160             : 
    4161        1036 :     index = __ WordSar(index, one);
    4162             : 
    4163             :     // Check if field is in-object or out-of-object.
    4164        1036 :     auto if_outofobject = __ MakeLabel();
    4165        1036 :     __ GotoIf(__ IntLessThan(index, zero), &if_outofobject);
    4166             : 
    4167             :     // The field is located in the {object} itself.
    4168             :     {
    4169             :       Node* offset =
    4170             :           __ IntAdd(__ WordShl(index, __ IntPtrConstant(kTaggedSizeLog2)),
    4171        1036 :                     __ IntPtrConstant(JSObject::kHeaderSize - kHeapObjectTag));
    4172             :       if (FLAG_unbox_double_fields) {
    4173        1036 :         Node* result = __ Load(MachineType::Float64(), object, offset);
    4174             :         __ Goto(&done_double, result);
    4175             :       } else {
    4176             :         Node* result = __ Load(MachineType::AnyTagged(), object, offset);
    4177             :         result = __ LoadField(AccessBuilder::ForHeapNumberValue(), result);
    4178             :         __ Goto(&done_double, result);
    4179             :       }
    4180             :     }
    4181             : 
    4182             :     __ Bind(&if_outofobject);
    4183             :     {
    4184             :       Node* properties =
    4185        1036 :           __ LoadField(AccessBuilder::ForJSObjectPropertiesOrHash(), object);
    4186             :       Node* offset =
    4187             :           __ IntAdd(__ WordShl(__ IntSub(zero, index),
    4188             :                                __ IntPtrConstant(kTaggedSizeLog2)),
    4189             :                     __ IntPtrConstant((FixedArray::kHeaderSize - kTaggedSize) -
    4190        1036 :                                       kHeapObjectTag));
    4191        1036 :       Node* result = __ Load(MachineType::AnyTagged(), properties, offset);
    4192        1036 :       result = __ LoadField(AccessBuilder::ForHeapNumberValue(), result);
    4193             :       __ Goto(&done_double, result);
    4194             :     }
    4195             : 
    4196             :     __ Bind(&done_double);
    4197             :     {
    4198        1036 :       Node* result = AllocateHeapNumberWithValue(done_double.PhiAt(0));
    4199             :       __ Goto(&done, result);
    4200             :     }
    4201             :   }
    4202             : 
    4203             :   __ Bind(&done);
    4204        1036 :   return done.PhiAt(0);
    4205             : }
    4206             : 
    4207         465 : Node* EffectControlLinearizer::BuildReverseBytes(ExternalArrayType type,
    4208             :                                                  Node* value) {
    4209         465 :   switch (type) {
    4210             :     case kExternalInt8Array:
    4211             :     case kExternalUint8Array:
    4212             :     case kExternalUint8ClampedArray:
    4213             :       return value;
    4214             : 
    4215             :     case kExternalInt16Array: {
    4216          55 :       Node* result = __ Word32ReverseBytes(value);
    4217          55 :       result = __ Word32Sar(result, __ Int32Constant(16));
    4218          55 :       return result;
    4219             :     }
    4220             : 
    4221             :     case kExternalUint16Array: {
    4222          55 :       Node* result = __ Word32ReverseBytes(value);
    4223          55 :       result = __ Word32Shr(result, __ Int32Constant(16));
    4224          55 :       return result;
    4225             :     }
    4226             : 
    4227             :     case kExternalInt32Array:  // Fall through.
    4228             :     case kExternalUint32Array:
    4229          96 :       return __ Word32ReverseBytes(value);
    4230             : 
    4231             :     case kExternalFloat32Array: {
    4232          55 :       Node* result = __ BitcastFloat32ToInt32(value);
    4233          55 :       result = __ Word32ReverseBytes(result);
    4234          55 :       result = __ BitcastInt32ToFloat32(result);
    4235          55 :       return result;
    4236             :     }
    4237             : 
    4238             :     case kExternalFloat64Array: {
    4239          55 :       if (machine()->Is64()) {
    4240          55 :         Node* result = __ BitcastFloat64ToInt64(value);
    4241          55 :         result = __ Word64ReverseBytes(result);
    4242          55 :         result = __ BitcastInt64ToFloat64(result);
    4243          55 :         return result;
    4244             :       } else {
    4245           0 :         Node* lo = __ Word32ReverseBytes(__ Float64ExtractLowWord32(value));
    4246           0 :         Node* hi = __ Word32ReverseBytes(__ Float64ExtractHighWord32(value));
    4247           0 :         Node* result = __ Float64Constant(0.0);
    4248           0 :         result = __ Float64InsertLowWord32(result, hi);
    4249           0 :         result = __ Float64InsertHighWord32(result, lo);
    4250           0 :         return result;
    4251             :       }
    4252             :     }
    4253             : 
    4254             :     case kExternalBigInt64Array:
    4255             :     case kExternalBigUint64Array:
    4256           0 :       UNREACHABLE();
    4257             :   }
    4258           0 : }
    4259             : 
    4260         268 : Node* EffectControlLinearizer::LowerLoadDataViewElement(Node* node) {
    4261         268 :   ExternalArrayType element_type = ExternalArrayTypeOf(node->op());
    4262             :   Node* buffer = node->InputAt(0);
    4263             :   Node* storage = node->InputAt(1);
    4264             :   Node* byte_offset = node->InputAt(2);
    4265             :   Node* index = node->InputAt(3);
    4266             :   Node* is_little_endian = node->InputAt(4);
    4267             : 
    4268             :   // We need to keep the {buffer} alive so that the GC will not release the
    4269             :   // ArrayBuffer (if there's any) as long as we are still operating on it.
    4270         268 :   __ Retain(buffer);
    4271             : 
    4272             :   // Compute the effective offset.
    4273         268 :   Node* offset = __ IntAdd(byte_offset, index);
    4274             : 
    4275             :   MachineType const machine_type =
    4276         268 :       AccessBuilder::ForTypedArrayElement(element_type, true).machine_type;
    4277             : 
    4278         268 :   Node* value = __ LoadUnaligned(machine_type, storage, offset);
    4279         268 :   auto big_endian = __ MakeLabel();
    4280         268 :   auto done = __ MakeLabel(machine_type.representation());
    4281             : 
    4282         268 :   __ GotoIfNot(is_little_endian, &big_endian);
    4283             :   {  // Little-endian load.
    4284             : #if V8_TARGET_LITTLE_ENDIAN
    4285             :     __ Goto(&done, value);
    4286             : #else
    4287             :     __ Goto(&done, BuildReverseBytes(element_type, value));
    4288             : #endif  // V8_TARGET_LITTLE_ENDIAN
    4289             :   }
    4290             : 
    4291             :   __ Bind(&big_endian);
    4292             :   {  // Big-endian load.
    4293             : #if V8_TARGET_LITTLE_ENDIAN
    4294         268 :     __ Goto(&done, BuildReverseBytes(element_type, value));
    4295             : #else
    4296             :     __ Goto(&done, value);
    4297             : #endif  // V8_TARGET_LITTLE_ENDIAN
    4298             :   }
    4299             : 
    4300             :   // We're done, return {result}.
    4301             :   __ Bind(&done);
    4302         268 :   return done.PhiAt(0);
    4303             : }
    4304             : 
    4305         197 : void EffectControlLinearizer::LowerStoreDataViewElement(Node* node) {
    4306         197 :   ExternalArrayType element_type = ExternalArrayTypeOf(node->op());
    4307             :   Node* buffer = node->InputAt(0);
    4308             :   Node* storage = node->InputAt(1);
    4309             :   Node* byte_offset = node->InputAt(2);
    4310             :   Node* index = node->InputAt(3);
    4311             :   Node* value = node->InputAt(4);
    4312             :   Node* is_little_endian = node->InputAt(5);
    4313             : 
    4314             :   // We need to keep the {buffer} alive so that the GC will not release the
    4315             :   // ArrayBuffer (if there's any) as long as we are still operating on it.
    4316         197 :   __ Retain(buffer);
    4317             : 
    4318             :   // Compute the effective offset.
    4319         197 :   Node* offset = __ IntAdd(byte_offset, index);
    4320             : 
    4321             :   MachineType const machine_type =
    4322         197 :       AccessBuilder::ForTypedArrayElement(element_type, true).machine_type;
    4323             : 
    4324         197 :   auto big_endian = __ MakeLabel();
    4325         197 :   auto done = __ MakeLabel(machine_type.representation());
    4326             : 
    4327         197 :   __ GotoIfNot(is_little_endian, &big_endian);
    4328             :   {  // Little-endian store.
    4329             : #if V8_TARGET_LITTLE_ENDIAN
    4330             :     __ Goto(&done, value);
    4331             : #else
    4332             :     __ Goto(&done, BuildReverseBytes(element_type, value));
    4333             : #endif  // V8_TARGET_LITTLE_ENDIAN
    4334             :   }
    4335             : 
    4336             :   __ Bind(&big_endian);
    4337             :   {  // Big-endian store.
    4338             : #if V8_TARGET_LITTLE_ENDIAN
    4339         197 :     __ Goto(&done, BuildReverseBytes(element_type, value));
    4340             : #else
    4341             :     __ Goto(&done, value);
    4342             : #endif  // V8_TARGET_LITTLE_ENDIAN
    4343             :   }
    4344             : 
    4345             :   __ Bind(&done);
    4346             :   __ StoreUnaligned(machine_type.representation(), storage, offset,
    4347         197 :                     done.PhiAt(0));
    4348         197 : }
    4349             : 
    4350        4594 : Node* EffectControlLinearizer::LowerLoadTypedElement(Node* node) {
    4351        4594 :   ExternalArrayType array_type = ExternalArrayTypeOf(node->op());
    4352             :   Node* buffer = node->InputAt(0);
    4353             :   Node* base = node->InputAt(1);
    4354             :   Node* external = node->InputAt(2);
    4355             :   Node* index = node->InputAt(3);
    4356             : 
    4357             :   // We need to keep the {buffer} alive so that the GC will not release the
    4358             :   // ArrayBuffer (if there's any) as long as we are still operating on it.
    4359        4594 :   __ Retain(buffer);
    4360             : 
    4361             :   // Compute the effective storage pointer, handling the case where the
    4362             :   // {external} pointer is the effective storage pointer (i.e. the {base}
    4363             :   // is Smi zero).
    4364             :   Node* storage = IntPtrMatcher(base).Is(0)
    4365             :                       ? external
    4366        4594 :                       : __ UnsafePointerAdd(base, external);
    4367             : 
    4368             :   // Perform the actual typed element access.
    4369             :   return __ LoadElement(AccessBuilder::ForTypedArrayElement(
    4370             :                             array_type, true, LoadSensitivity::kCritical),
    4371        4594 :                         storage, index);
    4372             : }
    4373             : 
    4374        4162 : void EffectControlLinearizer::LowerStoreTypedElement(Node* node) {
    4375        4162 :   ExternalArrayType array_type = ExternalArrayTypeOf(node->op());
    4376             :   Node* buffer = node->InputAt(0);
    4377             :   Node* base = node->InputAt(1);
    4378             :   Node* external = node->InputAt(2);
    4379             :   Node* index = node->InputAt(3);
    4380             :   Node* value = node->InputAt(4);
    4381             : 
    4382             :   // We need to keep the {buffer} alive so that the GC will not release the
    4383             :   // ArrayBuffer (if there's any) as long as we are still operating on it.
    4384        4162 :   __ Retain(buffer);
    4385             : 
    4386             :   // Compute the effective storage pointer, handling the case where the
    4387             :   // {external} pointer is the effective storage pointer (i.e. the {base}
    4388             :   // is Smi zero).
    4389             :   Node* storage = IntPtrMatcher(base).Is(0)
    4390             :                       ? external
    4391        4162 :                       : __ UnsafePointerAdd(base, external);
    4392             : 
    4393             :   // Perform the actual typed element access.
    4394             :   __ StoreElement(AccessBuilder::ForTypedArrayElement(array_type, true),
    4395        4162 :                   storage, index, value);
    4396        4162 : }
    4397             : 
    4398         614 : void EffectControlLinearizer::TransitionElementsTo(Node* node, Node* array,
    4399             :                                                    ElementsKind from,
    4400             :                                                    ElementsKind to) {
    4401             :   DCHECK(IsMoreGeneralElementsKindTransition(from, to));
    4402             :   DCHECK(to == HOLEY_ELEMENTS || to == HOLEY_DOUBLE_ELEMENTS);
    4403             : 
    4404             :   Handle<Map> target(to == HOLEY_ELEMENTS ? FastMapParameterOf(node->op())
    4405         614 :                                           : DoubleMapParameterOf(node->op()));
    4406         307 :   Node* target_map = __ HeapConstant(target);
    4407             : 
    4408         307 :   if (IsSimpleMapChangeTransition(from, to)) {
    4409         102 :     __ StoreField(AccessBuilder::ForMap(), array, target_map);
    4410             :   } else {
    4411             :     // Instance migration, call out to the runtime for {array}.
    4412         205 :     Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
    4413             :     Runtime::FunctionId id = Runtime::kTransitionElementsKind;
    4414             :     auto call_descriptor = Linkage::GetRuntimeCallDescriptor(
    4415         205 :         graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags);
    4416             :     __ Call(call_descriptor, __ CEntryStubConstant(1), array, target_map,
    4417             :             __ ExternalConstant(ExternalReference::Create(id)),
    4418         205 :             __ Int32Constant(2), __ NoContextConstant());
    4419             :   }
    4420         307 : }
    4421             : 
    4422         385 : Node* EffectControlLinearizer::IsElementsKindGreaterThan(
    4423             :     Node* kind, ElementsKind reference_kind) {
    4424         385 :   Node* ref_kind = __ Int32Constant(reference_kind);
    4425         385 :   Node* ret = __ Int32LessThan(ref_kind, kind);
    4426         385 :   return ret;
    4427             : }
    4428             : 
    4429          81 : void EffectControlLinearizer::LowerTransitionAndStoreElement(Node* node) {
    4430             :   Node* array = node->InputAt(0);
    4431             :   Node* index = node->InputAt(1);
    4432             :   Node* value = node->InputAt(2);
    4433             : 
    4434             :   // Possibly transition array based on input and store.
    4435             :   //
    4436             :   //   -- TRANSITION PHASE -----------------
    4437             :   //   kind = ElementsKind(array)
    4438             :   //   if value is not smi {
    4439             :   //     if kind == HOLEY_SMI_ELEMENTS {
    4440             :   //       if value is heap number {
    4441             :   //         Transition array to HOLEY_DOUBLE_ELEMENTS
    4442             :   //         kind = HOLEY_DOUBLE_ELEMENTS
    4443             :   //       } else {
    4444             :   //         Transition array to HOLEY_ELEMENTS
    4445             :   //         kind = HOLEY_ELEMENTS
    4446             :   //       }
    4447             :   //     } else if kind == HOLEY_DOUBLE_ELEMENTS {
    4448             :   //       if value is not heap number {
    4449             :   //         Transition array to HOLEY_ELEMENTS
    4450             :   //         kind = HOLEY_ELEMENTS
    4451             :   //       }
    4452             :   //     }
    4453             :   //   }
    4454             :   //
    4455             :   //   -- STORE PHASE ----------------------
    4456             :   //   [make sure {kind} is up-to-date]
    4457             :   //   if kind == HOLEY_DOUBLE_ELEMENTS {
    4458             :   //     if value is smi {
    4459             :   //       float_value = convert smi to float
    4460             :   //       Store array[index] = float_value
    4461             :   //     } else {
    4462             :   //       float_value = value
    4463             :   //       Store array[index] = float_value
    4464             :   //     }
    4465             :   //   } else {
    4466             :   //     // kind is HOLEY_SMI_ELEMENTS or HOLEY_ELEMENTS
    4467             :   //     Store array[index] = value
    4468             :   //   }
    4469             :   //
    4470          81 :   Node* map = __ LoadField(AccessBuilder::ForMap(), array);
    4471             :   Node* kind;
    4472             :   {
    4473          81 :     Node* bit_field2 = __ LoadField(AccessBuilder::ForMapBitField2(), map);
    4474          81 :     Node* mask = __ Int32Constant(Map::ElementsKindBits::kMask);
    4475          81 :     Node* andit = __ Word32And(bit_field2, mask);
    4476          81 :     Node* shift = __ Int32Constant(Map::ElementsKindBits::kShift);
    4477          81 :     kind = __ Word32Shr(andit, shift);
    4478             :   }
    4479             : 
    4480          81 :   auto do_store = __ MakeLabel(MachineRepresentation::kWord32);
    4481             :   // We can store a smi anywhere.
    4482          81 :   __ GotoIf(ObjectIsSmi(value), &do_store, kind);
    4483             : 
    4484             :   // {value} is a HeapObject.
    4485          81 :   auto transition_smi_array = __ MakeDeferredLabel();
    4486          81 :   auto transition_double_to_fast = __ MakeDeferredLabel();
    4487             :   {
    4488             :     __ GotoIfNot(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS),
    4489          81 :                  &transition_smi_array);
    4490             :     __ GotoIfNot(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS), &do_store,
    4491          81 :                  kind);
    4492             : 
    4493             :     // We have double elements kind. Only a HeapNumber can be stored
    4494             :     // without effecting a transition.
    4495          81 :     Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    4496          81 :     Node* heap_number_map = __ HeapNumberMapConstant();
    4497          81 :     Node* check = __ WordEqual(value_map, heap_number_map);
    4498          81 :     __ GotoIfNot(check, &transition_double_to_fast);
    4499             :     __ Goto(&do_store, kind);
    4500             :   }
    4501             : 
    4502             :   __ Bind(&transition_smi_array);  // deferred code.
    4503             :   {
    4504             :     // Transition {array} from HOLEY_SMI_ELEMENTS to HOLEY_DOUBLE_ELEMENTS or
    4505             :     // to HOLEY_ELEMENTS.
    4506          81 :     auto if_value_not_heap_number = __ MakeLabel();
    4507          81 :     Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    4508          81 :     Node* heap_number_map = __ HeapNumberMapConstant();
    4509          81 :     Node* check = __ WordEqual(value_map, heap_number_map);
    4510          81 :     __ GotoIfNot(check, &if_value_not_heap_number);
    4511             :     {
    4512             :       // {value} is a HeapNumber.
    4513             :       TransitionElementsTo(node, array, HOLEY_SMI_ELEMENTS,
    4514          81 :                            HOLEY_DOUBLE_ELEMENTS);
    4515          81 :       __ Goto(&do_store, __ Int32Constant(HOLEY_DOUBLE_ELEMENTS));
    4516             :     }
    4517             :     __ Bind(&if_value_not_heap_number);
    4518             :     {
    4519          81 :       TransitionElementsTo(node, array, HOLEY_SMI_ELEMENTS, HOLEY_ELEMENTS);
    4520          81 :       __ Goto(&do_store, __ Int32Constant(HOLEY_ELEMENTS));
    4521             :     }
    4522             :   }
    4523             : 
    4524             :   __ Bind(&transition_double_to_fast);  // deferred code.
    4525             :   {
    4526          81 :     TransitionElementsTo(node, array, HOLEY_DOUBLE_ELEMENTS, HOLEY_ELEMENTS);
    4527          81 :     __ Goto(&do_store, __ Int32Constant(HOLEY_ELEMENTS));
    4528             :   }
    4529             : 
    4530             :   // Make sure kind is up-to-date.
    4531             :   __ Bind(&do_store);
    4532             :   kind = do_store.PhiAt(0);
    4533             : 
    4534          81 :   Node* elements = __ LoadField(AccessBuilder::ForJSObjectElements(), array);
    4535          81 :   auto if_kind_is_double = __ MakeLabel();
    4536          81 :   auto done = __ MakeLabel();
    4537             :   __ GotoIf(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS),
    4538          81 :             &if_kind_is_double);
    4539             :   {
    4540             :     // Our ElementsKind is HOLEY_SMI_ELEMENTS or HOLEY_ELEMENTS.
    4541             :     __ StoreElement(AccessBuilder::ForFixedArrayElement(HOLEY_ELEMENTS),
    4542          81 :                     elements, index, value);
    4543             :     __ Goto(&done);
    4544             :   }
    4545             :   __ Bind(&if_kind_is_double);
    4546             :   {
    4547             :     // Our ElementsKind is HOLEY_DOUBLE_ELEMENTS.
    4548          81 :     auto do_double_store = __ MakeLabel();
    4549          81 :     __ GotoIfNot(ObjectIsSmi(value), &do_double_store);
    4550             :     {
    4551          81 :       Node* int_value = ChangeSmiToInt32(value);
    4552          81 :       Node* float_value = __ ChangeInt32ToFloat64(int_value);
    4553             :       __ StoreElement(AccessBuilder::ForFixedDoubleArrayElement(), elements,
    4554          81 :                       index, float_value);
    4555             :       __ Goto(&done);
    4556             :     }
    4557             :     __ Bind(&do_double_store);
    4558             :     {
    4559             :       Node* float_value =
    4560          81 :           __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    4561             :       __ StoreElement(AccessBuilder::ForFixedDoubleArrayElement(), elements,
    4562          81 :                       index, float_value);
    4563             :       __ Goto(&done);
    4564             :     }
    4565             :   }
    4566             : 
    4567             :   __ Bind(&done);
    4568          81 : }
    4569             : 
    4570          22 : void EffectControlLinearizer::LowerTransitionAndStoreNumberElement(Node* node) {
    4571             :   Node* array = node->InputAt(0);
    4572             :   Node* index = node->InputAt(1);
    4573             :   Node* value = node->InputAt(2);  // This is a Float64, not tagged.
    4574             : 
    4575             :   // Possibly transition array based on input and store.
    4576             :   //
    4577             :   //   -- TRANSITION PHASE -----------------
    4578             :   //   kind = ElementsKind(array)
    4579             :   //   if kind == HOLEY_SMI_ELEMENTS {
    4580             :   //     Transition array to HOLEY_DOUBLE_ELEMENTS
    4581             :   //   } else if kind != HOLEY_DOUBLE_ELEMENTS {
    4582             :   //     This is UNREACHABLE, execute a debug break.
    4583             :   //   }
    4584             :   //
    4585             :   //   -- STORE PHASE ----------------------
    4586             :   //   Store array[index] = value (it's a float)
    4587             :   //
    4588          22 :   Node* map = __ LoadField(AccessBuilder::ForMap(), array);
    4589             :   Node* kind;
    4590             :   {
    4591          22 :     Node* bit_field2 = __ LoadField(AccessBuilder::ForMapBitField2(), map);
    4592          22 :     Node* mask = __ Int32Constant(Map::ElementsKindBits::kMask);
    4593          22 :     Node* andit = __ Word32And(bit_field2, mask);
    4594          22 :     Node* shift = __ Int32Constant(Map::ElementsKindBits::kShift);
    4595          22 :     kind = __ Word32Shr(andit, shift);
    4596             :   }
    4597             : 
    4598          22 :   auto do_store = __ MakeLabel();
    4599             : 
    4600             :   // {value} is a float64.
    4601          22 :   auto transition_smi_array = __ MakeDeferredLabel();
    4602             :   {
    4603             :     __ GotoIfNot(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS),
    4604          22 :                  &transition_smi_array);
    4605             :     // We expect that our input array started at HOLEY_SMI_ELEMENTS, and
    4606             :     // climbs the lattice up to HOLEY_DOUBLE_ELEMENTS. Force a debug break
    4607             :     // if this assumption is broken. It also would be the case that
    4608             :     // loop peeling can break this assumption.
    4609             :     __ GotoIf(__ Word32Equal(kind, __ Int32Constant(HOLEY_DOUBLE_ELEMENTS)),
    4610          22 :               &do_store);
    4611             :     // TODO(turbofan): It would be good to have an "Unreachable()" node type.
    4612          22 :     __ DebugBreak();
    4613             :     __ Goto(&do_store);
    4614             :   }
    4615             : 
    4616             :   __ Bind(&transition_smi_array);  // deferred code.
    4617             :   {
    4618             :     // Transition {array} from HOLEY_SMI_ELEMENTS to HOLEY_DOUBLE_ELEMENTS.
    4619             :     TransitionElementsTo(node, array, HOLEY_SMI_ELEMENTS,
    4620          22 :                          HOLEY_DOUBLE_ELEMENTS);
    4621             :     __ Goto(&do_store);
    4622             :   }
    4623             : 
    4624             :   __ Bind(&do_store);
    4625             : 
    4626          22 :   Node* elements = __ LoadField(AccessBuilder::ForJSObjectElements(), array);
    4627             :   __ StoreElement(AccessBuilder::ForFixedDoubleArrayElement(), elements, index,
    4628          22 :                   value);
    4629          22 : }
    4630             : 
    4631          21 : void EffectControlLinearizer::LowerTransitionAndStoreNonNumberElement(
    4632          21 :     Node* node) {
    4633             :   Node* array = node->InputAt(0);
    4634             :   Node* index = node->InputAt(1);
    4635             :   Node* value = node->InputAt(2);
    4636             : 
    4637             :   // Possibly transition array based on input and store.
    4638             :   //
    4639             :   //   -- TRANSITION PHASE -----------------
    4640             :   //   kind = ElementsKind(array)
    4641             :   //   if kind == HOLEY_SMI_ELEMENTS {
    4642             :   //     Transition array to HOLEY_ELEMENTS
    4643             :   //   } else if kind == HOLEY_DOUBLE_ELEMENTS {
    4644             :   //     Transition array to HOLEY_ELEMENTS
    4645             :   //   }
    4646             :   //
    4647             :   //   -- STORE PHASE ----------------------
    4648             :   //   // kind is HOLEY_ELEMENTS
    4649             :   //   Store array[index] = value
    4650             :   //
    4651          21 :   Node* map = __ LoadField(AccessBuilder::ForMap(), array);
    4652             :   Node* kind;
    4653             :   {
    4654          21 :     Node* bit_field2 = __ LoadField(AccessBuilder::ForMapBitField2(), map);
    4655          21 :     Node* mask = __ Int32Constant(Map::ElementsKindBits::kMask);
    4656          21 :     Node* andit = __ Word32And(bit_field2, mask);
    4657          21 :     Node* shift = __ Int32Constant(Map::ElementsKindBits::kShift);
    4658          21 :     kind = __ Word32Shr(andit, shift);
    4659             :   }
    4660             : 
    4661          21 :   auto do_store = __ MakeLabel();
    4662             : 
    4663          21 :   auto transition_smi_array = __ MakeDeferredLabel();
    4664          21 :   auto transition_double_to_fast = __ MakeDeferredLabel();
    4665             :   {
    4666             :     __ GotoIfNot(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS),
    4667          21 :                  &transition_smi_array);
    4668             :     __ GotoIf(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS),
    4669          21 :               &transition_double_to_fast);
    4670             :     __ Goto(&do_store);
    4671             :   }
    4672             : 
    4673             :   __ Bind(&transition_smi_array);  // deferred code.
    4674             :   {
    4675             :     // Transition {array} from HOLEY_SMI_ELEMENTS to HOLEY_ELEMENTS.
    4676          21 :     TransitionElementsTo(node, array, HOLEY_SMI_ELEMENTS, HOLEY_ELEMENTS);
    4677             :     __ Goto(&do_store);
    4678             :   }
    4679             : 
    4680             :   __ Bind(&transition_double_to_fast);  // deferred code.
    4681             :   {
    4682          21 :     TransitionElementsTo(node, array, HOLEY_DOUBLE_ELEMENTS, HOLEY_ELEMENTS);
    4683             :     __ Goto(&do_store);
    4684             :   }
    4685             : 
    4686             :   __ Bind(&do_store);
    4687             : 
    4688          21 :   Node* elements = __ LoadField(AccessBuilder::ForJSObjectElements(), array);
    4689             :   // Our ElementsKind is HOLEY_ELEMENTS.
    4690          21 :   ElementAccess access = AccessBuilder::ForFixedArrayElement(HOLEY_ELEMENTS);
    4691          21 :   Type value_type = ValueTypeParameterOf(node->op());
    4692          21 :   if (value_type.Is(Type::BooleanOrNullOrUndefined())) {
    4693          16 :     access.type = value_type;
    4694          16 :     access.write_barrier_kind = kNoWriteBarrier;
    4695             :   }
    4696          21 :   __ StoreElement(access, elements, index, value);
    4697          21 : }
    4698             : 
    4699          78 : void EffectControlLinearizer::LowerStoreSignedSmallElement(Node* node) {
    4700             :   Node* array = node->InputAt(0);
    4701             :   Node* index = node->InputAt(1);
    4702             :   Node* value = node->InputAt(2);  // int32
    4703             : 
    4704             :   // Store a signed small in an output array.
    4705             :   //
    4706             :   //   kind = ElementsKind(array)
    4707             :   //
    4708             :   //   -- STORE PHASE ----------------------
    4709             :   //   if kind == HOLEY_DOUBLE_ELEMENTS {
    4710             :   //     float_value = convert int32 to float
    4711             :   //     Store array[index] = float_value
    4712             :   //   } else {
    4713             :   //     // kind is HOLEY_SMI_ELEMENTS or HOLEY_ELEMENTS
    4714             :   //     smi_value = convert int32 to smi
    4715             :   //     Store array[index] = smi_value
    4716             :   //   }
    4717             :   //
    4718          78 :   Node* map = __ LoadField(AccessBuilder::ForMap(), array);
    4719             :   Node* kind;
    4720             :   {
    4721          78 :     Node* bit_field2 = __ LoadField(AccessBuilder::ForMapBitField2(), map);
    4722          78 :     Node* mask = __ Int32Constant(Map::ElementsKindBits::kMask);
    4723          78 :     Node* andit = __ Word32And(bit_field2, mask);
    4724          78 :     Node* shift = __ Int32Constant(Map::ElementsKindBits::kShift);
    4725          78 :     kind = __ Word32Shr(andit, shift);
    4726             :   }
    4727             : 
    4728          78 :   Node* elements = __ LoadField(AccessBuilder::ForJSObjectElements(), array);
    4729          78 :   auto if_kind_is_double = __ MakeLabel();
    4730          78 :   auto done = __ MakeLabel();
    4731             :   __ GotoIf(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS),
    4732          78 :             &if_kind_is_double);
    4733             :   {
    4734             :     // Our ElementsKind is HOLEY_SMI_ELEMENTS or HOLEY_ELEMENTS.
    4735             :     // In this case, we know our value is a signed small, and we can optimize
    4736             :     // the ElementAccess information.
    4737          78 :     ElementAccess access = AccessBuilder::ForFixedArrayElement();
    4738          78 :     access.type = Type::SignedSmall();
    4739          78 :     access.machine_type = MachineType::TaggedSigned();
    4740          78 :     access.write_barrier_kind = kNoWriteBarrier;
    4741          78 :     Node* smi_value = ChangeInt32ToSmi(value);
    4742          78 :     __ StoreElement(access, elements, index, smi_value);
    4743             :     __ Goto(&done);
    4744             :   }
    4745             :   __ Bind(&if_kind_is_double);
    4746             :   {
    4747             :     // Our ElementsKind is HOLEY_DOUBLE_ELEMENTS.
    4748          78 :     Node* float_value = __ ChangeInt32ToFloat64(value);
    4749             :     __ StoreElement(AccessBuilder::ForFixedDoubleArrayElement(), elements,
    4750          78 :                     index, float_value);
    4751             :     __ Goto(&done);
    4752             :   }
    4753             : 
    4754             :   __ Bind(&done);
    4755          78 : }
    4756             : 
    4757        4926 : void EffectControlLinearizer::LowerRuntimeAbort(Node* node) {
    4758        2463 :   AbortReason reason = AbortReasonOf(node->op());
    4759        2463 :   Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
    4760             :   Runtime::FunctionId id = Runtime::kAbort;
    4761             :   auto call_descriptor = Linkage::GetRuntimeCallDescriptor(
    4762        2463 :       graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags);
    4763             :   __ Call(call_descriptor, __ CEntryStubConstant(1),
    4764             :           jsgraph()->SmiConstant(static_cast<int>(reason)),
    4765             :           __ ExternalConstant(ExternalReference::Create(id)),
    4766        4926 :           __ Int32Constant(1), __ NoContextConstant());
    4767        2463 : }
    4768             : 
    4769         892 : Node* EffectControlLinearizer::LowerConvertReceiver(Node* node) {
    4770         892 :   ConvertReceiverMode const mode = ConvertReceiverModeOf(node->op());
    4771             :   Node* value = node->InputAt(0);
    4772             :   Node* global_proxy = node->InputAt(1);
    4773             : 
    4774         892 :   switch (mode) {
    4775             :     case ConvertReceiverMode::kNullOrUndefined: {
    4776             :       return global_proxy;
    4777             :     }
    4778             :     case ConvertReceiverMode::kNotNullOrUndefined: {
    4779         822 :       auto convert_to_object = __ MakeDeferredLabel();
    4780         822 :       auto done_convert = __ MakeLabel(MachineRepresentation::kTagged);
    4781             : 
    4782             :       // Check if {value} is already a JSReceiver.
    4783         822 :       __ GotoIf(ObjectIsSmi(value), &convert_to_object);
    4784             :       STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
    4785         822 :       Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    4786             :       Node* value_instance_type =
    4787         822 :           __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    4788             :       Node* check = __ Uint32LessThan(
    4789         822 :           value_instance_type, __ Uint32Constant(FIRST_JS_RECEIVER_TYPE));
    4790         822 :       __ GotoIf(check, &convert_to_object);
    4791             :       __ Goto(&done_convert, value);
    4792             : 
    4793             :       // Wrap the primitive {value} into a JSValue.
    4794             :       __ Bind(&convert_to_object);
    4795             :       Operator::Properties properties = Operator::kEliminatable;
    4796         822 :       Callable callable = Builtins::CallableFor(isolate(), Builtins::kToObject);
    4797             :       CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    4798             :       auto call_descriptor = Linkage::GetStubCallDescriptor(
    4799             :           graph()->zone(), callable.descriptor(),
    4800        1644 :           callable.descriptor().GetStackParameterCount(), flags, properties);
    4801             :       Node* native_context = __ LoadField(
    4802         822 :           AccessBuilder::ForJSGlobalProxyNativeContext(), global_proxy);
    4803             :       Node* result = __ Call(call_descriptor, __ HeapConstant(callable.code()),
    4804         822 :                              value, native_context);
    4805             :       __ Goto(&done_convert, result);
    4806             : 
    4807             :       __ Bind(&done_convert);
    4808             :       return done_convert.PhiAt(0);
    4809             :     }
    4810             :     case ConvertReceiverMode::kAny: {
    4811          70 :       auto convert_to_object = __ MakeDeferredLabel();
    4812          70 :       auto convert_global_proxy = __ MakeDeferredLabel();
    4813          70 :       auto done_convert = __ MakeLabel(MachineRepresentation::kTagged);
    4814             : 
    4815             :       // Check if {value} is already a JSReceiver, or null/undefined.
    4816          70 :       __ GotoIf(ObjectIsSmi(value), &convert_to_object);
    4817             :       STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
    4818          70 :       Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    4819             :       Node* value_instance_type =
    4820          70 :           __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    4821             :       Node* check = __ Uint32LessThan(
    4822          70 :           value_instance_type, __ Uint32Constant(FIRST_JS_RECEIVER_TYPE));
    4823          70 :       __ GotoIf(check, &convert_to_object);
    4824             :       __ Goto(&done_convert, value);
    4825             : 
    4826             :       // Wrap the primitive {value} into a JSValue.
    4827             :       __ Bind(&convert_to_object);
    4828             :       __ GotoIf(__ WordEqual(value, __ UndefinedConstant()),
    4829          70 :                 &convert_global_proxy);
    4830          70 :       __ GotoIf(__ WordEqual(value, __ NullConstant()), &convert_global_proxy);
    4831             :       Operator::Properties properties = Operator::kEliminatable;
    4832          70 :       Callable callable = Builtins::CallableFor(isolate(), Builtins::kToObject);
    4833             :       CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    4834             :       auto call_descriptor = Linkage::GetStubCallDescriptor(
    4835             :           graph()->zone(), callable.descriptor(),
    4836         140 :           callable.descriptor().GetStackParameterCount(), flags, properties);
    4837             :       Node* native_context = __ LoadField(
    4838          70 :           AccessBuilder::ForJSGlobalProxyNativeContext(), global_proxy);
    4839             :       Node* result = __ Call(call_descriptor, __ HeapConstant(callable.code()),
    4840          70 :                              value, native_context);
    4841             :       __ Goto(&done_convert, result);
    4842             : 
    4843             :       // Replace the {value} with the {global_proxy}.
    4844             :       __ Bind(&convert_global_proxy);
    4845             :       __ Goto(&done_convert, global_proxy);
    4846             : 
    4847             :       __ Bind(&done_convert);
    4848             :       return done_convert.PhiAt(0);
    4849             :     }
    4850             :   }
    4851             : 
    4852           0 :   UNREACHABLE();
    4853             :   return nullptr;
    4854             : }
    4855             : 
    4856        8223 : Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundUp(Node* node) {
    4857             :   // Nothing to be done if a fast hardware instruction is available.
    4858        8223 :   if (machine()->Float64RoundUp().IsSupported()) {
    4859             :     return Nothing<Node*>();
    4860             :   }
    4861             : 
    4862             :   Node* const input = node->InputAt(0);
    4863             : 
    4864             :   // General case for ceil.
    4865             :   //
    4866             :   //   if 0.0 < input then
    4867             :   //     if 2^52 <= input then
    4868             :   //       input
    4869             :   //     else
    4870             :   //       let temp1 = (2^52 + input) - 2^52 in
    4871             :   //       if temp1 < input then
    4872             :   //         temp1 + 1
    4873             :   //       else
    4874             :   //         temp1
    4875             :   //   else
    4876             :   //     if input == 0 then
    4877             :   //       input
    4878             :   //     else
    4879             :   //       if input <= -2^52 then
    4880             :   //         input
    4881             :   //       else
    4882             :   //         let temp1 = -0 - input in
    4883             :   //         let temp2 = (2^52 + temp1) - 2^52 in
    4884             :   //         let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
    4885             :   //         -0 - temp3
    4886             : 
    4887           0 :   auto if_not_positive = __ MakeDeferredLabel();
    4888           0 :   auto if_greater_than_two_52 = __ MakeDeferredLabel();
    4889           0 :   auto if_less_than_minus_two_52 = __ MakeDeferredLabel();
    4890           0 :   auto if_zero = __ MakeDeferredLabel();
    4891           0 :   auto done_temp3 = __ MakeLabel(MachineRepresentation::kFloat64);
    4892           0 :   auto done = __ MakeLabel(MachineRepresentation::kFloat64);
    4893             : 
    4894           0 :   Node* const zero = __ Float64Constant(0.0);
    4895           0 :   Node* const two_52 = __ Float64Constant(4503599627370496.0E0);
    4896           0 :   Node* const one = __ Float64Constant(1.0);
    4897             : 
    4898           0 :   Node* check0 = __ Float64LessThan(zero, input);
    4899           0 :   __ GotoIfNot(check0, &if_not_positive);
    4900             :   {
    4901           0 :     Node* check1 = __ Float64LessThanOrEqual(two_52, input);
    4902           0 :     __ GotoIf(check1, &if_greater_than_two_52);
    4903             :     {
    4904           0 :       Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52);
    4905           0 :       __ GotoIfNot(__ Float64LessThan(temp1, input), &done, temp1);
    4906           0 :       __ Goto(&done, __ Float64Add(temp1, one));
    4907             :     }
    4908             : 
    4909             :     __ Bind(&if_greater_than_two_52);
    4910             :     __ Goto(&done, input);
    4911             :   }
    4912             : 
    4913             :   __ Bind(&if_not_positive);
    4914             :   {
    4915           0 :     Node* check1 = __ Float64Equal(input, zero);
    4916           0 :     __ GotoIf(check1, &if_zero);
    4917             : 
    4918           0 :     Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0);
    4919           0 :     Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52);
    4920           0 :     __ GotoIf(check2, &if_less_than_minus_two_52);
    4921             : 
    4922             :     {
    4923           0 :       Node* const minus_zero = __ Float64Constant(-0.0);
    4924           0 :       Node* temp1 = __ Float64Sub(minus_zero, input);
    4925           0 :       Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52);
    4926           0 :       Node* check3 = __ Float64LessThan(temp1, temp2);
    4927           0 :       __ GotoIfNot(check3, &done_temp3, temp2);
    4928           0 :       __ Goto(&done_temp3, __ Float64Sub(temp2, one));
    4929             : 
    4930             :       __ Bind(&done_temp3);
    4931             :       Node* temp3 = done_temp3.PhiAt(0);
    4932           0 :       __ Goto(&done, __ Float64Sub(minus_zero, temp3));
    4933             :     }
    4934             :     __ Bind(&if_less_than_minus_two_52);
    4935             :     __ Goto(&done, input);
    4936             : 
    4937             :     __ Bind(&if_zero);
    4938             :     __ Goto(&done, input);
    4939             :   }
    4940             :   __ Bind(&done);
    4941             :   return Just(done.PhiAt(0));
    4942             : }
    4943             : 
    4944           0 : Node* EffectControlLinearizer::BuildFloat64RoundDown(Node* value) {
    4945           0 :   if (machine()->Float64RoundDown().IsSupported()) {
    4946           0 :     return __ Float64RoundDown(value);
    4947             :   }
    4948             : 
    4949             :   Node* const input = value;
    4950             : 
    4951             :   // General case for floor.
    4952             :   //
    4953             :   //   if 0.0 < input then
    4954             :   //     if 2^52 <= input then
    4955             :   //       input
    4956             :   //     else
    4957             :   //       let temp1 = (2^52 + input) - 2^52 in
    4958             :   //       if input < temp1 then
    4959             :   //         temp1 - 1
    4960             :   //       else
    4961             :   //         temp1
    4962             :   //   else
    4963             :   //     if input == 0 then
    4964             :   //       input
    4965             :   //     else
    4966             :   //       if input <= -2^52 then
    4967             :   //         input
    4968             :   //       else
    4969             :   //         let temp1 = -0 - input in
    4970             :   //         let temp2 = (2^52 + temp1) - 2^52 in
    4971             :   //         if temp2 < temp1 then
    4972             :   //           -1 - temp2
    4973             :   //         else
    4974             :   //           -0 - temp2
    4975             : 
    4976           0 :   auto if_not_positive = __ MakeDeferredLabel();
    4977           0 :   auto if_greater_than_two_52 = __ MakeDeferredLabel();
    4978           0 :   auto if_less_than_minus_two_52 = __ MakeDeferredLabel();
    4979           0 :   auto if_temp2_lt_temp1 = __ MakeLabel();
    4980           0 :   auto if_zero = __ MakeDeferredLabel();
    4981           0 :   auto done = __ MakeLabel(MachineRepresentation::kFloat64);
    4982             : 
    4983           0 :   Node* const zero = __ Float64Constant(0.0);
    4984           0 :   Node* const two_52 = __ Float64Constant(4503599627370496.0E0);
    4985             : 
    4986           0 :   Node* check0 = __ Float64LessThan(zero, input);
    4987           0 :   __ GotoIfNot(check0, &if_not_positive);
    4988             :   {
    4989           0 :     Node* check1 = __ Float64LessThanOrEqual(two_52, input);
    4990           0 :     __ GotoIf(check1, &if_greater_than_two_52);
    4991             :     {
    4992           0 :       Node* const one = __ Float64Constant(1.0);
    4993           0 :       Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52);
    4994           0 :       __ GotoIfNot(__ Float64LessThan(input, temp1), &done, temp1);
    4995           0 :       __ Goto(&done, __ Float64Sub(temp1, one));
    4996             :     }
    4997             : 
    4998             :     __ Bind(&if_greater_than_two_52);
    4999             :     __ Goto(&done, input);
    5000             :   }
    5001             : 
    5002             :   __ Bind(&if_not_positive);
    5003             :   {
    5004           0 :     Node* check1 = __ Float64Equal(input, zero);
    5005           0 :     __ GotoIf(check1, &if_zero);
    5006             : 
    5007           0 :     Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0);
    5008           0 :     Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52);
    5009           0 :     __ GotoIf(check2, &if_less_than_minus_two_52);
    5010             : 
    5011             :     {
    5012           0 :       Node* const minus_zero = __ Float64Constant(-0.0);
    5013           0 :       Node* temp1 = __ Float64Sub(minus_zero, input);
    5014           0 :       Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52);
    5015           0 :       Node* check3 = __ Float64LessThan(temp2, temp1);
    5016           0 :       __ GotoIf(check3, &if_temp2_lt_temp1);
    5017           0 :       __ Goto(&done, __ Float64Sub(minus_zero, temp2));
    5018             : 
    5019             :       __ Bind(&if_temp2_lt_temp1);
    5020           0 :       __ Goto(&done, __ Float64Sub(__ Float64Constant(-1.0), temp2));
    5021             :     }
    5022             :     __ Bind(&if_less_than_minus_two_52);
    5023             :     __ Goto(&done, input);
    5024             : 
    5025             :     __ Bind(&if_zero);
    5026             :     __ Goto(&done, input);
    5027             :   }
    5028             :   __ Bind(&done);
    5029             :   return done.PhiAt(0);
    5030             : }
    5031             : 
    5032       25908 : Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundDown(Node* node) {
    5033             :   // Nothing to be done if a fast hardware instruction is available.
    5034       25908 :   if (machine()->Float64RoundDown().IsSupported()) {
    5035             :     return Nothing<Node*>();
    5036             :   }
    5037             : 
    5038             :   Node* const input = node->InputAt(0);
    5039           0 :   return Just(BuildFloat64RoundDown(input));
    5040             : }
    5041             : 
    5042         266 : Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundTiesEven(Node* node) {
    5043             :   // Nothing to be done if a fast hardware instruction is available.
    5044         266 :   if (machine()->Float64RoundTiesEven().IsSupported()) {
    5045             :     return Nothing<Node*>();
    5046             :   }
    5047             : 
    5048             :   Node* const input = node->InputAt(0);
    5049             : 
    5050             :   // Generate case for round ties to even:
    5051             :   //
    5052             :   //   let value = floor(input) in
    5053             :   //   let temp1 = input - value in
    5054             :   //   if temp1 < 0.5 then
    5055             :   //     value
    5056             :   //   else if 0.5 < temp1 then
    5057             :   //     value + 1.0
    5058             :   //   else
    5059             :   //     let temp2 = value % 2.0 in
    5060             :   //     if temp2 == 0.0 then
    5061             :   //       value
    5062             :   //     else
    5063             :   //       value + 1.0
    5064             : 
    5065           0 :   auto if_is_half = __ MakeLabel();
    5066           0 :   auto done = __ MakeLabel(MachineRepresentation::kFloat64);
    5067             : 
    5068           0 :   Node* value = BuildFloat64RoundDown(input);
    5069           0 :   Node* temp1 = __ Float64Sub(input, value);
    5070             : 
    5071           0 :   Node* const half = __ Float64Constant(0.5);
    5072           0 :   Node* check0 = __ Float64LessThan(temp1, half);
    5073           0 :   __ GotoIf(check0, &done, value);
    5074             : 
    5075           0 :   Node* const one = __ Float64Constant(1.0);
    5076           0 :   Node* check1 = __ Float64LessThan(half, temp1);
    5077           0 :   __ GotoIfNot(check1, &if_is_half);
    5078           0 :   __ Goto(&done, __ Float64Add(value, one));
    5079             : 
    5080             :   __ Bind(&if_is_half);
    5081           0 :   Node* temp2 = __ Float64Mod(value, __ Float64Constant(2.0));
    5082           0 :   Node* check2 = __ Float64Equal(temp2, __ Float64Constant(0.0));
    5083           0 :   __ GotoIf(check2, &done, value);
    5084           0 :   __ Goto(&done, __ Float64Add(value, one));
    5085             : 
    5086             :   __ Bind(&done);
    5087             :   return Just(done.PhiAt(0));
    5088             : }
    5089             : 
    5090         140 : Node* EffectControlLinearizer::BuildFloat64RoundTruncate(Node* input) {
    5091         140 :   if (machine()->Float64RoundTruncate().IsSupported()) {
    5092         140 :     return __ Float64RoundTruncate(input);
    5093             :   }
    5094             :   // General case for trunc.
    5095             :   //
    5096             :   //   if 0.0 < input then
    5097             :   //     if 2^52 <= input then
    5098             :   //       input
    5099             :   //     else
    5100             :   //       let temp1 = (2^52 + input) - 2^52 in
    5101             :   //       if input < temp1 then
    5102             :   //         temp1 - 1
    5103             :   //       else
    5104             :   //         temp1
    5105             :   //   else
    5106             :   //     if input == 0 then
    5107             :   //       input
    5108             :   //     else
    5109             :   //       if input <= -2^52 then
    5110             :   //         input
    5111             :   //       else
    5112             :   //         let temp1 = -0 - input in
    5113             :   //         let temp2 = (2^52 + temp1) - 2^52 in
    5114             :   //         let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
    5115             :   //         -0 - temp3
    5116             :   //
    5117             :   // Note: We do not use the Diamond helper class here, because it really hurts
    5118             :   // readability with nested diamonds.
    5119             : 
    5120           0 :   auto if_not_positive = __ MakeDeferredLabel();
    5121           0 :   auto if_greater_than_two_52 = __ MakeDeferredLabel();
    5122           0 :   auto if_less_than_minus_two_52 = __ MakeDeferredLabel();
    5123           0 :   auto if_zero = __ MakeDeferredLabel();
    5124           0 :   auto done_temp3 = __ MakeLabel(MachineRepresentation::kFloat64);
    5125           0 :   auto done = __ MakeLabel(MachineRepresentation::kFloat64);
    5126             : 
    5127           0 :   Node* const zero = __ Float64Constant(0.0);
    5128           0 :   Node* const two_52 = __ Float64Constant(4503599627370496.0E0);
    5129           0 :   Node* const one = __ Float64Constant(1.0);
    5130             : 
    5131           0 :   Node* check0 = __ Float64LessThan(zero, input);
    5132           0 :   __ GotoIfNot(check0, &if_not_positive);
    5133             :   {
    5134           0 :     Node* check1 = __ Float64LessThanOrEqual(two_52, input);
    5135           0 :     __ GotoIf(check1, &if_greater_than_two_52);
    5136             :     {
    5137           0 :       Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52);
    5138           0 :       __ GotoIfNot(__ Float64LessThan(input, temp1), &done, temp1);
    5139           0 :       __ Goto(&done, __ Float64Sub(temp1, one));
    5140             :     }
    5141             : 
    5142             :     __ Bind(&if_greater_than_two_52);
    5143             :     __ Goto(&done, input);
    5144             :   }
    5145             : 
    5146             :   __ Bind(&if_not_positive);
    5147             :   {
    5148           0 :     Node* check1 = __ Float64Equal(input, zero);
    5149           0 :     __ GotoIf(check1, &if_zero);
    5150             : 
    5151           0 :     Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0);
    5152           0 :     Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52);
    5153           0 :     __ GotoIf(check2, &if_less_than_minus_two_52);
    5154             : 
    5155             :     {
    5156           0 :       Node* const minus_zero = __ Float64Constant(-0.0);
    5157           0 :       Node* temp1 = __ Float64Sub(minus_zero, input);
    5158           0 :       Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52);
    5159           0 :       Node* check3 = __ Float64LessThan(temp1, temp2);
    5160           0 :       __ GotoIfNot(check3, &done_temp3, temp2);
    5161           0 :       __ Goto(&done_temp3, __ Float64Sub(temp2, one));
    5162             : 
    5163             :       __ Bind(&done_temp3);
    5164             :       Node* temp3 = done_temp3.PhiAt(0);
    5165           0 :       __ Goto(&done, __ Float64Sub(minus_zero, temp3));
    5166             :     }
    5167             :     __ Bind(&if_less_than_minus_two_52);
    5168             :     __ Goto(&done, input);
    5169             : 
    5170             :     __ Bind(&if_zero);
    5171             :     __ Goto(&done, input);
    5172             :   }
    5173             :   __ Bind(&done);
    5174             :   return done.PhiAt(0);
    5175             : }
    5176             : 
    5177        6912 : Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundTruncate(Node* node) {
    5178             :   // Nothing to be done if a fast hardware instruction is available.
    5179        6912 :   if (machine()->Float64RoundTruncate().IsSupported()) {
    5180             :     return Nothing<Node*>();
    5181             :   }
    5182             : 
    5183             :   Node* const input = node->InputAt(0);
    5184           0 :   return Just(BuildFloat64RoundTruncate(input));
    5185             : }
    5186             : 
    5187         380 : Node* EffectControlLinearizer::LowerFindOrderedHashMapEntry(Node* node) {
    5188         190 :   Node* table = NodeProperties::GetValueInput(node, 0);
    5189         190 :   Node* key = NodeProperties::GetValueInput(node, 1);
    5190             : 
    5191             :   {
    5192             :     Callable const callable =
    5193         190 :         Builtins::CallableFor(isolate(), Builtins::kFindOrderedHashMapEntry);
    5194         190 :     Operator::Properties const properties = node->op()->properties();
    5195             :     CallDescriptor::Flags const flags = CallDescriptor::kNoFlags;
    5196             :     auto call_descriptor = Linkage::GetStubCallDescriptor(
    5197             :         graph()->zone(), callable.descriptor(),
    5198         380 :         callable.descriptor().GetStackParameterCount(), flags, properties);
    5199             :     return __ Call(call_descriptor, __ HeapConstant(callable.code()), table,
    5200         380 :                    key, __ NoContextConstant());
    5201             :   }
    5202             : }
    5203             : 
    5204          15 : Node* EffectControlLinearizer::ComputeUnseededHash(Node* value) {
    5205             :   // See v8::internal::ComputeUnseededHash()
    5206             :   value = __ Int32Add(__ Word32Xor(value, __ Int32Constant(0xFFFFFFFF)),
    5207          15 :                       __ Word32Shl(value, __ Int32Constant(15)));
    5208          15 :   value = __ Word32Xor(value, __ Word32Shr(value, __ Int32Constant(12)));
    5209          15 :   value = __ Int32Add(value, __ Word32Shl(value, __ Int32Constant(2)));
    5210          15 :   value = __ Word32Xor(value, __ Word32Shr(value, __ Int32Constant(4)));
    5211          15 :   value = __ Int32Mul(value, __ Int32Constant(2057));
    5212          15 :   value = __ Word32Xor(value, __ Word32Shr(value, __ Int32Constant(16)));
    5213          15 :   value = __ Word32And(value, __ Int32Constant(0x3FFFFFFF));
    5214          15 :   return value;
    5215             : }
    5216             : 
    5217          15 : Node* EffectControlLinearizer::LowerFindOrderedHashMapEntryForInt32Key(
    5218             :     Node* node) {
    5219          15 :   Node* table = NodeProperties::GetValueInput(node, 0);
    5220          15 :   Node* key = NodeProperties::GetValueInput(node, 1);
    5221             : 
    5222             :   // Compute the integer hash code.
    5223          15 :   Node* hash = ChangeUint32ToUintPtr(ComputeUnseededHash(key));
    5224             : 
    5225             :   Node* number_of_buckets = ChangeSmiToIntPtr(__ LoadField(
    5226          15 :       AccessBuilder::ForOrderedHashMapOrSetNumberOfBuckets(), table));
    5227          15 :   hash = __ WordAnd(hash, __ IntSub(number_of_buckets, __ IntPtrConstant(1)));
    5228             :   Node* first_entry = ChangeSmiToIntPtr(__ Load(
    5229             :       MachineType::TaggedSigned(), table,
    5230             :       __ IntAdd(__ WordShl(hash, __ IntPtrConstant(kTaggedSizeLog2)),
    5231             :                 __ IntPtrConstant(OrderedHashMap::HashTableStartOffset() -
    5232          15 :                                   kHeapObjectTag))));
    5233             : 
    5234          15 :   auto loop = __ MakeLoopLabel(MachineType::PointerRepresentation());
    5235          15 :   auto done = __ MakeLabel(MachineType::PointerRepresentation());
    5236             :   __ Goto(&loop, first_entry);
    5237             :   __ Bind(&loop);
    5238             :   {
    5239             :     Node* entry = loop.PhiAt(0);
    5240             :     Node* check =
    5241          15 :         __ WordEqual(entry, __ IntPtrConstant(OrderedHashMap::kNotFound));
    5242          15 :     __ GotoIf(check, &done, entry);
    5243             :     entry = __ IntAdd(
    5244             :         __ IntMul(entry, __ IntPtrConstant(OrderedHashMap::kEntrySize)),
    5245          15 :         number_of_buckets);
    5246             : 
    5247             :     Node* candidate_key = __ Load(
    5248             :         MachineType::AnyTagged(), table,
    5249             :         __ IntAdd(__ WordShl(entry, __ IntPtrConstant(kTaggedSizeLog2)),
    5250             :                   __ IntPtrConstant(OrderedHashMap::HashTableStartOffset() -
    5251          15 :                                     kHeapObjectTag)));
    5252             : 
    5253          15 :     auto if_match = __ MakeLabel();
    5254          15 :     auto if_notmatch = __ MakeLabel();
    5255          15 :     auto if_notsmi = __ MakeDeferredLabel();
    5256          15 :     __ GotoIfNot(ObjectIsSmi(candidate_key), &if_notsmi);
    5257             :     __ Branch(__ Word32Equal(ChangeSmiToInt32(candidate_key), key), &if_match,
    5258          15 :               &if_notmatch);
    5259             : 
    5260             :     __ Bind(&if_notsmi);
    5261             :     __ GotoIfNot(
    5262             :         __ WordEqual(__ LoadField(AccessBuilder::ForMap(), candidate_key),
    5263             :                      __ HeapNumberMapConstant()),
    5264          15 :         &if_notmatch);
    5265             :     __ Branch(__ Float64Equal(__ LoadField(AccessBuilder::ForHeapNumberValue(),
    5266             :                                            candidate_key),
    5267             :                               __ ChangeInt32ToFloat64(key)),
    5268          15 :               &if_match, &if_notmatch);
    5269             : 
    5270             :     __ Bind(&if_match);
    5271             :     __ Goto(&done, entry);
    5272             : 
    5273             :     __ Bind(&if_notmatch);
    5274             :     {
    5275             :       Node* next_entry = ChangeSmiToIntPtr(__ Load(
    5276             :           MachineType::TaggedSigned(), table,
    5277             :           __ IntAdd(
    5278             :               __ WordShl(entry, __ IntPtrConstant(kTaggedSizeLog2)),
    5279             :               __ IntPtrConstant(OrderedHashMap::HashTableStartOffset() +
    5280             :                                 OrderedHashMap::kChainOffset * kTaggedSize -
    5281          15 :                                 kHeapObjectTag))));
    5282             :       __ Goto(&loop, next_entry);
    5283             :     }
    5284             :   }
    5285             : 
    5286             :   __ Bind(&done);
    5287          15 :   return done.PhiAt(0);
    5288             : }
    5289             : 
    5290           7 : Node* EffectControlLinearizer::LowerDateNow(Node* node) {
    5291           7 :   Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
    5292             :   Runtime::FunctionId id = Runtime::kDateCurrentTime;
    5293             :   auto call_descriptor = Linkage::GetRuntimeCallDescriptor(
    5294           7 :       graph()->zone(), id, 0, properties, CallDescriptor::kNoFlags);
    5295             :   return __ Call(call_descriptor, __ CEntryStubConstant(1),
    5296             :                  __ ExternalConstant(ExternalReference::Create(id)),
    5297           7 :                  __ Int32Constant(0), __ NoContextConstant());
    5298             : }
    5299             : 
    5300             : #undef __
    5301             : 
    5302           0 : Factory* EffectControlLinearizer::factory() const {
    5303           0 :   return isolate()->factory();
    5304             : }
    5305             : 
    5306       86371 : Isolate* EffectControlLinearizer::isolate() const {
    5307       86371 :   return jsgraph()->isolate();
    5308             : }
    5309             : 
    5310             : }  // namespace compiler
    5311             : }  // namespace internal
    5312      183867 : }  // namespace v8

Generated by: LCOV version 1.10