LCOV - code coverage report
Current view: top level - src/compiler - effect-control-linearizer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1340 1551 86.4 %
Date: 2017-10-20 Functions: 114 133 85.7 %

          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-properties.h"
      14             : #include "src/compiler/node.h"
      15             : #include "src/compiler/schedule.h"
      16             : #include "src/factory-inl.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : namespace compiler {
      21             : 
      22      443358 : EffectControlLinearizer::EffectControlLinearizer(
      23             :     JSGraph* js_graph, Schedule* schedule, Zone* temp_zone,
      24             :     SourcePositionTable* source_positions)
      25             :     : js_graph_(js_graph),
      26             :       schedule_(schedule),
      27             :       temp_zone_(temp_zone),
      28             :       source_positions_(source_positions),
      29             :       graph_assembler_(js_graph, nullptr, nullptr, temp_zone),
      30      443358 :       frame_state_zapper_(nullptr) {}
      31             : 
      32     1735646 : Graph* EffectControlLinearizer::graph() const { return js_graph_->graph(); }
      33           0 : CommonOperatorBuilder* EffectControlLinearizer::common() const {
      34     1087859 :   return js_graph_->common();
      35             : }
      36           0 : SimplifiedOperatorBuilder* EffectControlLinearizer::simplified() const {
      37           0 :   return js_graph_->simplified();
      38             : }
      39           0 : MachineOperatorBuilder* EffectControlLinearizer::machine() const {
      40      377522 :   return js_graph_->machine();
      41             : }
      42             : 
      43             : namespace {
      44             : 
      45             : struct BlockEffectControlData {
      46             :   Node* current_effect = nullptr;       // New effect.
      47             :   Node* current_control = nullptr;      // New control.
      48             :   Node* current_frame_state = nullptr;  // New frame state.
      49             : };
      50             : 
      51             : class BlockEffectControlMap {
      52             :  public:
      53             :   explicit BlockEffectControlMap(Zone* temp_zone) : map_(temp_zone) {}
      54             : 
      55    18827547 :   BlockEffectControlData& For(BasicBlock* from, BasicBlock* to) {
      56    18827547 :     return map_[std::make_pair(from->rpo_number(), to->rpo_number())];
      57             :   }
      58             : 
      59             :   const BlockEffectControlData& For(BasicBlock* from, BasicBlock* to) const {
      60             :     return map_.at(std::make_pair(from->rpo_number(), to->rpo_number()));
      61             :   }
      62             : 
      63             :  private:
      64             :   typedef std::pair<int32_t, int32_t> Key;
      65             :   typedef ZoneMap<Key, BlockEffectControlData> Map;
      66             : 
      67             :   Map map_;
      68             : };
      69             : 
      70             : // Effect phis that need to be updated after the first pass.
      71             : struct PendingEffectPhi {
      72             :   Node* effect_phi;
      73             :   BasicBlock* block;
      74             : 
      75             :   PendingEffectPhi(Node* effect_phi, BasicBlock* block)
      76       41663 :       : effect_phi(effect_phi), block(block) {}
      77             : };
      78             : 
      79     3391715 : void UpdateEffectPhi(Node* node, BasicBlock* block,
      80             :                      BlockEffectControlMap* block_effects) {
      81             :   // Update all inputs to an effect phi with the effects from the given
      82             :   // block->effect map.
      83             :   DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode());
      84             :   DCHECK_EQ(static_cast<size_t>(node->op()->EffectInputCount()),
      85             :             block->PredecessorCount());
      86     7738353 :   for (int i = 0; i < node->op()->EffectInputCount(); i++) {
      87             :     Node* input = node->InputAt(i);
      88     1767176 :     BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i));
      89             :     const BlockEffectControlData& block_effect =
      90             :         block_effects->For(predecessor, block);
      91     1767183 :     if (input != block_effect.current_effect) {
      92      170108 :       node->ReplaceInput(i, block_effect.current_effect);
      93             :     }
      94             :   }
      95      812275 : }
      96             : 
      97     4252229 : void UpdateBlockControl(BasicBlock* block,
      98             :                         BlockEffectControlMap* block_effects) {
      99    12054791 :   Node* control = block->NodeAt(0);
     100             :   DCHECK(NodeProperties::IsControl(control));
     101             : 
     102             :   // Do not rewire the end node.
     103     4252229 :   if (control->opcode() == IrOpcode::kEnd) return;
     104             : 
     105             :   // Update all inputs to the given control node with the correct control.
     106             :   DCHECK(control->opcode() == IrOpcode::kMerge ||
     107             :          static_cast<size_t>(control->op()->ControlInputCount()) ==
     108             :              block->PredecessorCount());
     109    11432058 :   if (static_cast<size_t>(control->op()->ControlInputCount()) !=
     110             :       block->PredecessorCount()) {
     111             :     return;  // We already re-wired the control inputs of this node.
     112             :   }
     113    19801669 :   for (int i = 0; i < control->op()->ControlInputCount(); i++) {
     114     4196565 :     Node* input = NodeProperties::GetControlInput(control, i);
     115     4196538 :     BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i));
     116             :     const BlockEffectControlData& block_effect =
     117             :         block_effects->For(predecessor, block);
     118     4196546 :     if (input != block_effect.current_control) {
     119             :       NodeProperties::ReplaceControlInput(control, block_effect.current_control,
     120       36495 :                                           i);
     121             :     }
     122             :   }
     123             : }
     124             : 
     125     6793867 : bool HasIncomingBackEdges(BasicBlock* block) {
     126    18556032 :   for (BasicBlock* pred : block->predecessors()) {
     127     6793867 :     if (pred->rpo_number() >= block->rpo_number()) {
     128             :       return true;
     129             :     }
     130             :   }
     131             :   return false;
     132             : }
     133             : 
     134      223616 : void RemoveRegionNode(Node* node) {
     135             :   DCHECK(IrOpcode::kFinishRegion == node->opcode() ||
     136             :          IrOpcode::kBeginRegion == node->opcode());
     137             :   // Update the value/context uses to the value input of the finish node and
     138             :   // the effect uses to the effect input.
     139     3425304 :   for (Edge edge : node->use_edges()) {
     140             :     DCHECK(!edge.from()->IsDead());
     141     1600844 :     if (NodeProperties::IsEffectEdge(edge)) {
     142      224435 :       edge.UpdateTo(NodeProperties::GetEffectInput(node));
     143             :     } else {
     144             :       DCHECK(!NodeProperties::IsControlEdge(edge));
     145             :       DCHECK(!NodeProperties::IsFrameStateEdge(edge));
     146     1376409 :       edge.UpdateTo(node->InputAt(0));
     147             :     }
     148             :   }
     149      223616 :   node->Kill();
     150      223616 : }
     151             : 
     152     1177210 : void TryCloneBranch(Node* node, BasicBlock* block, Zone* temp_zone,
     153      910547 :                     Graph* graph, CommonOperatorBuilder* common,
     154             :                     BlockEffectControlMap* block_effects,
     155             :                     SourcePositionTable* source_positions) {
     156             :   DCHECK_EQ(IrOpcode::kBranch, node->opcode());
     157             : 
     158             :   // This optimization is a special case of (super)block cloning. It takes an
     159             :   // input graph as shown below and clones the Branch node for every predecessor
     160             :   // to the Merge, essentially removing the Merge completely. This avoids
     161             :   // materializing the bit for the Phi and may offer potential for further
     162             :   // branch folding optimizations (i.e. because one or more inputs to the Phi is
     163             :   // a constant). Note that there may be more Phi nodes hanging off the Merge,
     164             :   // but we can only a certain subset of them currently (actually only Phi and
     165             :   // EffectPhi nodes whose uses have either the IfTrue or IfFalse as control
     166             :   // input).
     167             : 
     168             :   //   Control1 ... ControlN
     169             :   //      ^            ^
     170             :   //      |            |   Cond1 ... CondN
     171             :   //      +----+  +----+     ^         ^
     172             :   //           |  |          |         |
     173             :   //           |  |     +----+         |
     174             :   //          Merge<--+ | +------------+
     175             :   //            ^      \|/
     176             :   //            |      Phi
     177             :   //            |       |
     178             :   //          Branch----+
     179             :   //            ^
     180             :   //            |
     181             :   //      +-----+-----+
     182             :   //      |           |
     183             :   //    IfTrue     IfFalse
     184             :   //      ^           ^
     185             :   //      |           |
     186             : 
     187             :   // The resulting graph (modulo the Phi and EffectPhi nodes) looks like this:
     188             : 
     189             :   // Control1 Cond1 ... ControlN CondN
     190             :   //    ^      ^           ^      ^
     191             :   //    \      /           \      /
     192             :   //     Branch     ...     Branch
     193             :   //       ^                  ^
     194             :   //       |                  |
     195             :   //   +---+---+          +---+----+
     196             :   //   |       |          |        |
     197             :   // IfTrue IfFalse ... IfTrue  IfFalse
     198             :   //   ^       ^          ^        ^
     199             :   //   |       |          |        |
     200             :   //   +--+ +-------------+        |
     201             :   //      | |  +--------------+ +--+
     202             :   //      | |                 | |
     203             :   //     Merge               Merge
     204             :   //       ^                   ^
     205             :   //       |                   |
     206             : 
     207             :   SourcePositionTable::Scope scope(source_positions,
     208     1074875 :                                    source_positions->GetSourcePosition(node));
     209      102335 :   Node* branch = node;
     210     2129296 :   Node* cond = NodeProperties::GetValueInput(branch, 0);
     211     2129295 :   if (!cond->OwnedBy(branch) || cond->opcode() != IrOpcode::kPhi) return;
     212      213098 :   Node* merge = NodeProperties::GetControlInput(branch);
     213      219228 :   if (merge->opcode() != IrOpcode::kMerge ||
     214      108465 :       NodeProperties::GetControlInput(cond) != merge) {
     215             :     return;
     216             :   }
     217             :   // Grab the IfTrue/IfFalse projections of the Branch.
     218      108373 :   BranchMatcher matcher(branch);
     219             :   // Check/collect other Phi/EffectPhi nodes hanging off the Merge.
     220             :   NodeVector phis(temp_zone);
     221      742701 :   for (Node* const use : merge->uses()) {
     222      320183 :     if (use == branch || use == cond) continue;
     223             :     // We cannot currently deal with non-Phi/EffectPhi nodes hanging off the
     224             :     // Merge. Ideally, we would just clone the nodes (and everything that
     225             :     // depends on it to some distant join point), but that requires knowledge
     226             :     // about dominance/post-dominance.
     227      112705 :     if (!NodeProperties::IsPhi(use)) return;
     228      115790 :     for (Edge edge : use->use_edges()) {
     229             :       // Right now we can only handle Phi/EffectPhi nodes whose uses are
     230             :       // directly control-dependend on either the IfTrue or the IfFalse
     231             :       // successor, because we know exactly how to update those uses.
     232       15161 :       if (edge.from()->op()->ControlInputCount() != 1) return;
     233       13096 :       Node* control = NodeProperties::GetControlInput(edge.from());
     234       13096 :       if (NodeProperties::IsPhi(edge.from())) {
     235         801 :         control = NodeProperties::GetControlInput(control, edge.index());
     236             :       }
     237       13096 :       if (control != matcher.IfTrue() && control != matcher.IfFalse()) return;
     238             :     }
     239      100629 :     phis.push_back(use);
     240             :   }
     241      102335 :   BranchHint const hint = BranchHintOf(branch->op());
     242      102335 :   int const input_count = merge->op()->ControlInputCount();
     243             :   DCHECK_LE(1, input_count);
     244      102335 :   Node** const inputs = graph->zone()->NewArray<Node*>(2 * input_count);
     245             :   Node** const merge_true_inputs = &inputs[0];
     246      102335 :   Node** const merge_false_inputs = &inputs[input_count];
     247      506441 :   for (int index = 0; index < input_count; ++index) {
     248      404106 :     Node* cond1 = NodeProperties::GetValueInput(cond, index);
     249      404106 :     Node* control1 = NodeProperties::GetControlInput(merge, index);
     250      404106 :     Node* branch1 = graph->NewNode(common->Branch(hint), cond1, control1);
     251      808212 :     merge_true_inputs[index] = graph->NewNode(common->IfTrue(), branch1);
     252      808212 :     merge_false_inputs[index] = graph->NewNode(common->IfFalse(), branch1);
     253             :   }
     254      102335 :   Node* const merge_true = matcher.IfTrue();
     255      102335 :   Node* const merge_false = matcher.IfFalse();
     256      102335 :   merge_true->TrimInputCount(0);
     257      102335 :   merge_false->TrimInputCount(0);
     258      506441 :   for (int i = 0; i < input_count; ++i) {
     259      808212 :     merge_true->AppendInput(graph->zone(), merge_true_inputs[i]);
     260      808212 :     merge_false->AppendInput(graph->zone(), merge_false_inputs[i]);
     261             :   }
     262             :   DCHECK_EQ(2u, block->SuccessorCount());
     263      102335 :   NodeProperties::ChangeOp(matcher.IfTrue(), common->Merge(input_count));
     264      102335 :   NodeProperties::ChangeOp(matcher.IfFalse(), common->Merge(input_count));
     265             :   int const true_index =
     266      102335 :       block->SuccessorAt(0)->NodeAt(0) == matcher.IfTrue() ? 0 : 1;
     267             :   BlockEffectControlData* true_block_data =
     268      102335 :       &block_effects->For(block, block->SuccessorAt(true_index));
     269             :   BlockEffectControlData* false_block_data =
     270      102335 :       &block_effects->For(block, block->SuccessorAt(true_index ^ 1));
     271      607186 :   for (Node* const phi : phis) {
     272      500767 :     for (int index = 0; index < input_count; ++index) {
     273      800276 :       inputs[index] = phi->InputAt(index);
     274             :     }
     275      100629 :     inputs[input_count] = merge_true;
     276      201258 :     Node* phi_true = graph->NewNode(phi->op(), input_count + 1, inputs);
     277      100629 :     inputs[input_count] = merge_false;
     278      100629 :     Node* phi_false = graph->NewNode(phi->op(), input_count + 1, inputs);
     279      100629 :     if (phi->UseCount() == 0) {
     280             :       DCHECK_EQ(phi->opcode(), IrOpcode::kEffectPhi);
     281             :     } else {
     282       26931 :       for (Edge edge : phi->use_edges()) {
     283        9457 :         Node* control = NodeProperties::GetControlInput(edge.from());
     284       18914 :         if (NodeProperties::IsPhi(edge.from())) {
     285         783 :           control = NodeProperties::GetControlInput(control, edge.index());
     286             :         }
     287             :         DCHECK(control == matcher.IfTrue() || control == matcher.IfFalse());
     288        9457 :         edge.UpdateTo((control == matcher.IfTrue()) ? phi_true : phi_false);
     289             :       }
     290             :     }
     291      100629 :     if (phi->opcode() == IrOpcode::kEffectPhi) {
     292      100629 :       true_block_data->current_effect = phi_true;
     293      100629 :       false_block_data->current_effect = phi_false;
     294             :     }
     295      100629 :     phi->Kill();
     296             :   }
     297             :   // Fix up IfTrue and IfFalse and kill all dead nodes.
     298      102335 :   if (branch == block->control_input()) {
     299      102335 :     true_block_data->current_control = merge_true;
     300      102335 :     false_block_data->current_control = merge_false;
     301             :   }
     302      102335 :   branch->Kill();
     303      102335 :   cond->Kill();
     304      102335 :   merge->Kill();
     305             : }
     306             : }  // namespace
     307             : 
     308     9679446 : void EffectControlLinearizer::Run() {
     309             :   BlockEffectControlMap block_effects(temp_zone());
     310             :   ZoneVector<PendingEffectPhi> pending_effect_phis(temp_zone());
     311             :   ZoneVector<BasicBlock*> pending_block_controls(temp_zone());
     312             :   NodeVector inputs_buffer(temp_zone());
     313             : 
     314     5138945 :   for (BasicBlock* block : *(schedule()->rpo_order())) {
     315             :     size_t instr = 0;
     316             : 
     317             :     // The control node should be the first.
     318    11466535 :     Node* control = block->NodeAt(instr);
     319             :     DCHECK(NodeProperties::IsControl(control));
     320             :     // Update the control inputs.
     321     4252228 :     if (HasIncomingBackEdges(block)) {
     322             :       // If there are back edges, we need to update later because we have not
     323             :       // computed the control yet. This should only happen for loops.
     324             :       DCHECK_EQ(IrOpcode::kLoop, control->opcode());
     325       41665 :       pending_block_controls.push_back(block);
     326             :     } else {
     327             :       // If there are no back edges, we can update now.
     328     4210563 :       UpdateBlockControl(block, &block_effects);
     329             :     }
     330             :     instr++;
     331             : 
     332             :     // Iterate over the phis and update the effect phis.
     333     4252195 :     Node* effect = nullptr;
     334             :     Node* terminate = nullptr;
     335    10949218 :     for (; instr < block->NodeCount(); instr++) {
     336     3851975 :       Node* node = block->NodeAt(instr);
     337             :       // Only go through the phis and effect phis.
     338     3851975 :       if (node->opcode() == IrOpcode::kEffectPhi) {
     339             :         // There should be at most one effect phi in a block.
     340             :         DCHECK_NULL(effect);
     341             :         // IfException blocks should not have effect phis.
     342             :         DCHECK_NE(IrOpcode::kIfException, control->opcode());
     343      799397 :         effect = node;
     344             : 
     345             :         // Make sure we update the inputs to the incoming blocks' effects.
     346      799397 :         if (HasIncomingBackEdges(block)) {
     347             :           // In case of loops, we do not update the effect phi immediately
     348             :           // because the back predecessor has not been handled yet. We just
     349             :           // record the effect phi for later processing.
     350       41663 :           pending_effect_phis.push_back(PendingEffectPhi(node, block));
     351             :         } else {
     352      757734 :           UpdateEffectPhi(node, block, &block_effects);
     353             :         }
     354     3052578 :       } else if (node->opcode() == IrOpcode::kPhi) {
     355             :         // Just skip phis.
     356     2669008 :       } else if (node->opcode() == IrOpcode::kTerminate) {
     357             :         DCHECK_NULL(terminate);
     358             :         terminate = node;
     359             :       } else {
     360             :         break;
     361             :       }
     362             :     }
     363             : 
     364     4252177 :     if (effect == nullptr) {
     365             :       // There was no effect phi.
     366             :       DCHECK(!HasIncomingBackEdges(block));
     367     3452820 :       if (block == schedule()->start()) {
     368             :         // Start block => effect is start.
     369             :         DCHECK_EQ(graph()->start(), control);
     370      443362 :         effect = graph()->start();
     371     8586806 :       } else if (control->opcode() == IrOpcode::kEnd) {
     372             :         // End block is just a dummy, no effect needed.
     373             :         DCHECK_EQ(BasicBlock::kNone, block->control());
     374             :         DCHECK_EQ(1u, block->size());
     375      441548 :         effect = nullptr;
     376             :       } else {
     377             :         // If all the predecessors have the same effect, we can use it as our
     378             :         // current effect.
     379             :         effect =
     380     2567893 :             block_effects.For(block->PredecessorAt(0), block).current_effect;
     381     5293850 :         for (size_t i = 1; i < block->PredecessorCount(); ++i) {
     382       91909 :           if (block_effects.For(block->PredecessorAt(i), block)
     383       91909 :                   .current_effect != effect) {
     384       12877 :             effect = nullptr;
     385       12877 :             break;
     386             :           }
     387             :         }
     388     2567890 :         if (effect == nullptr) {
     389             :           DCHECK_NE(IrOpcode::kIfException, control->opcode());
     390             :           // The input blocks do not have the same effect. We have
     391             :           // to create an effect phi node.
     392             :           inputs_buffer.clear();
     393       25754 :           inputs_buffer.resize(block->PredecessorCount(), jsgraph()->Dead());
     394       12877 :           inputs_buffer.push_back(control);
     395             :           effect = graph()->NewNode(
     396       12877 :               common()->EffectPhi(static_cast<int>(block->PredecessorCount())),
     397       64385 :               static_cast<int>(inputs_buffer.size()), &(inputs_buffer.front()));
     398             :           // For loops, we update the effect phi node later to break cycles.
     399       25754 :           if (control->opcode() == IrOpcode::kLoop) {
     400           0 :             pending_effect_phis.push_back(PendingEffectPhi(effect, block));
     401             :           } else {
     402       12877 :             UpdateEffectPhi(effect, block, &block_effects);
     403             :           }
     404     5110026 :         } else if (control->opcode() == IrOpcode::kIfException) {
     405             :           // The IfException is connected into the effect chain, so we need
     406             :           // to update the effect here.
     407      152833 :           NodeProperties::ReplaceEffectInput(control, effect);
     408      152833 :           effect = control;
     409             :         }
     410             :       }
     411             :     }
     412             : 
     413             :     // Fixup the Terminate node.
     414     4252157 :     if (terminate != nullptr) {
     415       39423 :       NodeProperties::ReplaceEffectInput(terminate, effect);
     416             :     }
     417             : 
     418             :     // The frame state at block entry is determined by the frame states leaving
     419             :     // all predecessors. In case there is no frame state dominating this block,
     420             :     // we can rely on a checkpoint being present before the next deoptimization.
     421             :     // TODO(mstarzinger): Eventually we will need to go hunt for a frame state
     422             :     // once deoptimizing nodes roam freely through the schedule.
     423     4252157 :     Node* frame_state = nullptr;
     424     4252157 :     if (block != schedule()->start()) {
     425             :       // If all the predecessors have the same effect, we can use it
     426             :       // as our current effect.
     427             :       frame_state =
     428     3808837 :           block_effects.For(block->PredecessorAt(0), block).current_frame_state;
     429     9577786 :       for (size_t i = 1; i < block->PredecessorCount(); i++) {
     430     1136564 :         if (block_effects.For(block->PredecessorAt(i), block)
     431     1136564 :                 .current_frame_state != frame_state) {
     432      156508 :           frame_state = nullptr;
     433      156508 :           frame_state_zapper_ = graph()->end();
     434      156508 :           break;
     435             :         }
     436             :       }
     437             :     }
     438             : 
     439             :     // Process the ordinary instructions.
     440    68743269 :     for (; instr < block->NodeCount(); instr++) {
     441             :       Node* node = block->NodeAt(instr);
     442    32245569 :       ProcessNode(node, &frame_state, &effect, &control);
     443             :     }
     444             : 
     445     4252148 :     switch (block->control()) {
     446             :       case BasicBlock::kGoto:
     447             :       case BasicBlock::kNone:
     448             :         break;
     449             : 
     450             :       case BasicBlock::kCall:
     451             :       case BasicBlock::kTailCall:
     452             :       case BasicBlock::kSwitch:
     453             :       case BasicBlock::kReturn:
     454             :       case BasicBlock::kDeoptimize:
     455             :       case BasicBlock::kThrow:
     456      812402 :         ProcessNode(block->control_input(), &frame_state, &effect, &control);
     457      812406 :         break;
     458             : 
     459             :       case BasicBlock::kBranch:
     460     1074877 :         ProcessNode(block->control_input(), &frame_state, &effect, &control);
     461             :         TryCloneBranch(block->control_input(), block, temp_zone(), graph(),
     462     3224640 :                        common(), &block_effects, source_positions_);
     463     1074882 :         break;
     464             :     }
     465             : 
     466             :     // Store the effect, control and frame state for later use.
     467    17810495 :     for (BasicBlock* successor : block->successors()) {
     468     5053948 :       BlockEffectControlData* data = &block_effects.For(block, successor);
     469     5054024 :       if (data->current_effect == nullptr) {
     470     4852757 :         data->current_effect = effect;
     471             :       }
     472     5054024 :       if (data->current_control == nullptr) {
     473     4849351 :         data->current_control = control;
     474             :       }
     475     5054024 :       data->current_frame_state = frame_state;
     476             :     }
     477             :   }
     478             : 
     479             :   // Update the incoming edges of the effect phis that could not be processed
     480             :   // during the first pass (because they could have incoming back edges).
     481      928385 :   for (const PendingEffectPhi& pending_effect_phi : pending_effect_phis) {
     482             :     UpdateEffectPhi(pending_effect_phi.effect_phi, pending_effect_phi.block,
     483       41662 :                     &block_effects);
     484             :   }
     485      928387 :   for (BasicBlock* pending_block_control : pending_block_controls) {
     486       41663 :     UpdateBlockControl(pending_block_control, &block_effects);
     487             :   }
     488      443362 : }
     489             : 
     490   145273199 : void EffectControlLinearizer::ProcessNode(Node* node, Node** frame_state,
     491             :                                           Node** effect, Node** control) {
     492             :   SourcePositionTable::Scope scope(source_positions_,
     493    34132756 :                                    source_positions_->GetSourcePosition(node));
     494             : 
     495             :   // If the node needs to be wired into the effect/control chain, do this
     496             :   // here. Pass current frame state for lowering to eager deoptimization.
     497    34132795 :   if (TryWireInStateEffect(node, *frame_state, effect, control)) {
     498             :     return;
     499             :   }
     500             : 
     501             :   // If the node has a visible effect, then there must be a checkpoint in the
     502             :   // effect chain before we are allowed to place another eager deoptimization
     503             :   // point. We zap the frame state to ensure this invariant is maintained.
     504    65708700 :   if (region_observability_ == RegionObservability::kObservable &&
     505             :       !node->op()->HasProperty(Operator::kNoWrite)) {
     506     3358894 :     *frame_state = nullptr;
     507     3358894 :     frame_state_zapper_ = node;
     508             :   }
     509             : 
     510             :   // Remove the end markers of 'atomic' allocation region because the
     511             :   // region should be wired-in now.
     512    33254423 :   if (node->opcode() == IrOpcode::kFinishRegion) {
     513             :     // Reset the current region observability.
     514      111808 :     region_observability_ = RegionObservability::kObservable;
     515             :     // Update the value uses to the value input of the finish node and
     516             :     // the effect uses to the effect input.
     517      111808 :     return RemoveRegionNode(node);
     518             :   }
     519    33142615 :   if (node->opcode() == IrOpcode::kBeginRegion) {
     520             :     // Determine the observability for this region and use that for all
     521             :     // nodes inside the region (i.e. ignore the absence of kNoWrite on
     522             :     // StoreField and other operators).
     523             :     DCHECK_NE(RegionObservability::kNotObservable, region_observability_);
     524      111808 :     region_observability_ = RegionObservabilityOf(node->op());
     525             :     // Update the value uses to the value input of the finish node and
     526             :     // the effect uses to the effect input.
     527      111808 :     return RemoveRegionNode(node);
     528             :   }
     529             : 
     530             :   // Special treatment for checkpoint nodes.
     531    33030807 :   if (node->opcode() == IrOpcode::kCheckpoint) {
     532             :     // Unlink the check point; effect uses will be updated to the incoming
     533             :     // effect that is passed. The frame state is preserved for lowering.
     534             :     DCHECK_EQ(RegionObservability::kObservable, region_observability_);
     535     2508403 :     *frame_state = NodeProperties::GetFrameStateInput(node);
     536     2508399 :     return;
     537             :   }
     538             : 
     539             :   // The IfSuccess nodes should always start a basic block (and basic block
     540             :   // start nodes are not handled in the ProcessNode method).
     541             :   DCHECK_NE(IrOpcode::kIfSuccess, node->opcode());
     542             : 
     543             :   // If the node takes an effect, replace with the current one.
     544    61044808 :   if (node->op()->EffectInputCount() > 0) {
     545             :     DCHECK_EQ(1, node->op()->EffectInputCount());
     546     7246709 :     Node* input_effect = NodeProperties::GetEffectInput(node);
     547             : 
     548     7246704 :     if (input_effect != *effect) {
     549     2499861 :       NodeProperties::ReplaceEffectInput(node, *effect);
     550             :     }
     551             : 
     552             :     // If the node produces an effect, update our current effect. (However,
     553             :     // ignore new effect chains started with ValueEffect.)
     554    14493370 :     if (node->op()->EffectOutputCount() > 0) {
     555             :       DCHECK_EQ(1, node->op()->EffectOutputCount());
     556     6593947 :       *effect = node;
     557             :     }
     558             :   } else {
     559             :     // New effect chain is only started with a Start or ValueEffect node.
     560             :     DCHECK(node->op()->EffectOutputCount() == 0 ||
     561             :            node->opcode() == IrOpcode::kStart);
     562             :   }
     563             : 
     564             :   // Rewire control inputs.
     565    84032794 :   for (int i = 0; i < node->op()->ControlInputCount(); i++) {
     566     7662682 :     NodeProperties::ReplaceControlInput(node, *control, i);
     567             :   }
     568             :   // Update the current control.
     569    61044752 :   if (node->op()->ControlOutputCount() > 0) {
     570     4442063 :     *control = node;
     571             :   }
     572             : }
     573             : 
     574    69143975 : bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
     575             :                                                    Node* frame_state,
     576             :                                                    Node** effect,
     577             :                                                    Node** control) {
     578    34132773 :   gasm()->Reset(*effect, *control);
     579             :   Node* result = nullptr;
     580    34132778 :   switch (node->opcode()) {
     581             :     case IrOpcode::kChangeBitToTagged:
     582       10166 :       result = LowerChangeBitToTagged(node);
     583       10166 :       break;
     584             :     case IrOpcode::kChangeInt31ToTaggedSigned:
     585       14631 :       result = LowerChangeInt31ToTaggedSigned(node);
     586       14631 :       break;
     587             :     case IrOpcode::kChangeInt32ToTagged:
     588       49816 :       result = LowerChangeInt32ToTagged(node);
     589       49813 :       break;
     590             :     case IrOpcode::kChangeUint32ToTagged:
     591         532 :       result = LowerChangeUint32ToTagged(node);
     592         532 :       break;
     593             :     case IrOpcode::kChangeFloat64ToTagged:
     594       40024 :       result = LowerChangeFloat64ToTagged(node);
     595       40024 :       break;
     596             :     case IrOpcode::kChangeFloat64ToTaggedPointer:
     597          66 :       result = LowerChangeFloat64ToTaggedPointer(node);
     598          66 :       break;
     599             :     case IrOpcode::kChangeTaggedSignedToInt32:
     600       61723 :       result = LowerChangeTaggedSignedToInt32(node);
     601       61723 :       break;
     602             :     case IrOpcode::kChangeTaggedToBit:
     603      132688 :       result = LowerChangeTaggedToBit(node);
     604      132688 :       break;
     605             :     case IrOpcode::kChangeTaggedToInt32:
     606        5394 :       result = LowerChangeTaggedToInt32(node);
     607        5394 :       break;
     608             :     case IrOpcode::kChangeTaggedToUint32:
     609         231 :       result = LowerChangeTaggedToUint32(node);
     610         231 :       break;
     611             :     case IrOpcode::kChangeTaggedToFloat64:
     612             :       result = LowerChangeTaggedToFloat64(node);
     613       21777 :       break;
     614             :     case IrOpcode::kChangeTaggedToTaggedSigned:
     615           8 :       result = LowerChangeTaggedToTaggedSigned(node);
     616           8 :       break;
     617             :     case IrOpcode::kTruncateTaggedToBit:
     618       54876 :       result = LowerTruncateTaggedToBit(node);
     619       54876 :       break;
     620             :     case IrOpcode::kTruncateTaggedPointerToBit:
     621         381 :       result = LowerTruncateTaggedPointerToBit(node);
     622         381 :       break;
     623             :     case IrOpcode::kTruncateTaggedToFloat64:
     624         425 :       result = LowerTruncateTaggedToFloat64(node);
     625         425 :       break;
     626             :     case IrOpcode::kCheckBounds:
     627       25145 :       result = LowerCheckBounds(node, frame_state);
     628       25145 :       break;
     629             :     case IrOpcode::kCheckMaps:
     630       51650 :       LowerCheckMaps(node, frame_state);
     631       51650 :       break;
     632             :     case IrOpcode::kCompareMaps:
     633        8998 :       result = LowerCompareMaps(node);
     634        8998 :       break;
     635             :     case IrOpcode::kCheckNumber:
     636         381 :       result = LowerCheckNumber(node, frame_state);
     637         381 :       break;
     638             :     case IrOpcode::kCheckReceiver:
     639         855 :       result = LowerCheckReceiver(node, frame_state);
     640         855 :       break;
     641             :     case IrOpcode::kCheckSymbol:
     642           0 :       result = LowerCheckSymbol(node, frame_state);
     643           0 :       break;
     644             :     case IrOpcode::kCheckString:
     645        1770 :       result = LowerCheckString(node, frame_state);
     646        1770 :       break;
     647             :     case IrOpcode::kCheckSeqString:
     648        1113 :       result = LowerCheckSeqString(node, frame_state);
     649        1113 :       break;
     650             :     case IrOpcode::kCheckInternalizedString:
     651        1699 :       result = LowerCheckInternalizedString(node, frame_state);
     652        1699 :       break;
     653             :     case IrOpcode::kCheckIf:
     654       28990 :       LowerCheckIf(node, frame_state);
     655       28990 :       break;
     656             :     case IrOpcode::kCheckedInt32Add:
     657       42139 :       result = LowerCheckedInt32Add(node, frame_state);
     658       42139 :       break;
     659             :     case IrOpcode::kCheckedInt32Sub:
     660       35241 :       result = LowerCheckedInt32Sub(node, frame_state);
     661       35241 :       break;
     662             :     case IrOpcode::kCheckedInt32Div:
     663         230 :       result = LowerCheckedInt32Div(node, frame_state);
     664         230 :       break;
     665             :     case IrOpcode::kCheckedInt32Mod:
     666         895 :       result = LowerCheckedInt32Mod(node, frame_state);
     667         895 :       break;
     668             :     case IrOpcode::kCheckedUint32Div:
     669          55 :       result = LowerCheckedUint32Div(node, frame_state);
     670          55 :       break;
     671             :     case IrOpcode::kCheckedUint32Mod:
     672          42 :       result = LowerCheckedUint32Mod(node, frame_state);
     673          42 :       break;
     674             :     case IrOpcode::kCheckedInt32Mul:
     675        5830 :       result = LowerCheckedInt32Mul(node, frame_state);
     676        5830 :       break;
     677             :     case IrOpcode::kCheckedInt32ToTaggedSigned:
     678           0 :       result = LowerCheckedInt32ToTaggedSigned(node, frame_state);
     679           0 :       break;
     680             :     case IrOpcode::kCheckedUint32ToInt32:
     681         433 :       result = LowerCheckedUint32ToInt32(node, frame_state);
     682         433 :       break;
     683             :     case IrOpcode::kCheckedUint32ToTaggedSigned:
     684          24 :       result = LowerCheckedUint32ToTaggedSigned(node, frame_state);
     685          24 :       break;
     686             :     case IrOpcode::kCheckedFloat64ToInt32:
     687        4638 :       result = LowerCheckedFloat64ToInt32(node, frame_state);
     688        4638 :       break;
     689             :     case IrOpcode::kCheckedTaggedSignedToInt32:
     690       25490 :       if (frame_state == nullptr) {
     691             :         V8_Fatal(__FILE__, __LINE__, "No frame state (zapped by #%d: %s)",
     692             :                  frame_state_zapper_->id(),
     693           0 :                  frame_state_zapper_->op()->mnemonic());
     694             :       }
     695       25490 :       result = LowerCheckedTaggedSignedToInt32(node, frame_state);
     696       25491 :       break;
     697             :     case IrOpcode::kCheckedTaggedToInt32:
     698        2873 :       result = LowerCheckedTaggedToInt32(node, frame_state);
     699        2873 :       break;
     700             :     case IrOpcode::kCheckedTaggedToFloat64:
     701       20711 :       result = LowerCheckedTaggedToFloat64(node, frame_state);
     702       20711 :       break;
     703             :     case IrOpcode::kCheckedTaggedToTaggedSigned:
     704       27080 :       result = LowerCheckedTaggedToTaggedSigned(node, frame_state);
     705       27080 :       break;
     706             :     case IrOpcode::kCheckedTaggedToTaggedPointer:
     707       28657 :       result = LowerCheckedTaggedToTaggedPointer(node, frame_state);
     708       28657 :       break;
     709             :     case IrOpcode::kTruncateTaggedToWord32:
     710         927 :       result = LowerTruncateTaggedToWord32(node);
     711         927 :       break;
     712             :     case IrOpcode::kCheckedTruncateTaggedToWord32:
     713        2436 :       result = LowerCheckedTruncateTaggedToWord32(node, frame_state);
     714        2436 :       break;
     715             :     case IrOpcode::kObjectIsArrayBufferView:
     716           0 :       result = LowerObjectIsArrayBufferView(node);
     717           0 :       break;
     718             :     case IrOpcode::kObjectIsCallable:
     719          10 :       result = LowerObjectIsCallable(node);
     720          10 :       break;
     721             :     case IrOpcode::kObjectIsConstructor:
     722         160 :       result = LowerObjectIsConstructor(node);
     723         160 :       break;
     724             :     case IrOpcode::kObjectIsDetectableCallable:
     725       11027 :       result = LowerObjectIsDetectableCallable(node);
     726       11027 :       break;
     727             :     case IrOpcode::kObjectIsMinusZero:
     728          14 :       result = LowerObjectIsMinusZero(node);
     729          14 :       break;
     730             :     case IrOpcode::kObjectIsNaN:
     731         534 :       result = LowerObjectIsNaN(node);
     732         534 :       break;
     733             :     case IrOpcode::kObjectIsNonCallable:
     734        5284 :       result = LowerObjectIsNonCallable(node);
     735        5284 :       break;
     736             :     case IrOpcode::kObjectIsNumber:
     737        7693 :       result = LowerObjectIsNumber(node);
     738        7693 :       break;
     739             :     case IrOpcode::kObjectIsReceiver:
     740       18113 :       result = LowerObjectIsReceiver(node);
     741       18113 :       break;
     742             :     case IrOpcode::kObjectIsSmi:
     743        6382 :       result = LowerObjectIsSmi(node);
     744        6382 :       break;
     745             :     case IrOpcode::kObjectIsString:
     746        2380 :       result = LowerObjectIsString(node);
     747        2380 :       break;
     748             :     case IrOpcode::kObjectIsSymbol:
     749         134 :       result = LowerObjectIsSymbol(node);
     750         134 :       break;
     751             :     case IrOpcode::kObjectIsUndetectable:
     752        5469 :       result = LowerObjectIsUndetectable(node);
     753        5469 :       break;
     754             :     case IrOpcode::kArgumentsFrame:
     755       15826 :       result = LowerArgumentsFrame(node);
     756       15826 :       break;
     757             :     case IrOpcode::kArgumentsLength:
     758       15855 :       result = LowerArgumentsLength(node);
     759       15855 :       break;
     760             :     case IrOpcode::kToBoolean:
     761         580 :       result = LowerToBoolean(node);
     762         580 :       break;
     763             :     case IrOpcode::kTypeOf:
     764       20286 :       result = LowerTypeOf(node);
     765       20286 :       break;
     766             :     case IrOpcode::kClassOf:
     767         966 :       result = LowerClassOf(node);
     768         966 :       break;
     769             :     case IrOpcode::kNewDoubleElements:
     770          32 :       result = LowerNewDoubleElements(node);
     771          32 :       break;
     772             :     case IrOpcode::kNewSmiOrObjectElements:
     773         322 :       result = LowerNewSmiOrObjectElements(node);
     774         322 :       break;
     775             :     case IrOpcode::kNewArgumentsElements:
     776       15111 :       result = LowerNewArgumentsElements(node);
     777       15111 :       break;
     778             :     case IrOpcode::kArrayBufferWasNeutered:
     779         544 :       result = LowerArrayBufferWasNeutered(node);
     780         544 :       break;
     781             :     case IrOpcode::kStringFromCharCode:
     782         203 :       result = LowerStringFromCharCode(node);
     783         203 :       break;
     784             :     case IrOpcode::kStringFromCodePoint:
     785          39 :       result = LowerStringFromCodePoint(node);
     786          39 :       break;
     787             :     case IrOpcode::kStringIndexOf:
     788         195 :       result = LowerStringIndexOf(node);
     789         195 :       break;
     790             :     case IrOpcode::kStringToNumber:
     791         183 :       result = LowerStringToNumber(node);
     792         183 :       break;
     793             :     case IrOpcode::kStringCharAt:
     794         302 :       result = LowerStringCharAt(node);
     795         302 :       break;
     796             :     case IrOpcode::kStringCharCodeAt:
     797         147 :       result = LowerStringCharCodeAt(node);
     798         147 :       break;
     799             :     case IrOpcode::kSeqStringCharCodeAt:
     800         410 :       result = LowerSeqStringCharCodeAt(node);
     801         410 :       break;
     802             :     case IrOpcode::kStringToLowerCaseIntl:
     803           0 :       result = LowerStringToLowerCaseIntl(node);
     804           0 :       break;
     805             :     case IrOpcode::kStringToUpperCaseIntl:
     806           0 :       result = LowerStringToUpperCaseIntl(node);
     807           0 :       break;
     808             :     case IrOpcode::kStringEqual:
     809        5673 :       result = LowerStringEqual(node);
     810        5673 :       break;
     811             :     case IrOpcode::kStringLessThan:
     812         516 :       result = LowerStringLessThan(node);
     813         516 :       break;
     814             :     case IrOpcode::kStringLessThanOrEqual:
     815         311 :       result = LowerStringLessThanOrEqual(node);
     816         311 :       break;
     817             :     case IrOpcode::kCheckFloat64Hole:
     818         626 :       result = LowerCheckFloat64Hole(node, frame_state);
     819         626 :       break;
     820             :     case IrOpcode::kCheckNotTaggedHole:
     821        1087 :       result = LowerCheckNotTaggedHole(node, frame_state);
     822        1087 :       break;
     823             :     case IrOpcode::kConvertTaggedHoleToUndefined:
     824        1215 :       result = LowerConvertTaggedHoleToUndefined(node);
     825        1215 :       break;
     826             :     case IrOpcode::kCheckEqualsInternalizedString:
     827         102 :       LowerCheckEqualsInternalizedString(node, frame_state);
     828         102 :       break;
     829             :     case IrOpcode::kCheckEqualsSymbol:
     830          62 :       LowerCheckEqualsSymbol(node, frame_state);
     831          62 :       break;
     832             :     case IrOpcode::kPlainPrimitiveToNumber:
     833          36 :       result = LowerPlainPrimitiveToNumber(node);
     834          36 :       break;
     835             :     case IrOpcode::kPlainPrimitiveToWord32:
     836         192 :       result = LowerPlainPrimitiveToWord32(node);
     837         192 :       break;
     838             :     case IrOpcode::kPlainPrimitiveToFloat64:
     839        9090 :       result = LowerPlainPrimitiveToFloat64(node);
     840        9090 :       break;
     841             :     case IrOpcode::kEnsureWritableFastElements:
     842         351 :       result = LowerEnsureWritableFastElements(node);
     843         351 :       break;
     844             :     case IrOpcode::kMaybeGrowFastElements:
     845        2956 :       result = LowerMaybeGrowFastElements(node, frame_state);
     846        2956 :       break;
     847             :     case IrOpcode::kTransitionElementsKind:
     848         569 :       LowerTransitionElementsKind(node);
     849         569 :       break;
     850             :     case IrOpcode::kLoadFieldByIndex:
     851        2119 :       result = LowerLoadFieldByIndex(node);
     852        2119 :       break;
     853             :     case IrOpcode::kLoadTypedElement:
     854        6159 :       result = LowerLoadTypedElement(node);
     855        6159 :       break;
     856             :     case IrOpcode::kStoreTypedElement:
     857        6033 :       LowerStoreTypedElement(node);
     858        6033 :       break;
     859             :     case IrOpcode::kStoreSignedSmallElement:
     860          61 :       LowerStoreSignedSmallElement(node);
     861          61 :       break;
     862             :     case IrOpcode::kFindOrderedHashMapEntry:
     863           8 :       result = LowerFindOrderedHashMapEntry(node);
     864           8 :       break;
     865             :     case IrOpcode::kFindOrderedHashMapEntryForInt32Key:
     866           0 :       result = LowerFindOrderedHashMapEntryForInt32Key(node);
     867           0 :       break;
     868             :     case IrOpcode::kTransitionAndStoreNumberElement:
     869          20 :       LowerTransitionAndStoreNumberElement(node);
     870          20 :       break;
     871             :     case IrOpcode::kTransitionAndStoreNonNumberElement:
     872           6 :       LowerTransitionAndStoreNonNumberElement(node);
     873           6 :       break;
     874             :     case IrOpcode::kTransitionAndStoreElement:
     875          70 :       LowerTransitionAndStoreElement(node);
     876          70 :       break;
     877             :     case IrOpcode::kRuntimeAbort:
     878        1920 :       LowerRuntimeAbort(node);
     879        1920 :       break;
     880             :     case IrOpcode::kFloat64RoundUp:
     881       10936 :       if (!LowerFloat64RoundUp(node).To(&result)) {
     882             :         return false;
     883             :       }
     884             :       break;
     885             :     case IrOpcode::kFloat64RoundDown:
     886       16748 :       if (!LowerFloat64RoundDown(node).To(&result)) {
     887             :         return false;
     888             :       }
     889             :       break;
     890             :     case IrOpcode::kFloat64RoundTruncate:
     891        2674 :       if (!LowerFloat64RoundTruncate(node).To(&result)) {
     892             :         return false;
     893             :       }
     894             :       break;
     895             :     case IrOpcode::kFloat64RoundTiesEven:
     896         650 :       if (!LowerFloat64RoundTiesEven(node).To(&result)) {
     897             :         return false;
     898             :       }
     899             :       break;
     900             :     default:
     901             :       return false;
     902             :   }
     903             : 
     904     2635272 :   if ((result ? 1 : 0) != node->op()->ValueOutputCount()) {
     905             :     V8_Fatal(__FILE__, __LINE__,
     906             :              "Effect control linearizer lowering of '%s':"
     907             :              " value output count does not agree.",
     908           0 :              node->op()->mnemonic());
     909             :   }
     910             : 
     911      878424 :   *effect = gasm()->ExtractCurrentEffect();
     912      878427 :   *control = gasm()->ExtractCurrentControl();
     913      878430 :   NodeProperties::ReplaceUses(node, result, *effect, *control);
     914      878433 :   return true;
     915             : }
     916             : 
     917             : #define __ gasm()->
     918             : 
     919       40023 : Node* EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node) {
     920       40023 :   CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
     921             :   Node* value = node->InputAt(0);
     922             : 
     923       40023 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
     924       40023 :   auto if_heapnumber = __ MakeDeferredLabel();
     925       40023 :   auto if_int32 = __ MakeLabel();
     926             : 
     927       40023 :   Node* value32 = __ RoundFloat64ToInt32(value);
     928             :   __ GotoIf(__ Float64Equal(value, __ ChangeInt32ToFloat64(value32)),
     929       40025 :             &if_int32);
     930             :   __ Goto(&if_heapnumber);
     931             : 
     932             :   __ Bind(&if_int32);
     933             :   {
     934       40024 :     if (mode == CheckForMinusZeroMode::kCheckForMinusZero) {
     935       21459 :       Node* zero = __ Int32Constant(0);
     936       21460 :       auto if_zero = __ MakeDeferredLabel();
     937       21460 :       auto if_smi = __ MakeLabel();
     938             : 
     939       21460 :       __ GotoIf(__ Word32Equal(value32, zero), &if_zero);
     940             :       __ Goto(&if_smi);
     941             : 
     942             :       __ Bind(&if_zero);
     943             :       {
     944             :         // In case of 0, we need to check the high bits for the IEEE -0 pattern.
     945             :         __ GotoIf(__ Int32LessThan(__ Float64ExtractHighWord32(value), zero),
     946       21459 :                   &if_heapnumber);
     947             :         __ Goto(&if_smi);
     948             :       }
     949             : 
     950             :       __ Bind(&if_smi);
     951             :     }
     952             : 
     953       40025 :     if (machine()->Is64()) {
     954       40025 :       Node* value_smi = ChangeInt32ToSmi(value32);
     955             :       __ Goto(&done, value_smi);
     956             :     } else {
     957           0 :       Node* add = __ Int32AddWithOverflow(value32, value32);
     958           0 :       Node* ovf = __ Projection(1, add);
     959           0 :       __ GotoIf(ovf, &if_heapnumber);
     960           0 :       Node* value_smi = __ Projection(0, add);
     961             :       __ Goto(&done, value_smi);
     962             :     }
     963             :   }
     964             : 
     965             :   __ Bind(&if_heapnumber);
     966             :   {
     967       40025 :     Node* value_number = AllocateHeapNumberWithValue(value);
     968             :     __ Goto(&done, value_number);
     969             :   }
     970             : 
     971             :   __ Bind(&done);
     972       40025 :   return done.PhiAt(0);
     973             : }
     974             : 
     975          66 : Node* EffectControlLinearizer::LowerChangeFloat64ToTaggedPointer(Node* node) {
     976             :   Node* value = node->InputAt(0);
     977          66 :   return AllocateHeapNumberWithValue(value);
     978             : }
     979             : 
     980       10166 : Node* EffectControlLinearizer::LowerChangeBitToTagged(Node* node) {
     981             :   Node* value = node->InputAt(0);
     982             : 
     983       10166 :   auto if_true = __ MakeLabel();
     984       10166 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
     985             : 
     986       10166 :   __ GotoIf(value, &if_true);
     987       10166 :   __ Goto(&done, __ FalseConstant());
     988             : 
     989             :   __ Bind(&if_true);
     990       10166 :   __ Goto(&done, __ TrueConstant());
     991             : 
     992             :   __ Bind(&done);
     993       10166 :   return done.PhiAt(0);
     994             : }
     995             : 
     996       14631 : Node* EffectControlLinearizer::LowerChangeInt31ToTaggedSigned(Node* node) {
     997             :   Node* value = node->InputAt(0);
     998       14631 :   return ChangeInt32ToSmi(value);
     999             : }
    1000             : 
    1001       49814 : Node* EffectControlLinearizer::LowerChangeInt32ToTagged(Node* node) {
    1002             :   Node* value = node->InputAt(0);
    1003             : 
    1004       49814 :   if (machine()->Is64()) {
    1005       49814 :     return ChangeInt32ToSmi(value);
    1006             :   }
    1007             : 
    1008           0 :   auto if_overflow = __ MakeDeferredLabel();
    1009           0 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    1010             : 
    1011           0 :   Node* add = __ Int32AddWithOverflow(value, value);
    1012           0 :   Node* ovf = __ Projection(1, add);
    1013           0 :   __ GotoIf(ovf, &if_overflow);
    1014           0 :   __ Goto(&done, __ Projection(0, add));
    1015             : 
    1016             :   __ Bind(&if_overflow);
    1017           0 :   Node* number = AllocateHeapNumberWithValue(__ ChangeInt32ToFloat64(value));
    1018             :   __ Goto(&done, number);
    1019             : 
    1020             :   __ Bind(&done);
    1021             :   return done.PhiAt(0);
    1022             : }
    1023             : 
    1024         532 : Node* EffectControlLinearizer::LowerChangeUint32ToTagged(Node* node) {
    1025             :   Node* value = node->InputAt(0);
    1026             : 
    1027         532 :   auto if_not_in_smi_range = __ MakeDeferredLabel();
    1028         532 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    1029             : 
    1030         532 :   Node* check = __ Uint32LessThanOrEqual(value, SmiMaxValueConstant());
    1031         532 :   __ GotoIfNot(check, &if_not_in_smi_range);
    1032         532 :   __ Goto(&done, ChangeUint32ToSmi(value));
    1033             : 
    1034             :   __ Bind(&if_not_in_smi_range);
    1035         532 :   Node* number = AllocateHeapNumberWithValue(__ ChangeUint32ToFloat64(value));
    1036             : 
    1037             :   __ Goto(&done, number);
    1038             :   __ Bind(&done);
    1039             : 
    1040         532 :   return done.PhiAt(0);
    1041             : }
    1042             : 
    1043       61723 : Node* EffectControlLinearizer::LowerChangeTaggedSignedToInt32(Node* node) {
    1044             :   Node* value = node->InputAt(0);
    1045       61723 :   return ChangeSmiToInt32(value);
    1046             : }
    1047             : 
    1048      132688 : Node* EffectControlLinearizer::LowerChangeTaggedToBit(Node* node) {
    1049             :   Node* value = node->InputAt(0);
    1050      132688 :   return __ WordEqual(value, __ TrueConstant());
    1051             : }
    1052             : 
    1053       54876 : Node* EffectControlLinearizer::LowerTruncateTaggedToBit(Node* node) {
    1054             :   Node* value = node->InputAt(0);
    1055             : 
    1056       54876 :   auto if_smi = __ MakeDeferredLabel();
    1057       54876 :   auto if_heapnumber = __ MakeDeferredLabel();
    1058       54876 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    1059             : 
    1060       54876 :   Node* zero = __ Int32Constant(0);
    1061       54876 :   Node* fzero = __ Float64Constant(0.0);
    1062             : 
    1063             :   // Check if {value} is false.
    1064       54876 :   __ GotoIf(__ WordEqual(value, __ FalseConstant()), &done, zero);
    1065             : 
    1066             :   // Check if {value} is a Smi.
    1067       54876 :   Node* check_smi = ObjectIsSmi(value);
    1068       54876 :   __ GotoIf(check_smi, &if_smi);
    1069             : 
    1070             :   // Check if {value} is the empty string.
    1071       54876 :   __ GotoIf(__ WordEqual(value, __ EmptyStringConstant()), &done, zero);
    1072             : 
    1073             :   // Load the map of {value}.
    1074       54876 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1075             : 
    1076             :   // Check if the {value} is undetectable and immediately return false.
    1077             :   Node* value_map_bitfield =
    1078       54876 :       __ LoadField(AccessBuilder::ForMapBitField(), value_map);
    1079             :   __ GotoIfNot(
    1080             :       __ Word32Equal(__ Word32And(value_map_bitfield,
    1081             :                                   __ Int32Constant(1 << Map::kIsUndetectable)),
    1082             :                      zero),
    1083       54876 :       &done, zero);
    1084             : 
    1085             :   // Check if {value} is a HeapNumber.
    1086             :   __ GotoIf(__ WordEqual(value_map, __ HeapNumberMapConstant()),
    1087       54876 :             &if_heapnumber);
    1088             : 
    1089             :   // All other values that reach here are true.
    1090       54876 :   __ Goto(&done, __ Int32Constant(1));
    1091             : 
    1092             :   __ Bind(&if_heapnumber);
    1093             :   {
    1094             :     // For HeapNumber {value}, just check that its value is not 0.0, -0.0 or
    1095             :     // NaN.
    1096             :     Node* value_value =
    1097       54876 :         __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1098       54876 :     __ Goto(&done, __ Float64LessThan(fzero, __ Float64Abs(value_value)));
    1099             :   }
    1100             : 
    1101             :   __ Bind(&if_smi);
    1102             :   {
    1103             :     // If {value} is a Smi, then we only need to check that it's not zero.
    1104             :     __ Goto(&done,
    1105       54876 :             __ Word32Equal(__ WordEqual(value, __ IntPtrConstant(0)), zero));
    1106             :   }
    1107             : 
    1108             :   __ Bind(&done);
    1109       54876 :   return done.PhiAt(0);
    1110             : }
    1111             : 
    1112         381 : Node* EffectControlLinearizer::LowerTruncateTaggedPointerToBit(Node* node) {
    1113             :   Node* value = node->InputAt(0);
    1114             : 
    1115         381 :   auto if_heapnumber = __ MakeDeferredLabel();
    1116         381 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    1117             : 
    1118         381 :   Node* zero = __ Int32Constant(0);
    1119         381 :   Node* fzero = __ Float64Constant(0.0);
    1120             : 
    1121             :   // Check if {value} is false.
    1122         381 :   __ GotoIf(__ WordEqual(value, __ FalseConstant()), &done, zero);
    1123             : 
    1124             :   // Check if {value} is the empty string.
    1125         381 :   __ GotoIf(__ WordEqual(value, __ EmptyStringConstant()), &done, zero);
    1126             : 
    1127             :   // Load the map of {value}.
    1128         381 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1129             : 
    1130             :   // Check if the {value} is undetectable and immediately return false.
    1131             :   Node* value_map_bitfield =
    1132         381 :       __ LoadField(AccessBuilder::ForMapBitField(), value_map);
    1133             :   __ GotoIfNot(
    1134             :       __ Word32Equal(__ Word32And(value_map_bitfield,
    1135             :                                   __ Int32Constant(1 << Map::kIsUndetectable)),
    1136             :                      zero),
    1137         381 :       &done, zero);
    1138             : 
    1139             :   // Check if {value} is a HeapNumber.
    1140             :   __ GotoIf(__ WordEqual(value_map, __ HeapNumberMapConstant()),
    1141         381 :             &if_heapnumber);
    1142             : 
    1143             :   // All other values that reach here are true.
    1144         381 :   __ Goto(&done, __ Int32Constant(1));
    1145             : 
    1146             :   __ Bind(&if_heapnumber);
    1147             :   {
    1148             :     // For HeapNumber {value}, just check that its value is not 0.0, -0.0 or
    1149             :     // NaN.
    1150             :     Node* value_value =
    1151         381 :         __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1152         381 :     __ Goto(&done, __ Float64LessThan(fzero, __ Float64Abs(value_value)));
    1153             :   }
    1154             : 
    1155             :   __ Bind(&done);
    1156         381 :   return done.PhiAt(0);
    1157             : }
    1158             : 
    1159        5394 : Node* EffectControlLinearizer::LowerChangeTaggedToInt32(Node* node) {
    1160             :   Node* value = node->InputAt(0);
    1161             : 
    1162        5394 :   auto if_not_smi = __ MakeDeferredLabel();
    1163        5394 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    1164             : 
    1165        5394 :   Node* check = ObjectIsSmi(value);
    1166        5394 :   __ GotoIfNot(check, &if_not_smi);
    1167        5394 :   __ Goto(&done, ChangeSmiToInt32(value));
    1168             : 
    1169             :   __ Bind(&if_not_smi);
    1170             :   STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    1171        5394 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1172        5394 :   vfalse = __ ChangeFloat64ToInt32(vfalse);
    1173             :   __ Goto(&done, vfalse);
    1174             : 
    1175             :   __ Bind(&done);
    1176        5394 :   return done.PhiAt(0);
    1177             : }
    1178             : 
    1179         231 : Node* EffectControlLinearizer::LowerChangeTaggedToUint32(Node* node) {
    1180             :   Node* value = node->InputAt(0);
    1181             : 
    1182         231 :   auto if_not_smi = __ MakeDeferredLabel();
    1183         231 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    1184             : 
    1185         231 :   Node* check = ObjectIsSmi(value);
    1186         231 :   __ GotoIfNot(check, &if_not_smi);
    1187         231 :   __ Goto(&done, ChangeSmiToInt32(value));
    1188             : 
    1189             :   __ Bind(&if_not_smi);
    1190             :   STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    1191         231 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1192         231 :   vfalse = __ ChangeFloat64ToUint32(vfalse);
    1193             :   __ Goto(&done, vfalse);
    1194             : 
    1195             :   __ Bind(&done);
    1196         231 :   return done.PhiAt(0);
    1197             : }
    1198             : 
    1199           0 : Node* EffectControlLinearizer::LowerChangeTaggedToFloat64(Node* node) {
    1200       21777 :   return LowerTruncateTaggedToFloat64(node);
    1201             : }
    1202             : 
    1203           8 : Node* EffectControlLinearizer::LowerChangeTaggedToTaggedSigned(Node* node) {
    1204             :   Node* value = node->InputAt(0);
    1205             : 
    1206           8 :   auto if_not_smi = __ MakeDeferredLabel();
    1207           8 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    1208             : 
    1209           8 :   Node* check = ObjectIsSmi(value);
    1210           8 :   __ GotoIfNot(check, &if_not_smi);
    1211             :   __ Goto(&done, value);
    1212             : 
    1213             :   __ Bind(&if_not_smi);
    1214             :   STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    1215           8 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1216           8 :   vfalse = __ ChangeFloat64ToInt32(vfalse);
    1217           8 :   vfalse = ChangeInt32ToSmi(vfalse);
    1218             :   __ Goto(&done, vfalse);
    1219             : 
    1220             :   __ Bind(&done);
    1221           8 :   return done.PhiAt(0);
    1222             : }
    1223             : 
    1224       22202 : Node* EffectControlLinearizer::LowerTruncateTaggedToFloat64(Node* node) {
    1225             :   Node* value = node->InputAt(0);
    1226             : 
    1227       22202 :   auto if_not_smi = __ MakeDeferredLabel();
    1228       22202 :   auto done = __ MakeLabel(MachineRepresentation::kFloat64);
    1229             : 
    1230       22202 :   Node* check = ObjectIsSmi(value);
    1231       22202 :   __ GotoIfNot(check, &if_not_smi);
    1232       22202 :   Node* vtrue = ChangeSmiToInt32(value);
    1233       22202 :   vtrue = __ ChangeInt32ToFloat64(vtrue);
    1234             :   __ Goto(&done, vtrue);
    1235             : 
    1236             :   __ Bind(&if_not_smi);
    1237             :   STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    1238       22202 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1239             :   __ Goto(&done, vfalse);
    1240             : 
    1241             :   __ Bind(&done);
    1242       22202 :   return done.PhiAt(0);
    1243             : }
    1244             : 
    1245       25145 : Node* EffectControlLinearizer::LowerCheckBounds(Node* node, Node* frame_state) {
    1246             :   Node* index = node->InputAt(0);
    1247             :   Node* limit = node->InputAt(1);
    1248             : 
    1249       25145 :   Node* check = __ Uint32LessThan(index, limit);
    1250       25145 :   __ DeoptimizeIfNot(DeoptimizeReason::kOutOfBounds, check, frame_state);
    1251       25145 :   return index;
    1252             : }
    1253             : 
    1254       51650 : void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
    1255       51650 :   CheckMapsParameters const& p = CheckMapsParametersOf(node->op());
    1256             :   Node* value = node->InputAt(0);
    1257             : 
    1258             :   ZoneHandleSet<Map> const& maps = p.maps();
    1259             :   size_t const map_count = maps.size();
    1260             : 
    1261       51650 :   if (p.flags() & CheckMapsFlag::kTryMigrateInstance) {
    1262         505 :     auto done = __ MakeDeferredLabel();
    1263         505 :     auto migrate = __ MakeDeferredLabel();
    1264             : 
    1265             :     // Load the current map of the {value}.
    1266         505 :     Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1267             : 
    1268             :     // Perform the map checks.
    1269        1115 :     for (size_t i = 0; i < map_count; ++i) {
    1270         610 :       Node* map = __ HeapConstant(maps[i]);
    1271         610 :       Node* check = __ WordEqual(value_map, map);
    1272         610 :       if (i == map_count - 1) {
    1273         505 :         __ GotoIfNot(check, &migrate);
    1274             :         __ Goto(&done);
    1275             :       } else {
    1276         105 :         __ GotoIf(check, &done);
    1277             :       }
    1278             :     }
    1279             : 
    1280             :     // Perform the (deferred) instance migration.
    1281             :     __ Bind(&migrate);
    1282             :     {
    1283             :       // If map is not deprecated the migration attempt does not make sense.
    1284             :       Node* bitfield3 =
    1285         505 :           __ LoadField(AccessBuilder::ForMapBitField3(), value_map);
    1286             :       Node* if_not_deprecated = __ WordEqual(
    1287             :           __ Word32And(bitfield3, __ Int32Constant(Map::Deprecated::kMask)),
    1288         505 :           __ Int32Constant(0));
    1289             :       __ DeoptimizeIf(DeoptimizeReason::kWrongMap, if_not_deprecated,
    1290         505 :                       frame_state);
    1291             : 
    1292         505 :       Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
    1293             :       Runtime::FunctionId id = Runtime::kTryMigrateInstance;
    1294             :       CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
    1295         505 :           graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags);
    1296             :       Node* result =
    1297             :           __ Call(desc, __ CEntryStubConstant(1), value,
    1298             :                   __ ExternalConstant(ExternalReference(id, isolate())),
    1299        1010 :                   __ Int32Constant(1), __ NoContextConstant());
    1300         505 :       Node* check = ObjectIsSmi(result);
    1301             :       __ DeoptimizeIf(DeoptimizeReason::kInstanceMigrationFailed, check,
    1302         505 :                       frame_state);
    1303             :     }
    1304             : 
    1305             :     // Reload the current map of the {value}.
    1306         505 :     value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1307             : 
    1308             :     // Perform the map checks again.
    1309        1115 :     for (size_t i = 0; i < map_count; ++i) {
    1310         610 :       Node* map = __ HeapConstant(maps[i]);
    1311         610 :       Node* check = __ WordEqual(value_map, map);
    1312         610 :       if (i == map_count - 1) {
    1313         505 :         __ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, check, frame_state);
    1314             :       } else {
    1315         105 :         __ GotoIf(check, &done);
    1316             :       }
    1317             :     }
    1318             : 
    1319             :     __ Goto(&done);
    1320             :     __ Bind(&done);
    1321             :   } else {
    1322       51145 :     auto done = __ MakeLabel();
    1323             : 
    1324             :     // Load the current map of the {value}.
    1325       51145 :     Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1326             : 
    1327      107227 :     for (size_t i = 0; i < map_count; ++i) {
    1328       56082 :       Node* map = __ HeapConstant(maps[i]);
    1329       56082 :       Node* check = __ WordEqual(value_map, map);
    1330       56082 :       if (i == map_count - 1) {
    1331       51145 :         __ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, check, frame_state);
    1332             :       } else {
    1333        4937 :         __ GotoIf(check, &done);
    1334             :       }
    1335             :     }
    1336             :     __ Goto(&done);
    1337             :     __ Bind(&done);
    1338             :   }
    1339       51650 : }
    1340             : 
    1341        8998 : Node* EffectControlLinearizer::LowerCompareMaps(Node* node) {
    1342        8998 :   ZoneHandleSet<Map> const& maps = CompareMapsParametersOf(node->op()).maps();
    1343             :   size_t const map_count = maps.size();
    1344             :   Node* value = node->InputAt(0);
    1345             : 
    1346        8998 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    1347             : 
    1348             :   // Load the current map of the {value}.
    1349        8998 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1350             : 
    1351       18019 :   for (size_t i = 0; i < map_count; ++i) {
    1352        9021 :     Node* map = __ HeapConstant(maps[i]);
    1353        9021 :     Node* check = __ WordEqual(value_map, map);
    1354        9021 :     __ GotoIf(check, &done, __ Int32Constant(1));
    1355             :   }
    1356        8998 :   __ Goto(&done, __ Int32Constant(0));
    1357             : 
    1358             :   __ Bind(&done);
    1359        8998 :   return done.PhiAt(0);
    1360             : }
    1361             : 
    1362         381 : Node* EffectControlLinearizer::LowerCheckNumber(Node* node, Node* frame_state) {
    1363             :   Node* value = node->InputAt(0);
    1364             : 
    1365         381 :   auto if_not_smi = __ MakeDeferredLabel();
    1366         381 :   auto done = __ MakeLabel();
    1367             : 
    1368         381 :   Node* check0 = ObjectIsSmi(value);
    1369         381 :   __ GotoIfNot(check0, &if_not_smi);
    1370             :   __ Goto(&done);
    1371             : 
    1372             :   __ Bind(&if_not_smi);
    1373         381 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1374         381 :   Node* check1 = __ WordEqual(value_map, __ HeapNumberMapConstant());
    1375         381 :   __ DeoptimizeIfNot(DeoptimizeReason::kNotAHeapNumber, check1, frame_state);
    1376             :   __ Goto(&done);
    1377             : 
    1378             :   __ Bind(&done);
    1379         381 :   return value;
    1380             : }
    1381             : 
    1382         855 : Node* EffectControlLinearizer::LowerCheckReceiver(Node* node,
    1383             :                                                   Node* frame_state) {
    1384             :   Node* value = node->InputAt(0);
    1385             : 
    1386         855 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1387             :   Node* value_instance_type =
    1388         855 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1389             : 
    1390             :   STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
    1391             :   Node* check = __ Uint32LessThanOrEqual(
    1392         855 :       __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type);
    1393             :   __ DeoptimizeIfNot(DeoptimizeReason::kNotAJavaScriptObject, check,
    1394         855 :                      frame_state);
    1395         855 :   return value;
    1396             : }
    1397             : 
    1398           0 : Node* EffectControlLinearizer::LowerCheckSymbol(Node* node, Node* frame_state) {
    1399             :   Node* value = node->InputAt(0);
    1400             : 
    1401           0 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1402             : 
    1403             :   Node* check =
    1404           0 :       __ WordEqual(value_map, __ HeapConstant(factory()->symbol_map()));
    1405           0 :   __ DeoptimizeIfNot(DeoptimizeReason::kNotASymbol, check, frame_state);
    1406           0 :   return value;
    1407             : }
    1408             : 
    1409        1770 : Node* EffectControlLinearizer::LowerCheckString(Node* node, Node* frame_state) {
    1410             :   Node* value = node->InputAt(0);
    1411             : 
    1412        1770 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1413             :   Node* value_instance_type =
    1414        1770 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1415             : 
    1416             :   Node* check = __ Uint32LessThan(value_instance_type,
    1417        1770 :                                   __ Uint32Constant(FIRST_NONSTRING_TYPE));
    1418        1770 :   __ DeoptimizeIfNot(DeoptimizeReason::kWrongInstanceType, check, frame_state);
    1419        1770 :   return value;
    1420             : }
    1421             : 
    1422        1113 : Node* EffectControlLinearizer::LowerCheckSeqString(Node* node,
    1423             :                                                    Node* frame_state) {
    1424             :   Node* value = node->InputAt(0);
    1425             : 
    1426        1113 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1427             :   Node* value_instance_type =
    1428        1114 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1429             : 
    1430             :   Node* is_string = __ Uint32LessThan(value_instance_type,
    1431        1114 :                                       __ Uint32Constant(FIRST_NONSTRING_TYPE));
    1432             :   Node* is_sequential =
    1433             :       __ Word32Equal(__ Word32And(value_instance_type,
    1434             :                                   __ Int32Constant(kStringRepresentationMask)),
    1435        1114 :                      __ Int32Constant(kSeqStringTag));
    1436        1114 :   Node* is_sequential_string = __ Word32And(is_string, is_sequential);
    1437             : 
    1438             :   __ DeoptimizeIfNot(DeoptimizeReason::kWrongInstanceType, is_sequential_string,
    1439        1113 :                      frame_state);
    1440        1114 :   return value;
    1441             : }
    1442             : 
    1443        1699 : Node* EffectControlLinearizer::LowerCheckInternalizedString(Node* node,
    1444             :                                                             Node* frame_state) {
    1445             :   Node* value = node->InputAt(0);
    1446             : 
    1447        1699 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1448             :   Node* value_instance_type =
    1449        1699 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1450             : 
    1451             :   Node* check = __ Word32Equal(
    1452             :       __ Word32And(value_instance_type,
    1453             :                    __ Int32Constant(kIsNotStringMask | kIsNotInternalizedMask)),
    1454        1699 :       __ Int32Constant(kInternalizedTag));
    1455        1699 :   __ DeoptimizeIfNot(DeoptimizeReason::kWrongInstanceType, check, frame_state);
    1456             : 
    1457        1699 :   return value;
    1458             : }
    1459             : 
    1460       57980 : void EffectControlLinearizer::LowerCheckIf(Node* node, Node* frame_state) {
    1461             :   Node* value = node->InputAt(0);
    1462             :   __ DeoptimizeIfNot(DeoptimizeKind::kEager, DeoptimizeReasonOf(node->op()),
    1463       28990 :                      value, frame_state);
    1464       28990 : }
    1465             : 
    1466       42140 : Node* EffectControlLinearizer::LowerCheckedInt32Add(Node* node,
    1467             :                                                     Node* frame_state) {
    1468             :   Node* lhs = node->InputAt(0);
    1469             :   Node* rhs = node->InputAt(1);
    1470             : 
    1471       42140 :   Node* value = __ Int32AddWithOverflow(lhs, rhs);
    1472       42139 :   Node* check = __ Projection(1, value);
    1473       42140 :   __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state);
    1474       42140 :   return __ Projection(0, value);
    1475             : }
    1476             : 
    1477       35241 : Node* EffectControlLinearizer::LowerCheckedInt32Sub(Node* node,
    1478             :                                                     Node* frame_state) {
    1479             :   Node* lhs = node->InputAt(0);
    1480             :   Node* rhs = node->InputAt(1);
    1481             : 
    1482       35241 :   Node* value = __ Int32SubWithOverflow(lhs, rhs);
    1483       35241 :   Node* check = __ Projection(1, value);
    1484       35241 :   __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state);
    1485       35241 :   return __ Projection(0, value);
    1486             : }
    1487             : 
    1488         230 : Node* EffectControlLinearizer::LowerCheckedInt32Div(Node* node,
    1489             :                                                     Node* frame_state) {
    1490             :   Node* lhs = node->InputAt(0);
    1491             :   Node* rhs = node->InputAt(1);
    1492             : 
    1493         230 :   auto if_not_positive = __ MakeDeferredLabel();
    1494         230 :   auto if_is_minint = __ MakeDeferredLabel();
    1495         230 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    1496         230 :   auto minint_check_done = __ MakeLabel();
    1497             : 
    1498         230 :   Node* zero = __ Int32Constant(0);
    1499             : 
    1500             :   // Check if {rhs} is positive (and not zero).
    1501         230 :   Node* check0 = __ Int32LessThan(zero, rhs);
    1502         230 :   __ GotoIfNot(check0, &if_not_positive);
    1503             : 
    1504             :   // Fast case, no additional checking required.
    1505         230 :   __ Goto(&done, __ Int32Div(lhs, rhs));
    1506             : 
    1507             :   {
    1508             :     __ Bind(&if_not_positive);
    1509             : 
    1510             :     // Check if {rhs} is zero.
    1511         230 :     Node* check = __ Word32Equal(rhs, zero);
    1512         230 :     __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state);
    1513             : 
    1514             :     // Check if {lhs} is zero, as that would produce minus zero.
    1515         230 :     check = __ Word32Equal(lhs, zero);
    1516         230 :     __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check, frame_state);
    1517             : 
    1518             :     // Check if {lhs} is kMinInt and {rhs} is -1, in which case we'd have
    1519             :     // to return -kMinInt, which is not representable.
    1520         230 :     Node* minint = __ Int32Constant(std::numeric_limits<int32_t>::min());
    1521         230 :     Node* check1 = graph()->NewNode(machine()->Word32Equal(), lhs, minint);
    1522         230 :     __ GotoIf(check1, &if_is_minint);
    1523             :     __ Goto(&minint_check_done);
    1524             : 
    1525             :     __ Bind(&if_is_minint);
    1526             :     // Check if {rhs} is -1.
    1527         230 :     Node* minusone = __ Int32Constant(-1);
    1528         230 :     Node* is_minus_one = __ Word32Equal(rhs, minusone);
    1529         230 :     __ DeoptimizeIf(DeoptimizeReason::kOverflow, is_minus_one, frame_state);
    1530             :     __ Goto(&minint_check_done);
    1531             : 
    1532             :     __ Bind(&minint_check_done);
    1533             :     // Perform the actual integer division.
    1534         230 :     __ Goto(&done, __ Int32Div(lhs, rhs));
    1535             :   }
    1536             : 
    1537             :   __ Bind(&done);
    1538             :   Node* value = done.PhiAt(0);
    1539             : 
    1540             :   // Check if the remainder is non-zero.
    1541         230 :   Node* check = __ Word32Equal(lhs, __ Int32Mul(rhs, value));
    1542         230 :   __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, check, frame_state);
    1543             : 
    1544         230 :   return value;
    1545             : }
    1546             : 
    1547         895 : Node* EffectControlLinearizer::LowerCheckedInt32Mod(Node* node,
    1548             :                                                     Node* frame_state) {
    1549             :   // General case for signed integer modulus, with optimization for (unknown)
    1550             :   // power of 2 right hand side.
    1551             :   //
    1552             :   //   if rhs <= 0 then
    1553             :   //     rhs = -rhs
    1554             :   //     deopt if rhs == 0
    1555             :   //   if lhs < 0 then
    1556             :   //     let res = lhs % rhs in
    1557             :   //     deopt if res == 0
    1558             :   //     res
    1559             :   //   else
    1560             :   //     let msk = rhs - 1 in
    1561             :   //     if rhs & msk == 0 then
    1562             :   //       lhs & msk
    1563             :   //     else
    1564             :   //       lhs % rhs
    1565             :   //
    1566             :   Node* lhs = node->InputAt(0);
    1567             :   Node* rhs = node->InputAt(1);
    1568             : 
    1569         895 :   auto if_rhs_not_positive = __ MakeDeferredLabel();
    1570         895 :   auto if_lhs_negative = __ MakeDeferredLabel();
    1571         895 :   auto if_power_of_two = __ MakeLabel();
    1572         895 :   auto rhs_checked = __ MakeLabel(MachineRepresentation::kWord32);
    1573         895 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    1574             : 
    1575         895 :   Node* zero = __ Int32Constant(0);
    1576             : 
    1577             :   // Check if {rhs} is not strictly positive.
    1578         895 :   Node* check0 = __ Int32LessThanOrEqual(rhs, zero);
    1579         895 :   __ GotoIf(check0, &if_rhs_not_positive);
    1580             :   __ Goto(&rhs_checked, rhs);
    1581             : 
    1582             :   __ Bind(&if_rhs_not_positive);
    1583             :   {
    1584             :     // Negate {rhs}, might still produce a negative result in case of
    1585             :     // -2^31, but that is handled safely below.
    1586         895 :     Node* vtrue0 = __ Int32Sub(zero, rhs);
    1587             : 
    1588             :     // Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
    1589         895 :     Node* check = __ Word32Equal(vtrue0, zero);
    1590         895 :     __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state);
    1591             :     __ Goto(&rhs_checked, vtrue0);
    1592             :   }
    1593             : 
    1594             :   __ Bind(&rhs_checked);
    1595             :   rhs = rhs_checked.PhiAt(0);
    1596             : 
    1597             :   // Check if {lhs} is negative.
    1598         895 :   Node* check1 = __ Int32LessThan(lhs, zero);
    1599         895 :   __ GotoIf(check1, &if_lhs_negative);
    1600             : 
    1601             :   // {lhs} non-negative.
    1602             :   {
    1603         895 :     Node* one = __ Int32Constant(1);
    1604         895 :     Node* msk = __ Int32Sub(rhs, one);
    1605             : 
    1606             :     // Check if {rhs} minus one is a valid mask.
    1607         895 :     Node* check2 = __ Word32Equal(__ Word32And(rhs, msk), zero);
    1608         895 :     __ GotoIf(check2, &if_power_of_two);
    1609             :     // Compute the remainder using the generic {lhs % rhs}.
    1610         895 :     __ Goto(&done, __ Int32Mod(lhs, rhs));
    1611             : 
    1612             :     __ Bind(&if_power_of_two);
    1613             :     // Compute the remainder using {lhs & msk}.
    1614         895 :     __ Goto(&done, __ Word32And(lhs, msk));
    1615             :   }
    1616             : 
    1617             :   __ Bind(&if_lhs_negative);
    1618             :   {
    1619             :     // Compute the remainder using {lhs % msk}.
    1620         895 :     Node* vtrue1 = __ Int32Mod(lhs, rhs);
    1621             : 
    1622             :     // Check if we would have to return -0.
    1623         895 :     Node* check = __ Word32Equal(vtrue1, zero);
    1624         895 :     __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check, frame_state);
    1625             :     __ Goto(&done, vtrue1);
    1626             :   }
    1627             : 
    1628             :   __ Bind(&done);
    1629         895 :   return done.PhiAt(0);
    1630             : }
    1631             : 
    1632          55 : Node* EffectControlLinearizer::LowerCheckedUint32Div(Node* node,
    1633             :                                                      Node* frame_state) {
    1634             :   Node* lhs = node->InputAt(0);
    1635             :   Node* rhs = node->InputAt(1);
    1636             : 
    1637          55 :   Node* zero = __ Int32Constant(0);
    1638             : 
    1639             :   // Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
    1640          55 :   Node* check = __ Word32Equal(rhs, zero);
    1641          55 :   __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state);
    1642             : 
    1643             :   // Perform the actual unsigned integer division.
    1644          55 :   Node* value = __ Uint32Div(lhs, rhs);
    1645             : 
    1646             :   // Check if the remainder is non-zero.
    1647          55 :   check = __ Word32Equal(lhs, __ Int32Mul(rhs, value));
    1648          55 :   __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, check, frame_state);
    1649          55 :   return value;
    1650             : }
    1651             : 
    1652          42 : Node* EffectControlLinearizer::LowerCheckedUint32Mod(Node* node,
    1653             :                                                      Node* frame_state) {
    1654             :   Node* lhs = node->InputAt(0);
    1655             :   Node* rhs = node->InputAt(1);
    1656             : 
    1657          42 :   Node* zero = __ Int32Constant(0);
    1658             : 
    1659             :   // Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
    1660          42 :   Node* check = __ Word32Equal(rhs, zero);
    1661          42 :   __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state);
    1662             : 
    1663             :   // Perform the actual unsigned integer modulus.
    1664          42 :   return __ Uint32Mod(lhs, rhs);
    1665             : }
    1666             : 
    1667        5830 : Node* EffectControlLinearizer::LowerCheckedInt32Mul(Node* node,
    1668             :                                                     Node* frame_state) {
    1669        5830 :   CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
    1670             :   Node* lhs = node->InputAt(0);
    1671             :   Node* rhs = node->InputAt(1);
    1672             : 
    1673        5830 :   Node* projection = __ Int32MulWithOverflow(lhs, rhs);
    1674        5830 :   Node* check = __ Projection(1, projection);
    1675        5830 :   __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state);
    1676             : 
    1677        5830 :   Node* value = __ Projection(0, projection);
    1678             : 
    1679        5830 :   if (mode == CheckForMinusZeroMode::kCheckForMinusZero) {
    1680        4215 :     auto if_zero = __ MakeDeferredLabel();
    1681        4215 :     auto check_done = __ MakeLabel();
    1682        4215 :     Node* zero = __ Int32Constant(0);
    1683        4215 :     Node* check_zero = __ Word32Equal(value, zero);
    1684        4215 :     __ GotoIf(check_zero, &if_zero);
    1685             :     __ Goto(&check_done);
    1686             : 
    1687             :     __ Bind(&if_zero);
    1688             :     // We may need to return negative zero.
    1689        4215 :     Node* check_or = __ Int32LessThan(__ Word32Or(lhs, rhs), zero);
    1690        4215 :     __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check_or, frame_state);
    1691             :     __ Goto(&check_done);
    1692             : 
    1693             :     __ Bind(&check_done);
    1694             :   }
    1695             : 
    1696        5830 :   return value;
    1697             : }
    1698             : 
    1699           0 : Node* EffectControlLinearizer::LowerCheckedInt32ToTaggedSigned(
    1700             :     Node* node, Node* frame_state) {
    1701             :   DCHECK(SmiValuesAre31Bits());
    1702             :   Node* value = node->InputAt(0);
    1703             : 
    1704           0 :   Node* add = __ Int32AddWithOverflow(value, value);
    1705           0 :   Node* check = __ Projection(1, add);
    1706           0 :   __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state);
    1707           0 :   return __ Projection(0, add);
    1708             : }
    1709             : 
    1710         433 : Node* EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node,
    1711             :                                                          Node* frame_state) {
    1712             :   Node* value = node->InputAt(0);
    1713         433 :   Node* unsafe = __ Int32LessThan(value, __ Int32Constant(0));
    1714         433 :   __ DeoptimizeIf(DeoptimizeReason::kLostPrecision, unsafe, frame_state);
    1715         433 :   return value;
    1716             : }
    1717             : 
    1718          24 : Node* EffectControlLinearizer::LowerCheckedUint32ToTaggedSigned(
    1719             :     Node* node, Node* frame_state) {
    1720             :   Node* value = node->InputAt(0);
    1721          24 :   Node* check = __ Uint32LessThanOrEqual(value, SmiMaxValueConstant());
    1722          24 :   __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, check, frame_state);
    1723          24 :   return ChangeUint32ToSmi(value);
    1724             : }
    1725             : 
    1726        7511 : Node* EffectControlLinearizer::BuildCheckedFloat64ToInt32(
    1727             :     CheckForMinusZeroMode mode, Node* value, Node* frame_state) {
    1728        7511 :   Node* value32 = __ RoundFloat64ToInt32(value);
    1729        7511 :   Node* check_same = __ Float64Equal(value, __ ChangeInt32ToFloat64(value32));
    1730             :   __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecisionOrNaN, check_same,
    1731        7511 :                      frame_state);
    1732             : 
    1733        7511 :   if (mode == CheckForMinusZeroMode::kCheckForMinusZero) {
    1734             :     // Check if {value} is -0.
    1735        2177 :     auto if_zero = __ MakeDeferredLabel();
    1736        2177 :     auto check_done = __ MakeLabel();
    1737             : 
    1738        2177 :     Node* check_zero = __ Word32Equal(value32, __ Int32Constant(0));
    1739        2177 :     __ GotoIf(check_zero, &if_zero);
    1740             :     __ Goto(&check_done);
    1741             : 
    1742             :     __ Bind(&if_zero);
    1743             :     // In case of 0, we need to check the high bits for the IEEE -0 pattern.
    1744             :     Node* check_negative = __ Int32LessThan(__ Float64ExtractHighWord32(value),
    1745        2177 :                                             __ Int32Constant(0));
    1746        2177 :     __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check_negative, frame_state);
    1747             :     __ Goto(&check_done);
    1748             : 
    1749             :     __ Bind(&check_done);
    1750             :   }
    1751        7511 :   return value32;
    1752             : }
    1753             : 
    1754        4638 : Node* EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node,
    1755             :                                                           Node* frame_state) {
    1756        4638 :   CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
    1757             :   Node* value = node->InputAt(0);
    1758        4638 :   return BuildCheckedFloat64ToInt32(mode, value, frame_state);
    1759             : }
    1760             : 
    1761       25490 : Node* EffectControlLinearizer::LowerCheckedTaggedSignedToInt32(
    1762             :     Node* node, Node* frame_state) {
    1763             :   Node* value = node->InputAt(0);
    1764       25490 :   Node* check = ObjectIsSmi(value);
    1765       25491 :   __ DeoptimizeIfNot(DeoptimizeReason::kNotASmi, check, frame_state);
    1766       25491 :   return ChangeSmiToInt32(value);
    1767             : }
    1768             : 
    1769        2873 : Node* EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node,
    1770             :                                                          Node* frame_state) {
    1771        2873 :   CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
    1772             :   Node* value = node->InputAt(0);
    1773             : 
    1774        2873 :   auto if_not_smi = __ MakeDeferredLabel();
    1775        2873 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    1776             : 
    1777        2873 :   Node* check = ObjectIsSmi(value);
    1778        2873 :   __ GotoIfNot(check, &if_not_smi);
    1779             :   // In the Smi case, just convert to int32.
    1780        2873 :   __ Goto(&done, ChangeSmiToInt32(value));
    1781             : 
    1782             :   // In the non-Smi case, check the heap numberness, load the number and convert
    1783             :   // to int32.
    1784             :   __ Bind(&if_not_smi);
    1785        2873 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1786        2873 :   Node* check_map = __ WordEqual(value_map, __ HeapNumberMapConstant());
    1787        2873 :   __ DeoptimizeIfNot(DeoptimizeReason::kNotAHeapNumber, check_map, frame_state);
    1788        2873 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1789        2873 :   vfalse = BuildCheckedFloat64ToInt32(mode, vfalse, frame_state);
    1790             :   __ Goto(&done, vfalse);
    1791             : 
    1792             :   __ Bind(&done);
    1793        2873 :   return done.PhiAt(0);
    1794             : }
    1795             : 
    1796       23148 : Node* EffectControlLinearizer::BuildCheckedHeapNumberOrOddballToFloat64(
    1797             :     CheckTaggedInputMode mode, Node* value, Node* frame_state) {
    1798       23148 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1799       23151 :   Node* check_number = __ WordEqual(value_map, __ HeapNumberMapConstant());
    1800       23148 :   switch (mode) {
    1801             :     case CheckTaggedInputMode::kNumber: {
    1802             :       __ DeoptimizeIfNot(DeoptimizeReason::kNotAHeapNumber, check_number,
    1803        9264 :                          frame_state);
    1804        9266 :       break;
    1805             :     }
    1806             :     case CheckTaggedInputMode::kNumberOrOddball: {
    1807       13885 :       auto check_done = __ MakeLabel();
    1808             : 
    1809       13885 :       __ GotoIf(check_number, &check_done);
    1810             :       // For oddballs also contain the numeric value, let us just check that
    1811             :       // we have an oddball here.
    1812             :       Node* instance_type =
    1813       13885 :           __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1814             :       Node* check_oddball =
    1815       13885 :           __ Word32Equal(instance_type, __ Int32Constant(ODDBALL_TYPE));
    1816             :       __ DeoptimizeIfNot(DeoptimizeReason::kNotANumberOrOddball, check_oddball,
    1817       13885 :                          frame_state);
    1818             :       STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    1819             :       __ Goto(&check_done);
    1820             : 
    1821             :       __ Bind(&check_done);
    1822             :       break;
    1823             :     }
    1824             :   }
    1825       23150 :   return __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1826             : }
    1827             : 
    1828       20711 : Node* EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node,
    1829             :                                                            Node* frame_state) {
    1830       20711 :   CheckTaggedInputMode mode = CheckTaggedInputModeOf(node->op());
    1831             :   Node* value = node->InputAt(0);
    1832             : 
    1833       20711 :   auto if_smi = __ MakeLabel();
    1834       20711 :   auto done = __ MakeLabel(MachineRepresentation::kFloat64);
    1835             : 
    1836       20711 :   Node* check = ObjectIsSmi(value);
    1837       20711 :   __ GotoIf(check, &if_smi);
    1838             : 
    1839             :   // In the Smi case, just convert to int32 and then float64.
    1840             :   // Otherwise, check heap numberness and load the number.
    1841             :   Node* number =
    1842       20712 :       BuildCheckedHeapNumberOrOddballToFloat64(mode, value, frame_state);
    1843             :   __ Goto(&done, number);
    1844             : 
    1845             :   __ Bind(&if_smi);
    1846       20711 :   Node* from_smi = ChangeSmiToInt32(value);
    1847       20712 :   from_smi = __ ChangeInt32ToFloat64(from_smi);
    1848             :   __ Goto(&done, from_smi);
    1849             : 
    1850             :   __ Bind(&done);
    1851       20712 :   return done.PhiAt(0);
    1852             : }
    1853             : 
    1854       27080 : Node* EffectControlLinearizer::LowerCheckedTaggedToTaggedSigned(
    1855             :     Node* node, Node* frame_state) {
    1856             :   Node* value = node->InputAt(0);
    1857             : 
    1858       27080 :   Node* check = ObjectIsSmi(value);
    1859       27080 :   __ DeoptimizeIfNot(DeoptimizeReason::kNotASmi, check, frame_state);
    1860             : 
    1861       27080 :   return value;
    1862             : }
    1863             : 
    1864       28657 : Node* EffectControlLinearizer::LowerCheckedTaggedToTaggedPointer(
    1865             :     Node* node, Node* frame_state) {
    1866             :   Node* value = node->InputAt(0);
    1867             : 
    1868       28657 :   Node* check = ObjectIsSmi(value);
    1869       28657 :   __ DeoptimizeIf(DeoptimizeReason::kSmi, check, frame_state);
    1870       28657 :   return value;
    1871             : }
    1872             : 
    1873         927 : Node* EffectControlLinearizer::LowerTruncateTaggedToWord32(Node* node) {
    1874             :   Node* value = node->InputAt(0);
    1875             : 
    1876         927 :   auto if_not_smi = __ MakeDeferredLabel();
    1877         927 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    1878             : 
    1879         927 :   Node* check = ObjectIsSmi(value);
    1880         927 :   __ GotoIfNot(check, &if_not_smi);
    1881         927 :   __ Goto(&done, ChangeSmiToInt32(value));
    1882             : 
    1883             :   __ Bind(&if_not_smi);
    1884             :   STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    1885         927 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1886         927 :   vfalse = __ TruncateFloat64ToWord32(vfalse);
    1887             :   __ Goto(&done, vfalse);
    1888             : 
    1889             :   __ Bind(&done);
    1890         927 :   return done.PhiAt(0);
    1891             : }
    1892             : 
    1893        2437 : Node* EffectControlLinearizer::LowerCheckedTruncateTaggedToWord32(
    1894        2437 :     Node* node, Node* frame_state) {
    1895        2437 :   CheckTaggedInputMode mode = CheckTaggedInputModeOf(node->op());
    1896             :   Node* value = node->InputAt(0);
    1897             : 
    1898        2438 :   auto if_not_smi = __ MakeLabel();
    1899        2438 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    1900             : 
    1901        2438 :   Node* check = ObjectIsSmi(value);
    1902        2437 :   __ GotoIfNot(check, &if_not_smi);
    1903             :   // In the Smi case, just convert to int32.
    1904        2440 :   __ Goto(&done, ChangeSmiToInt32(value));
    1905             : 
    1906             :   // Otherwise, check that it's a heap number or oddball and truncate the value
    1907             :   // to int32.
    1908             :   __ Bind(&if_not_smi);
    1909             :   Node* number =
    1910        2437 :       BuildCheckedHeapNumberOrOddballToFloat64(mode, value, frame_state);
    1911        2439 :   number = __ TruncateFloat64ToWord32(number);
    1912             :   __ Goto(&done, number);
    1913             : 
    1914             :   __ Bind(&done);
    1915        2440 :   return done.PhiAt(0);
    1916             : }
    1917             : 
    1918           0 : Node* EffectControlLinearizer::LowerObjectIsArrayBufferView(Node* node) {
    1919             :   Node* value = node->InputAt(0);
    1920             : 
    1921           0 :   auto if_smi = __ MakeDeferredLabel();
    1922           0 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    1923             : 
    1924           0 :   Node* check = ObjectIsSmi(value);
    1925           0 :   __ GotoIf(check, &if_smi);
    1926             : 
    1927           0 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1928             :   Node* value_instance_type =
    1929           0 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1930             :   STATIC_ASSERT(JS_TYPED_ARRAY_TYPE + 1 == JS_DATA_VIEW_TYPE);
    1931             :   Node* vfalse = __ Uint32LessThan(
    1932             :       __ Int32Sub(value_instance_type, __ Int32Constant(JS_TYPED_ARRAY_TYPE)),
    1933           0 :       __ Int32Constant(2));
    1934             :   __ Goto(&done, vfalse);
    1935             : 
    1936             :   __ Bind(&if_smi);
    1937           0 :   __ Goto(&done, __ Int32Constant(0));
    1938             : 
    1939             :   __ Bind(&done);
    1940           0 :   return done.PhiAt(0);
    1941             : }
    1942             : 
    1943          10 : Node* EffectControlLinearizer::LowerObjectIsCallable(Node* node) {
    1944             :   Node* value = node->InputAt(0);
    1945             : 
    1946          10 :   auto if_smi = __ MakeDeferredLabel();
    1947          10 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    1948             : 
    1949          10 :   Node* check = ObjectIsSmi(value);
    1950          10 :   __ GotoIf(check, &if_smi);
    1951             : 
    1952          10 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1953             :   Node* value_bit_field =
    1954          10 :       __ LoadField(AccessBuilder::ForMapBitField(), value_map);
    1955             :   Node* vfalse = __ Word32Equal(
    1956             :       __ Int32Constant(1 << Map::kIsCallable),
    1957          10 :       __ Word32And(value_bit_field, __ Int32Constant(1 << Map::kIsCallable)));
    1958             :   __ Goto(&done, vfalse);
    1959             : 
    1960             :   __ Bind(&if_smi);
    1961          10 :   __ Goto(&done, __ Int32Constant(0));
    1962             : 
    1963             :   __ Bind(&done);
    1964          10 :   return done.PhiAt(0);
    1965             : }
    1966             : 
    1967         160 : Node* EffectControlLinearizer::LowerObjectIsConstructor(Node* node) {
    1968             :   Node* value = node->InputAt(0);
    1969             : 
    1970         160 :   auto if_smi = __ MakeDeferredLabel();
    1971         160 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    1972             : 
    1973         160 :   Node* check = ObjectIsSmi(value);
    1974         160 :   __ GotoIf(check, &if_smi);
    1975             : 
    1976         160 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1977             :   Node* value_bit_field =
    1978         160 :       __ LoadField(AccessBuilder::ForMapBitField(), value_map);
    1979             :   Node* vfalse =
    1980             :       __ Word32Equal(__ Int32Constant(1 << Map::kIsConstructor),
    1981             :                      __ Word32And(value_bit_field,
    1982         160 :                                   __ Int32Constant(1 << Map::kIsConstructor)));
    1983             :   __ Goto(&done, vfalse);
    1984             : 
    1985             :   __ Bind(&if_smi);
    1986         160 :   __ Goto(&done, __ Int32Constant(0));
    1987             : 
    1988             :   __ Bind(&done);
    1989         160 :   return done.PhiAt(0);
    1990             : }
    1991             : 
    1992       11027 : Node* EffectControlLinearizer::LowerObjectIsDetectableCallable(Node* node) {
    1993             :   Node* value = node->InputAt(0);
    1994             : 
    1995       11027 :   auto if_smi = __ MakeDeferredLabel();
    1996       11027 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    1997             : 
    1998       11027 :   Node* check = ObjectIsSmi(value);
    1999       11027 :   __ GotoIf(check, &if_smi);
    2000             : 
    2001       11027 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2002             :   Node* value_bit_field =
    2003       11027 :       __ LoadField(AccessBuilder::ForMapBitField(), value_map);
    2004             :   Node* vfalse = __ Word32Equal(
    2005             :       __ Int32Constant(1 << Map::kIsCallable),
    2006             :       __ Word32And(value_bit_field,
    2007             :                    __ Int32Constant((1 << Map::kIsCallable) |
    2008       11027 :                                     (1 << Map::kIsUndetectable))));
    2009             :   __ Goto(&done, vfalse);
    2010             : 
    2011             :   __ Bind(&if_smi);
    2012       11027 :   __ Goto(&done, __ Int32Constant(0));
    2013             : 
    2014             :   __ Bind(&done);
    2015       11027 :   return done.PhiAt(0);
    2016             : }
    2017             : 
    2018          14 : Node* EffectControlLinearizer::LowerObjectIsMinusZero(Node* node) {
    2019             :   Node* value = node->InputAt(0);
    2020          14 :   Node* zero = __ Int32Constant(0);
    2021             : 
    2022          14 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2023             : 
    2024             :   // Check if {value} is a Smi.
    2025          14 :   __ GotoIf(ObjectIsSmi(value), &done, zero);
    2026             : 
    2027             :   // Check if {value} is a HeapNumber.
    2028          14 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2029             :   __ GotoIfNot(__ WordEqual(value_map, __ HeapNumberMapConstant()), &done,
    2030          14 :                zero);
    2031             : 
    2032             :   // Check if {value} contains -0.
    2033          14 :   Node* value_value = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    2034             :   __ Goto(&done,
    2035             :           __ Float64Equal(
    2036             :               __ Float64Div(__ Float64Constant(1.0), value_value),
    2037          14 :               __ Float64Constant(-std::numeric_limits<double>::infinity())));
    2038             : 
    2039             :   __ Bind(&done);
    2040          14 :   return done.PhiAt(0);
    2041             : }
    2042             : 
    2043         534 : Node* EffectControlLinearizer::LowerObjectIsNaN(Node* node) {
    2044             :   Node* value = node->InputAt(0);
    2045         534 :   Node* zero = __ Int32Constant(0);
    2046             : 
    2047         534 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2048             : 
    2049             :   // Check if {value} is a Smi.
    2050         534 :   __ GotoIf(ObjectIsSmi(value), &done, zero);
    2051             : 
    2052             :   // Check if {value} is a HeapNumber.
    2053         534 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2054             :   __ GotoIfNot(__ WordEqual(value_map, __ HeapNumberMapConstant()), &done,
    2055         534 :                zero);
    2056             : 
    2057             :   // Check if {value} contains a NaN.
    2058         534 :   Node* value_value = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    2059             :   __ Goto(&done,
    2060         534 :           __ Word32Equal(__ Float64Equal(value_value, value_value), zero));
    2061             : 
    2062             :   __ Bind(&done);
    2063         534 :   return done.PhiAt(0);
    2064             : }
    2065             : 
    2066        5284 : Node* EffectControlLinearizer::LowerObjectIsNonCallable(Node* node) {
    2067             :   Node* value = node->InputAt(0);
    2068             : 
    2069        5284 :   auto if_primitive = __ MakeDeferredLabel();
    2070        5284 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2071             : 
    2072        5284 :   Node* check0 = ObjectIsSmi(value);
    2073        5284 :   __ GotoIf(check0, &if_primitive);
    2074             : 
    2075        5284 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2076             :   Node* value_instance_type =
    2077        5284 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    2078             :   STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
    2079             :   Node* check1 = __ Uint32LessThanOrEqual(
    2080        5284 :       __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type);
    2081        5284 :   __ GotoIfNot(check1, &if_primitive);
    2082             : 
    2083             :   Node* value_bit_field =
    2084        5284 :       __ LoadField(AccessBuilder::ForMapBitField(), value_map);
    2085             :   Node* check2 = __ Word32Equal(
    2086             :       __ Int32Constant(0),
    2087        5284 :       __ Word32And(value_bit_field, __ Int32Constant(1 << Map::kIsCallable)));
    2088             :   __ Goto(&done, check2);
    2089             : 
    2090             :   __ Bind(&if_primitive);
    2091        5284 :   __ Goto(&done, __ Int32Constant(0));
    2092             : 
    2093             :   __ Bind(&done);
    2094        5284 :   return done.PhiAt(0);
    2095             : }
    2096             : 
    2097        7693 : Node* EffectControlLinearizer::LowerObjectIsNumber(Node* node) {
    2098             :   Node* value = node->InputAt(0);
    2099             : 
    2100        7693 :   auto if_smi = __ MakeLabel();
    2101        7693 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2102             : 
    2103        7693 :   __ GotoIf(ObjectIsSmi(value), &if_smi);
    2104        7693 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2105        7693 :   __ Goto(&done, __ WordEqual(value_map, __ HeapNumberMapConstant()));
    2106             : 
    2107             :   __ Bind(&if_smi);
    2108        7693 :   __ Goto(&done, __ Int32Constant(1));
    2109             : 
    2110             :   __ Bind(&done);
    2111        7693 :   return done.PhiAt(0);
    2112             : }
    2113             : 
    2114       18113 : Node* EffectControlLinearizer::LowerObjectIsReceiver(Node* node) {
    2115             :   Node* value = node->InputAt(0);
    2116             : 
    2117       18113 :   auto if_smi = __ MakeDeferredLabel();
    2118       18113 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2119             : 
    2120       18113 :   __ GotoIf(ObjectIsSmi(value), &if_smi);
    2121             : 
    2122             :   STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
    2123       18113 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2124             :   Node* value_instance_type =
    2125       18113 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    2126             :   Node* result = __ Uint32LessThanOrEqual(
    2127       18113 :       __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type);
    2128             :   __ Goto(&done, result);
    2129             : 
    2130             :   __ Bind(&if_smi);
    2131       18113 :   __ Goto(&done, __ Int32Constant(0));
    2132             : 
    2133             :   __ Bind(&done);
    2134       18113 :   return done.PhiAt(0);
    2135             : }
    2136             : 
    2137        6382 : Node* EffectControlLinearizer::LowerObjectIsSmi(Node* node) {
    2138             :   Node* value = node->InputAt(0);
    2139        6382 :   return ObjectIsSmi(value);
    2140             : }
    2141             : 
    2142        2380 : Node* EffectControlLinearizer::LowerObjectIsString(Node* node) {
    2143             :   Node* value = node->InputAt(0);
    2144             : 
    2145        2380 :   auto if_smi = __ MakeDeferredLabel();
    2146        2380 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2147             : 
    2148        2380 :   Node* check = ObjectIsSmi(value);
    2149        2380 :   __ GotoIf(check, &if_smi);
    2150        2380 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2151             :   Node* value_instance_type =
    2152        2380 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    2153             :   Node* vfalse = __ Uint32LessThan(value_instance_type,
    2154        2380 :                                    __ Uint32Constant(FIRST_NONSTRING_TYPE));
    2155             :   __ Goto(&done, vfalse);
    2156             : 
    2157             :   __ Bind(&if_smi);
    2158        2380 :   __ Goto(&done, __ Int32Constant(0));
    2159             : 
    2160             :   __ Bind(&done);
    2161        2380 :   return done.PhiAt(0);
    2162             : }
    2163             : 
    2164         134 : Node* EffectControlLinearizer::LowerObjectIsSymbol(Node* node) {
    2165             :   Node* value = node->InputAt(0);
    2166             : 
    2167         134 :   auto if_smi = __ MakeDeferredLabel();
    2168         134 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2169             : 
    2170         134 :   Node* check = ObjectIsSmi(value);
    2171         134 :   __ GotoIf(check, &if_smi);
    2172         134 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2173             :   Node* value_instance_type =
    2174         134 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    2175             :   Node* vfalse =
    2176         134 :       __ Word32Equal(value_instance_type, __ Uint32Constant(SYMBOL_TYPE));
    2177             :   __ Goto(&done, vfalse);
    2178             : 
    2179             :   __ Bind(&if_smi);
    2180         134 :   __ Goto(&done, __ Int32Constant(0));
    2181             : 
    2182             :   __ Bind(&done);
    2183         134 :   return done.PhiAt(0);
    2184             : }
    2185             : 
    2186        5469 : Node* EffectControlLinearizer::LowerObjectIsUndetectable(Node* node) {
    2187             :   Node* value = node->InputAt(0);
    2188             : 
    2189        5469 :   auto if_smi = __ MakeDeferredLabel();
    2190        5469 :   auto done = __ MakeLabel(MachineRepresentation::kBit);
    2191             : 
    2192        5469 :   Node* check = ObjectIsSmi(value);
    2193        5469 :   __ GotoIf(check, &if_smi);
    2194             : 
    2195        5469 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    2196             :   Node* value_bit_field =
    2197        5469 :       __ LoadField(AccessBuilder::ForMapBitField(), value_map);
    2198             :   Node* vfalse = __ Word32Equal(
    2199             :       __ Word32Equal(__ Int32Constant(0),
    2200             :                      __ Word32And(value_bit_field,
    2201             :                                   __ Int32Constant(1 << Map::kIsUndetectable))),
    2202        5469 :       __ Int32Constant(0));
    2203             :   __ Goto(&done, vfalse);
    2204             : 
    2205             :   __ Bind(&if_smi);
    2206        5469 :   __ Goto(&done, __ Int32Constant(0));
    2207             : 
    2208             :   __ Bind(&done);
    2209        5469 :   return done.PhiAt(0);
    2210             : }
    2211             : 
    2212       20286 : Node* EffectControlLinearizer::LowerTypeOf(Node* node) {
    2213             :   Node* obj = node->InputAt(0);
    2214       20286 :   Callable const callable = Builtins::CallableFor(isolate(), Builtins::kTypeof);
    2215             :   Operator::Properties const properties = Operator::kEliminatable;
    2216             :   CallDescriptor::Flags const flags = CallDescriptor::kNoAllocate;
    2217             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    2218       60858 :       isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
    2219             :   return __ Call(desc, __ HeapConstant(callable.code()), obj,
    2220       40572 :                  __ NoContextConstant());
    2221             : }
    2222             : 
    2223         966 : Node* EffectControlLinearizer::LowerClassOf(Node* node) {
    2224             :   Node* obj = node->InputAt(0);
    2225             :   Callable const callable =
    2226         966 :       Builtins::CallableFor(isolate(), Builtins::kClassOf);
    2227             :   Operator::Properties const properties = Operator::kEliminatable;
    2228             :   CallDescriptor::Flags const flags = CallDescriptor::kNoAllocate;
    2229             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    2230        2898 :       isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
    2231             :   return __ Call(desc, __ HeapConstant(callable.code()), obj,
    2232        1932 :                  __ NoContextConstant());
    2233             : }
    2234             : 
    2235         580 : Node* EffectControlLinearizer::LowerToBoolean(Node* node) {
    2236             :   Node* obj = node->InputAt(0);
    2237             :   Callable const callable =
    2238         580 :       Builtins::CallableFor(isolate(), Builtins::kToBoolean);
    2239             :   Operator::Properties const properties = Operator::kEliminatable;
    2240             :   CallDescriptor::Flags const flags = CallDescriptor::kNoAllocate;
    2241             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    2242        1740 :       isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
    2243             :   return __ Call(desc, __ HeapConstant(callable.code()), obj,
    2244        1160 :                  __ NoContextConstant());
    2245             : }
    2246             : 
    2247       47565 : Node* EffectControlLinearizer::LowerArgumentsLength(Node* node) {
    2248       15855 :   Node* arguments_frame = NodeProperties::GetValueInput(node, 0);
    2249       15855 :   int formal_parameter_count = FormalParameterCountOf(node->op());
    2250       15855 :   bool is_rest_length = IsRestLengthOf(node->op());
    2251             :   DCHECK_LE(0, formal_parameter_count);
    2252             : 
    2253       15855 :   if (is_rest_length) {
    2254             :     // The ArgumentsLength node is computing the number of rest parameters,
    2255             :     // which is max(0, actual_parameter_count - formal_parameter_count).
    2256             :     // We have to distinguish the case, when there is an arguments adaptor frame
    2257             :     // (i.e., arguments_frame != LoadFramePointer()).
    2258         227 :     auto if_adaptor_frame = __ MakeLabel();
    2259         227 :     auto done = __ MakeLabel(MachineRepresentation::kTaggedSigned);
    2260             : 
    2261         227 :     Node* frame = __ LoadFramePointer();
    2262         227 :     __ GotoIf(__ WordEqual(arguments_frame, frame), &done, __ SmiConstant(0));
    2263             :     __ Goto(&if_adaptor_frame);
    2264             : 
    2265             :     __ Bind(&if_adaptor_frame);
    2266             :     Node* arguments_length = __ Load(
    2267             :         MachineType::TaggedSigned(), arguments_frame,
    2268         227 :         __ IntPtrConstant(ArgumentsAdaptorFrameConstants::kLengthOffset));
    2269             : 
    2270             :     Node* rest_length =
    2271         227 :         __ IntSub(arguments_length, __ SmiConstant(formal_parameter_count));
    2272             :     __ GotoIf(__ IntLessThan(rest_length, __ SmiConstant(0)), &done,
    2273         227 :               __ SmiConstant(0));
    2274             :     __ Goto(&done, rest_length);
    2275             : 
    2276             :     __ Bind(&done);
    2277             :     return done.PhiAt(0);
    2278             :   } else {
    2279             :     // The ArgumentsLength node is computing the actual number of arguments.
    2280             :     // We have to distinguish the case when there is an arguments adaptor frame
    2281             :     // (i.e., arguments_frame != LoadFramePointer()).
    2282       15628 :     auto if_adaptor_frame = __ MakeLabel();
    2283       15628 :     auto done = __ MakeLabel(MachineRepresentation::kTaggedSigned);
    2284             : 
    2285       15628 :     Node* frame = __ LoadFramePointer();
    2286             :     __ GotoIf(__ WordEqual(arguments_frame, frame), &done,
    2287       15628 :               __ SmiConstant(formal_parameter_count));
    2288             :     __ Goto(&if_adaptor_frame);
    2289             : 
    2290             :     __ Bind(&if_adaptor_frame);
    2291             :     Node* arguments_length = __ Load(
    2292             :         MachineType::TaggedSigned(), arguments_frame,
    2293       15628 :         __ IntPtrConstant(ArgumentsAdaptorFrameConstants::kLengthOffset));
    2294             :     __ Goto(&done, arguments_length);
    2295             : 
    2296             :     __ Bind(&done);
    2297             :     return done.PhiAt(0);
    2298             :   }
    2299             : }
    2300             : 
    2301       15826 : Node* EffectControlLinearizer::LowerArgumentsFrame(Node* node) {
    2302       15826 :   auto done = __ MakeLabel(MachineType::PointerRepresentation());
    2303             : 
    2304       15826 :   Node* frame = __ LoadFramePointer();
    2305             :   Node* parent_frame =
    2306             :       __ Load(MachineType::AnyTagged(), frame,
    2307       15826 :               __ IntPtrConstant(StandardFrameConstants::kCallerFPOffset));
    2308             :   Node* parent_frame_type = __ Load(
    2309             :       MachineType::AnyTagged(), parent_frame,
    2310       15826 :       __ IntPtrConstant(CommonFrameConstants::kContextOrFrameTypeOffset));
    2311             :   __ GotoIf(__ WordEqual(parent_frame_type,
    2312             :                          __ IntPtrConstant(StackFrame::TypeToMarker(
    2313             :                              StackFrame::ARGUMENTS_ADAPTOR))),
    2314       15826 :             &done, parent_frame);
    2315             :   __ Goto(&done, frame);
    2316             : 
    2317             :   __ Bind(&done);
    2318       15826 :   return done.PhiAt(0);
    2319             : }
    2320             : 
    2321          32 : Node* EffectControlLinearizer::LowerNewDoubleElements(Node* node) {
    2322          32 :   PretenureFlag const pretenure = PretenureFlagOf(node->op());
    2323             :   Node* length = node->InputAt(0);
    2324             : 
    2325             :   // Compute the effective size of the backing store.
    2326             :   Node* size =
    2327             :       __ Int32Add(__ Word32Shl(length, __ Int32Constant(kDoubleSizeLog2)),
    2328          32 :                   __ Int32Constant(FixedDoubleArray::kHeaderSize));
    2329             : 
    2330             :   // Allocate the result and initialize the header.
    2331          32 :   Node* result = __ Allocate(pretenure, size);
    2332             :   __ StoreField(AccessBuilder::ForMap(), result,
    2333          32 :                 __ FixedDoubleArrayMapConstant());
    2334             :   __ StoreField(AccessBuilder::ForFixedArrayLength(), result,
    2335          32 :                 ChangeInt32ToSmi(length));
    2336             : 
    2337             :   // Initialize the backing store with holes.
    2338             :   STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    2339             :   Node* limit = ChangeUint32ToUintPtr(length);
    2340             :   Node* the_hole =
    2341          32 :       __ LoadField(AccessBuilder::ForHeapNumberValue(), __ TheHoleConstant());
    2342          32 :   auto loop = __ MakeLoopLabel(MachineType::PointerRepresentation());
    2343          32 :   auto done_loop = __ MakeLabel();
    2344          32 :   __ Goto(&loop, __ IntPtrConstant(0));
    2345             :   __ Bind(&loop);
    2346             :   {
    2347             :     // Check if we've initialized everything.
    2348             :     Node* index = loop.PhiAt(0);
    2349          32 :     Node* check = __ UintLessThan(index, limit);
    2350          32 :     __ GotoIfNot(check, &done_loop);
    2351             : 
    2352             :     // Storing "the_hole" doesn't need a write barrier.
    2353             :     StoreRepresentation rep(MachineRepresentation::kFloat64, kNoWriteBarrier);
    2354             :     Node* offset = __ IntAdd(
    2355             :         __ WordShl(index, __ IntPtrConstant(kDoubleSizeLog2)),
    2356          32 :         __ IntPtrConstant(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
    2357          32 :     __ Store(rep, result, offset, the_hole);
    2358             : 
    2359             :     // Advance the {index}.
    2360          32 :     index = __ IntAdd(index, __ IntPtrConstant(1));
    2361             :     __ Goto(&loop, index);
    2362             :   }
    2363             : 
    2364             :   __ Bind(&done_loop);
    2365          32 :   return result;
    2366             : }
    2367             : 
    2368         322 : Node* EffectControlLinearizer::LowerNewSmiOrObjectElements(Node* node) {
    2369         322 :   PretenureFlag const pretenure = PretenureFlagOf(node->op());
    2370             :   Node* length = node->InputAt(0);
    2371             : 
    2372             :   // Compute the effective size of the backing store.
    2373             :   Node* size =
    2374             :       __ Int32Add(__ Word32Shl(length, __ Int32Constant(kPointerSizeLog2)),
    2375         322 :                   __ Int32Constant(FixedArray::kHeaderSize));
    2376             : 
    2377             :   // Allocate the result and initialize the header.
    2378         322 :   Node* result = __ Allocate(pretenure, size);
    2379         322 :   __ StoreField(AccessBuilder::ForMap(), result, __ FixedArrayMapConstant());
    2380             :   __ StoreField(AccessBuilder::ForFixedArrayLength(), result,
    2381         322 :                 ChangeInt32ToSmi(length));
    2382             : 
    2383             :   // Initialize the backing store with holes.
    2384             :   Node* limit = ChangeUint32ToUintPtr(length);
    2385         322 :   Node* the_hole = __ TheHoleConstant();
    2386         322 :   auto loop = __ MakeLoopLabel(MachineType::PointerRepresentation());
    2387         322 :   auto done_loop = __ MakeLabel();
    2388         322 :   __ Goto(&loop, __ IntPtrConstant(0));
    2389             :   __ Bind(&loop);
    2390             :   {
    2391             :     // Check if we've initialized everything.
    2392             :     Node* index = loop.PhiAt(0);
    2393         322 :     Node* check = __ UintLessThan(index, limit);
    2394         322 :     __ GotoIfNot(check, &done_loop);
    2395             : 
    2396             :     // Storing "the_hole" doesn't need a write barrier.
    2397             :     StoreRepresentation rep(MachineRepresentation::kTagged, kNoWriteBarrier);
    2398             :     Node* offset =
    2399             :         __ IntAdd(__ WordShl(index, __ IntPtrConstant(kPointerSizeLog2)),
    2400         322 :                   __ IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag));
    2401         322 :     __ Store(rep, result, offset, the_hole);
    2402             : 
    2403             :     // Advance the {index}.
    2404         322 :     index = __ IntAdd(index, __ IntPtrConstant(1));
    2405             :     __ Goto(&loop, index);
    2406             :   }
    2407             : 
    2408             :   __ Bind(&done_loop);
    2409         322 :   return result;
    2410             : }
    2411             : 
    2412       30222 : Node* EffectControlLinearizer::LowerNewArgumentsElements(Node* node) {
    2413       15111 :   Node* frame = NodeProperties::GetValueInput(node, 0);
    2414       15111 :   Node* length = NodeProperties::GetValueInput(node, 1);
    2415       15111 :   int mapped_count = OpParameter<int>(node);
    2416             : 
    2417             :   Callable const callable =
    2418       15111 :       Builtins::CallableFor(isolate(), Builtins::kNewArgumentsElements);
    2419       15111 :   Operator::Properties const properties = node->op()->properties();
    2420             :   CallDescriptor::Flags const flags = CallDescriptor::kNoFlags;
    2421             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    2422       45333 :       isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
    2423             :   return __ Call(desc, __ HeapConstant(callable.code()), frame, length,
    2424       30222 :                  __ SmiConstant(mapped_count), __ NoContextConstant());
    2425             : }
    2426             : 
    2427         544 : Node* EffectControlLinearizer::LowerArrayBufferWasNeutered(Node* node) {
    2428             :   Node* value = node->InputAt(0);
    2429             : 
    2430             :   Node* value_bit_field =
    2431         544 :       __ LoadField(AccessBuilder::ForJSArrayBufferBitField(), value);
    2432             :   return __ Word32Equal(
    2433             :       __ Word32Equal(
    2434             :           __ Word32And(value_bit_field,
    2435             :                        __ Int32Constant(JSArrayBuffer::WasNeutered::kMask)),
    2436             :           __ Int32Constant(0)),
    2437         544 :       __ Int32Constant(0));
    2438             : }
    2439             : 
    2440         183 : Node* EffectControlLinearizer::LowerStringToNumber(Node* node) {
    2441             :   Node* string = node->InputAt(0);
    2442             : 
    2443             :   Callable const callable =
    2444         183 :       Builtins::CallableFor(isolate(), Builtins::kStringToNumber);
    2445             :   Operator::Properties properties = Operator::kEliminatable;
    2446             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    2447             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    2448         549 :       isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
    2449             :   return __ Call(desc, __ HeapConstant(callable.code()), string,
    2450         366 :                  __ NoContextConstant());
    2451             : }
    2452             : 
    2453         302 : Node* EffectControlLinearizer::LowerStringCharAt(Node* node) {
    2454             :   Node* receiver = node->InputAt(0);
    2455             :   Node* position = node->InputAt(1);
    2456             : 
    2457             :   Callable const callable =
    2458         302 :       Builtins::CallableFor(isolate(), Builtins::kStringCharAt);
    2459         302 :   Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite;
    2460             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    2461             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    2462         906 :       isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
    2463             :   return __ Call(desc, __ HeapConstant(callable.code()), receiver, position,
    2464         604 :                  __ NoContextConstant());
    2465             : }
    2466             : 
    2467         147 : Node* EffectControlLinearizer::LowerStringCharCodeAt(Node* node) {
    2468             :   Node* receiver = node->InputAt(0);
    2469             :   Node* position = node->InputAt(1);
    2470             : 
    2471             :   Callable const callable =
    2472         147 :       Builtins::CallableFor(isolate(), Builtins::kStringCharCodeAt);
    2473         147 :   Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite;
    2474             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    2475             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    2476             :       isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties,
    2477         441 :       MachineType::TaggedSigned());
    2478             :   return __ Call(desc, __ HeapConstant(callable.code()), receiver, position,
    2479         294 :                  __ NoContextConstant());
    2480             : }
    2481             : 
    2482         410 : Node* EffectControlLinearizer::LowerSeqStringCharCodeAt(Node* node) {
    2483             :   Node* receiver = node->InputAt(0);
    2484             :   Node* position = node->InputAt(1);
    2485             : 
    2486         410 :   auto one_byte_load = __ MakeLabel();
    2487         410 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    2488             : 
    2489         410 :   Node* map = __ LoadField(AccessBuilder::ForMap(), receiver);
    2490         410 :   Node* instance_type = __ LoadField(AccessBuilder::ForMapInstanceType(), map);
    2491             :   Node* is_one_byte = __ Word32Equal(
    2492             :       __ Word32And(instance_type, __ Int32Constant(kStringEncodingMask)),
    2493         410 :       __ Int32Constant(kOneByteStringTag));
    2494             : 
    2495         410 :   __ GotoIf(is_one_byte, &one_byte_load);
    2496             :   Node* two_byte_result = __ LoadElement(
    2497         410 :       AccessBuilder::ForSeqTwoByteStringCharacter(), receiver, position);
    2498             :   __ Goto(&done, two_byte_result);
    2499             : 
    2500             :   __ Bind(&one_byte_load);
    2501             :   Node* one_byte_element = __ LoadElement(
    2502         410 :       AccessBuilder::ForSeqOneByteStringCharacter(), receiver, position);
    2503             :   __ Goto(&done, one_byte_element);
    2504             : 
    2505             :   __ Bind(&done);
    2506         410 :   return done.PhiAt(0);
    2507             : }
    2508             : 
    2509         203 : Node* EffectControlLinearizer::LowerStringFromCharCode(Node* node) {
    2510             :   Node* value = node->InputAt(0);
    2511             : 
    2512         203 :   auto runtime_call = __ MakeDeferredLabel();
    2513             :   auto if_undefined = __ MakeDeferredLabel();
    2514         203 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    2515             : 
    2516             :   // Compute the character code.
    2517         203 :   Node* code = __ Word32And(value, __ Int32Constant(String::kMaxUtf16CodeUnit));
    2518             : 
    2519             :   // Check if the {code} is a one-byte char code.
    2520             :   Node* check0 = __ Int32LessThanOrEqual(
    2521         203 :       code, __ Int32Constant(String::kMaxOneByteCharCode));
    2522         203 :   __ GotoIfNot(check0, &runtime_call);
    2523             : 
    2524             :   // Load the isolate wide single character string cache.
    2525         203 :   Node* cache = __ HeapConstant(factory()->single_character_string_cache());
    2526             : 
    2527             :   // Compute the {cache} index for {code}.
    2528         203 :   Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code);
    2529             : 
    2530             :   // Check if we have an entry for the {code} in the single character string
    2531             :   // cache already.
    2532             :   Node* entry =
    2533         203 :       __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index);
    2534             : 
    2535         203 :   Node* check1 = __ WordEqual(entry, __ UndefinedConstant());
    2536         203 :   __ GotoIf(check1, &runtime_call);
    2537             :   __ Goto(&done, entry);
    2538             : 
    2539             :   // Let %StringFromCharCode handle this case.
    2540             :   // TODO(turbofan): At some point we may consider adding a stub for this
    2541             :   // deferred case, so that we don't need to call to C++ here.
    2542             :   __ Bind(&runtime_call);
    2543             :   {
    2544         203 :     Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
    2545             :     Runtime::FunctionId id = Runtime::kStringCharFromCode;
    2546             :     CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
    2547         203 :         graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags);
    2548             :     Node* vtrue1 =
    2549             :         __ Call(desc, __ CEntryStubConstant(1), ChangeInt32ToSmi(code),
    2550             :                 __ ExternalConstant(ExternalReference(id, isolate())),
    2551         406 :                 __ Int32Constant(1), __ NoContextConstant());
    2552             :     __ Goto(&done, vtrue1);
    2553             :   }
    2554             :   __ Bind(&done);
    2555         203 :   return done.PhiAt(0);
    2556             : }
    2557             : 
    2558             : #ifdef V8_INTL_SUPPORT
    2559             : 
    2560           0 : Node* EffectControlLinearizer::LowerStringToLowerCaseIntl(Node* node) {
    2561             :   Node* receiver = node->InputAt(0);
    2562             : 
    2563             :   Callable callable =
    2564           0 :       Builtins::CallableFor(isolate(), Builtins::kStringToLowerCaseIntl);
    2565           0 :   Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
    2566             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    2567             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    2568           0 :       isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
    2569             :   return __ Call(desc, __ HeapConstant(callable.code()), receiver,
    2570           0 :                  __ NoContextConstant());
    2571             : }
    2572             : 
    2573           0 : Node* EffectControlLinearizer::LowerStringToUpperCaseIntl(Node* node) {
    2574             :   Node* receiver = node->InputAt(0);
    2575           0 :   Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
    2576             :   Runtime::FunctionId id = Runtime::kStringToUpperCaseIntl;
    2577             :   CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
    2578           0 :       graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags);
    2579             :   return __ Call(desc, __ CEntryStubConstant(1), receiver,
    2580             :                  __ ExternalConstant(ExternalReference(id, isolate())),
    2581           0 :                  __ Int32Constant(1), __ NoContextConstant());
    2582             : }
    2583             : 
    2584             : #else
    2585             : 
    2586             : Node* EffectControlLinearizer::LowerStringToLowerCaseIntl(Node* node) {
    2587             :   UNREACHABLE();
    2588             :   return nullptr;
    2589             : }
    2590             : 
    2591             : Node* EffectControlLinearizer::LowerStringToUpperCaseIntl(Node* node) {
    2592             :   UNREACHABLE();
    2593             :   return nullptr;
    2594             : }
    2595             : 
    2596             : #endif  // V8_INTL_SUPPORT
    2597             : 
    2598          78 : Node* EffectControlLinearizer::LowerStringFromCodePoint(Node* node) {
    2599             :   Node* value = node->InputAt(0);
    2600             :   Node* code = value;
    2601             : 
    2602          39 :   auto if_not_single_code = __ MakeDeferredLabel();
    2603          39 :   auto if_not_one_byte = __ MakeDeferredLabel();
    2604          39 :   auto cache_miss = __ MakeDeferredLabel();
    2605          39 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    2606             : 
    2607             :   // Check if the {code} is a single code unit
    2608          39 :   Node* check0 = __ Uint32LessThanOrEqual(code, __ Uint32Constant(0xFFFF));
    2609          39 :   __ GotoIfNot(check0, &if_not_single_code);
    2610             : 
    2611             :   {
    2612             :     // Check if the {code} is a one byte character
    2613             :     Node* check1 = __ Uint32LessThanOrEqual(
    2614          39 :         code, __ Uint32Constant(String::kMaxOneByteCharCode));
    2615          39 :     __ GotoIfNot(check1, &if_not_one_byte);
    2616             :     {
    2617             :       // Load the isolate wide single character string cache.
    2618          39 :       Node* cache = __ HeapConstant(factory()->single_character_string_cache());
    2619             : 
    2620             :       // Compute the {cache} index for {code}.
    2621          39 :       Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code);
    2622             : 
    2623             :       // Check if we have an entry for the {code} in the single character string
    2624             :       // cache already.
    2625             :       Node* entry =
    2626          39 :           __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index);
    2627             : 
    2628          39 :       Node* check2 = __ WordEqual(entry, __ UndefinedConstant());
    2629          39 :       __ GotoIf(check2, &cache_miss);
    2630             : 
    2631             :       // Use the {entry} from the {cache}.
    2632             :       __ Goto(&done, entry);
    2633             : 
    2634             :       __ Bind(&cache_miss);
    2635             :       {
    2636             :         // Allocate a new SeqOneByteString for {code}.
    2637             :         Node* vtrue2 = __ Allocate(
    2638          39 :             NOT_TENURED, __ Int32Constant(SeqOneByteString::SizeFor(1)));
    2639             :         __ StoreField(AccessBuilder::ForMap(), vtrue2,
    2640          39 :                       __ HeapConstant(factory()->one_byte_string_map()));
    2641             :         __ StoreField(AccessBuilder::ForNameHashField(), vtrue2,
    2642          39 :                       __ IntPtrConstant(Name::kEmptyHashField));
    2643             :         __ StoreField(AccessBuilder::ForStringLength(), vtrue2,
    2644          39 :                       __ SmiConstant(1));
    2645             :         __ Store(
    2646             :             StoreRepresentation(MachineRepresentation::kWord8, kNoWriteBarrier),
    2647             :             vtrue2,
    2648             :             __ IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag),
    2649          78 :             code);
    2650             : 
    2651             :         // Remember it in the {cache}.
    2652             :         __ StoreElement(AccessBuilder::ForFixedArrayElement(), cache, index,
    2653          39 :                         vtrue2);
    2654             :         __ Goto(&done, vtrue2);
    2655             :       }
    2656             :     }
    2657             : 
    2658             :     __ Bind(&if_not_one_byte);
    2659             :     {
    2660             :       // Allocate a new SeqTwoByteString for {code}.
    2661             :       Node* vfalse1 = __ Allocate(
    2662          39 :           NOT_TENURED, __ Int32Constant(SeqTwoByteString::SizeFor(1)));
    2663             :       __ StoreField(AccessBuilder::ForMap(), vfalse1,
    2664          39 :                     __ HeapConstant(factory()->string_map()));
    2665             :       __ StoreField(AccessBuilder::ForNameHashField(), vfalse1,
    2666          39 :                     __ IntPtrConstant(Name::kEmptyHashField));
    2667             :       __ StoreField(AccessBuilder::ForStringLength(), vfalse1,
    2668          39 :                     __ SmiConstant(1));
    2669             :       __ Store(
    2670             :           StoreRepresentation(MachineRepresentation::kWord16, kNoWriteBarrier),
    2671             :           vfalse1,
    2672             :           __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag),
    2673          78 :           code);
    2674             :       __ Goto(&done, vfalse1);
    2675             :     }
    2676             :   }
    2677             : 
    2678             :   __ Bind(&if_not_single_code);
    2679             :   // Generate surrogate pair string
    2680             :   {
    2681          39 :     switch (UnicodeEncodingOf(node->op())) {
    2682             :       case UnicodeEncoding::UTF16:
    2683             :         break;
    2684             : 
    2685             :       case UnicodeEncoding::UTF32: {
    2686             :         // Convert UTF32 to UTF16 code units, and store as a 32 bit word.
    2687           0 :         Node* lead_offset = __ Int32Constant(0xD800 - (0x10000 >> 10));
    2688             : 
    2689             :         // lead = (codepoint >> 10) + LEAD_OFFSET
    2690             :         Node* lead =
    2691           0 :             __ Int32Add(__ Word32Shr(code, __ Int32Constant(10)), lead_offset);
    2692             : 
    2693             :         // trail = (codepoint & 0x3FF) + 0xDC00;
    2694             :         Node* trail = __ Int32Add(__ Word32And(code, __ Int32Constant(0x3FF)),
    2695           0 :                                   __ Int32Constant(0xDC00));
    2696             : 
    2697             :         // codpoint = (trail << 16) | lead;
    2698           0 :         code = __ Word32Or(__ Word32Shl(trail, __ Int32Constant(16)), lead);
    2699           0 :         break;
    2700             :       }
    2701             :     }
    2702             : 
    2703             :     // Allocate a new SeqTwoByteString for {code}.
    2704             :     Node* vfalse0 = __ Allocate(NOT_TENURED,
    2705          39 :                                 __ Int32Constant(SeqTwoByteString::SizeFor(2)));
    2706             :     __ StoreField(AccessBuilder::ForMap(), vfalse0,
    2707          39 :                   __ HeapConstant(factory()->string_map()));
    2708             :     __ StoreField(AccessBuilder::ForNameHashField(), vfalse0,
    2709          39 :                   __ IntPtrConstant(Name::kEmptyHashField));
    2710          39 :     __ StoreField(AccessBuilder::ForStringLength(), vfalse0, __ SmiConstant(2));
    2711             :     __ Store(
    2712             :         StoreRepresentation(MachineRepresentation::kWord32, kNoWriteBarrier),
    2713             :         vfalse0,
    2714             :         __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag),
    2715          78 :         code);
    2716             :     __ Goto(&done, vfalse0);
    2717             :   }
    2718             : 
    2719             :   __ Bind(&done);
    2720          39 :   return done.PhiAt(0);
    2721             : }
    2722             : 
    2723         195 : Node* EffectControlLinearizer::LowerStringIndexOf(Node* node) {
    2724             :   Node* subject = node->InputAt(0);
    2725             :   Node* search_string = node->InputAt(1);
    2726             :   Node* position = node->InputAt(2);
    2727             : 
    2728             :   Callable callable =
    2729         195 :       Builtins::CallableFor(isolate(), Builtins::kStringIndexOf);
    2730             :   Operator::Properties properties = Operator::kEliminatable;
    2731             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    2732             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    2733         585 :       isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
    2734             :   return __ Call(desc, __ HeapConstant(callable.code()), subject, search_string,
    2735         390 :                  position, __ NoContextConstant());
    2736             : }
    2737             : 
    2738        6500 : Node* EffectControlLinearizer::LowerStringComparison(Callable const& callable,
    2739             :                                                      Node* node) {
    2740             :   Node* lhs = node->InputAt(0);
    2741             :   Node* rhs = node->InputAt(1);
    2742             : 
    2743             :   Operator::Properties properties = Operator::kEliminatable;
    2744             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    2745             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    2746       19500 :       isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
    2747             :   return __ Call(desc, __ HeapConstant(callable.code()), lhs, rhs,
    2748       13000 :                  __ NoContextConstant());
    2749             : }
    2750             : 
    2751        5673 : Node* EffectControlLinearizer::LowerStringEqual(Node* node) {
    2752             :   return LowerStringComparison(
    2753        5673 :       Builtins::CallableFor(isolate(), Builtins::kStringEqual), node);
    2754             : }
    2755             : 
    2756         516 : Node* EffectControlLinearizer::LowerStringLessThan(Node* node) {
    2757             :   return LowerStringComparison(
    2758         516 :       Builtins::CallableFor(isolate(), Builtins::kStringLessThan), node);
    2759             : }
    2760             : 
    2761         311 : Node* EffectControlLinearizer::LowerStringLessThanOrEqual(Node* node) {
    2762             :   return LowerStringComparison(
    2763         311 :       Builtins::CallableFor(isolate(), Builtins::kStringLessThanOrEqual), node);
    2764             : }
    2765             : 
    2766         626 : Node* EffectControlLinearizer::LowerCheckFloat64Hole(Node* node,
    2767             :                                                      Node* frame_state) {
    2768             :   // If we reach this point w/o eliminating the {node} that's marked
    2769             :   // with allow-return-hole, we cannot do anything, so just deoptimize
    2770             :   // in case of the hole NaN (similar to Crankshaft).
    2771             :   Node* value = node->InputAt(0);
    2772             :   Node* check = __ Word32Equal(__ Float64ExtractHighWord32(value),
    2773         626 :                                __ Int32Constant(kHoleNanUpper32));
    2774         626 :   __ DeoptimizeIf(DeoptimizeReason::kHole, check, frame_state);
    2775         626 :   return value;
    2776             : }
    2777             : 
    2778             : 
    2779        1087 : Node* EffectControlLinearizer::LowerCheckNotTaggedHole(Node* node,
    2780             :                                                        Node* frame_state) {
    2781             :   Node* value = node->InputAt(0);
    2782        1087 :   Node* check = __ WordEqual(value, __ TheHoleConstant());
    2783        1087 :   __ DeoptimizeIf(DeoptimizeReason::kHole, check, frame_state);
    2784        1087 :   return value;
    2785             : }
    2786             : 
    2787        1215 : Node* EffectControlLinearizer::LowerConvertTaggedHoleToUndefined(Node* node) {
    2788             :   Node* value = node->InputAt(0);
    2789             : 
    2790        1215 :   auto if_is_hole = __ MakeDeferredLabel();
    2791        1215 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    2792             : 
    2793        1215 :   Node* check = __ WordEqual(value, __ TheHoleConstant());
    2794        1215 :   __ GotoIf(check, &if_is_hole);
    2795             :   __ Goto(&done, value);
    2796             : 
    2797             :   __ Bind(&if_is_hole);
    2798        1215 :   __ Goto(&done, __ UndefinedConstant());
    2799             : 
    2800             :   __ Bind(&done);
    2801        1215 :   return done.PhiAt(0);
    2802             : }
    2803             : 
    2804         102 : void EffectControlLinearizer::LowerCheckEqualsInternalizedString(
    2805             :     Node* node, Node* frame_state) {
    2806             :   Node* exp = node->InputAt(0);
    2807             :   Node* val = node->InputAt(1);
    2808             : 
    2809         102 :   auto if_same = __ MakeLabel();
    2810         102 :   auto if_notsame = __ MakeDeferredLabel();
    2811         102 :   auto if_thinstring = __ MakeLabel();
    2812         102 :   auto if_notthinstring = __ MakeLabel();
    2813             : 
    2814             :   // Check if {exp} and {val} are the same, which is the likely case.
    2815         102 :   __ Branch(__ WordEqual(exp, val), &if_same, &if_notsame);
    2816             : 
    2817             :   __ Bind(&if_notsame);
    2818             :   {
    2819             :     // Now {val} could still be a non-internalized String that matches {exp}.
    2820             :     __ DeoptimizeIf(DeoptimizeReason::kWrongName, ObjectIsSmi(val),
    2821         102 :                     frame_state);
    2822         102 :     Node* val_map = __ LoadField(AccessBuilder::ForMap(), val);
    2823             :     Node* val_instance_type =
    2824         102 :         __ LoadField(AccessBuilder::ForMapInstanceType(), val_map);
    2825             : 
    2826             :     // Check for the common case of ThinString first.
    2827             :     __ GotoIf(__ Word32Equal(val_instance_type,
    2828             :                              __ Int32Constant(THIN_ONE_BYTE_STRING_TYPE)),
    2829         102 :               &if_thinstring);
    2830             :     __ Branch(
    2831             :         __ Word32Equal(val_instance_type, __ Int32Constant(THIN_STRING_TYPE)),
    2832         102 :         &if_thinstring, &if_notthinstring);
    2833             : 
    2834             :     __ Bind(&if_notthinstring);
    2835             :     {
    2836             :       // Check that the {val} is a non-internalized String, if it's anything
    2837             :       // else it cannot match the recorded feedback {exp} anyways.
    2838             :       __ DeoptimizeIfNot(
    2839             :           DeoptimizeReason::kWrongName,
    2840             :           __ Word32Equal(__ Word32And(val_instance_type,
    2841             :                                       __ Int32Constant(kIsNotStringMask |
    2842             :                                                        kIsNotInternalizedMask)),
    2843             :                          __ Int32Constant(kStringTag | kNotInternalizedTag)),
    2844         102 :           frame_state);
    2845             : 
    2846             :       // Try to find the {val} in the string table.
    2847         102 :       MachineSignature::Builder builder(graph()->zone(), 1, 1);
    2848             :       builder.AddReturn(MachineType::AnyTagged());
    2849             :       builder.AddParam(MachineType::AnyTagged());
    2850             :       Node* try_internalize_string_function = __ ExternalConstant(
    2851         102 :           ExternalReference::try_internalize_string_function(isolate()));
    2852             :       CallDescriptor const* const desc =
    2853         204 :           Linkage::GetSimplifiedCDescriptor(graph()->zone(), builder.Build());
    2854             :       Node* val_internalized =
    2855         102 :           __ Call(common()->Call(desc), try_internalize_string_function, val);
    2856             : 
    2857             :       // Now see if the results match.
    2858             :       __ DeoptimizeIfNot(DeoptimizeReason::kWrongName,
    2859         102 :                          __ WordEqual(exp, val_internalized), frame_state);
    2860             :       __ Goto(&if_same);
    2861             :     }
    2862             : 
    2863             :     __ Bind(&if_thinstring);
    2864             :     {
    2865             :       // The {val} is a ThinString, let's check the actual value.
    2866             :       Node* val_actual =
    2867         102 :           __ LoadField(AccessBuilder::ForThinStringActual(), val);
    2868             :       __ DeoptimizeIfNot(DeoptimizeReason::kWrongName,
    2869         102 :                          __ WordEqual(exp, val_actual), frame_state);
    2870             :       __ Goto(&if_same);
    2871             :     }
    2872             :   }
    2873             : 
    2874             :   __ Bind(&if_same);
    2875         102 : }
    2876             : 
    2877          62 : void EffectControlLinearizer::LowerCheckEqualsSymbol(Node* node,
    2878             :                                                      Node* frame_state) {
    2879             :   Node* exp = node->InputAt(0);
    2880             :   Node* val = node->InputAt(1);
    2881          62 :   Node* check = __ WordEqual(exp, val);
    2882          62 :   __ DeoptimizeIfNot(DeoptimizeReason::kWrongName, check, frame_state);
    2883          62 : }
    2884             : 
    2885       42742 : Node* EffectControlLinearizer::AllocateHeapNumberWithValue(Node* value) {
    2886       42742 :   Node* result = __ Allocate(NOT_TENURED, __ Int32Constant(HeapNumber::kSize));
    2887       42742 :   __ StoreField(AccessBuilder::ForMap(), result, __ HeapNumberMapConstant());
    2888       42742 :   __ StoreField(AccessBuilder::ForHeapNumberValue(), result, value);
    2889       42742 :   return result;
    2890             : }
    2891             : 
    2892      108052 : Node* EffectControlLinearizer::ChangeInt32ToSmi(Node* value) {
    2893      108052 :   if (machine()->Is64()) {
    2894      108054 :     value = __ ChangeInt32ToInt64(value);
    2895             :   }
    2896      108056 :   return __ WordShl(value, SmiShiftBitsConstant());
    2897             : }
    2898             : 
    2899           0 : Node* EffectControlLinearizer::ChangeIntPtrToInt32(Node* value) {
    2900           0 :   if (machine()->Is64()) {
    2901           0 :     value = __ TruncateInt64ToInt32(value);
    2902             :   }
    2903           0 :   return value;
    2904             : }
    2905             : 
    2906           0 : Node* EffectControlLinearizer::ChangeUint32ToUintPtr(Node* value) {
    2907         910 :   if (machine()->Is64()) {
    2908         910 :     value = __ ChangeUint32ToUint64(value);
    2909             :   }
    2910           0 :   return value;
    2911             : }
    2912             : 
    2913         556 : Node* EffectControlLinearizer::ChangeUint32ToSmi(Node* value) {
    2914             :   value = ChangeUint32ToUintPtr(value);
    2915         556 :   return __ WordShl(value, SmiShiftBitsConstant());
    2916             : }
    2917             : 
    2918      160622 : Node* EffectControlLinearizer::ChangeSmiToIntPtr(Node* value) {
    2919      160627 :   return __ WordSar(value, SmiShiftBitsConstant());
    2920             : }
    2921             : 
    2922      160626 : Node* EffectControlLinearizer::ChangeSmiToInt32(Node* value) {
    2923      160626 :   value = ChangeSmiToIntPtr(value);
    2924      160626 :   if (machine()->Is64()) {
    2925      160626 :     value = __ TruncateInt64ToInt32(value);
    2926             :   }
    2927      160626 :   return value;
    2928             : }
    2929             : 
    2930      270734 : Node* EffectControlLinearizer::ObjectIsSmi(Node* value) {
    2931             :   return __ WordEqual(__ WordAnd(value, __ IntPtrConstant(kSmiTagMask)),
    2932      270734 :                       __ IntPtrConstant(kSmiTag));
    2933             : }
    2934             : 
    2935           0 : Node* EffectControlLinearizer::SmiMaxValueConstant() {
    2936         556 :   return __ Int32Constant(Smi::kMaxValue);
    2937             : }
    2938             : 
    2939           0 : Node* EffectControlLinearizer::SmiShiftBitsConstant() {
    2940      269231 :   return __ IntPtrConstant(kSmiShiftSize + kSmiTagSize);
    2941             : }
    2942             : 
    2943          36 : Node* EffectControlLinearizer::LowerPlainPrimitiveToNumber(Node* node) {
    2944             :   Node* value = node->InputAt(0);
    2945          36 :   return __ ToNumber(value);
    2946             : }
    2947             : 
    2948         192 : Node* EffectControlLinearizer::LowerPlainPrimitiveToWord32(Node* node) {
    2949             :   Node* value = node->InputAt(0);
    2950             : 
    2951         192 :   auto if_not_smi = __ MakeDeferredLabel();
    2952         192 :   auto if_to_number_smi = __ MakeLabel();
    2953         192 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    2954             : 
    2955         192 :   Node* check0 = ObjectIsSmi(value);
    2956         192 :   __ GotoIfNot(check0, &if_not_smi);
    2957         192 :   __ Goto(&done, ChangeSmiToInt32(value));
    2958             : 
    2959             :   __ Bind(&if_not_smi);
    2960         192 :   Node* to_number = __ ToNumber(value);
    2961             : 
    2962         192 :   Node* check1 = ObjectIsSmi(to_number);
    2963         192 :   __ GotoIf(check1, &if_to_number_smi);
    2964         192 :   Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), to_number);
    2965         192 :   __ Goto(&done, __ TruncateFloat64ToWord32(number));
    2966             : 
    2967             :   __ Bind(&if_to_number_smi);
    2968         192 :   __ Goto(&done, ChangeSmiToInt32(to_number));
    2969             : 
    2970             :   __ Bind(&done);
    2971         192 :   return done.PhiAt(0);
    2972             : }
    2973             : 
    2974        9090 : Node* EffectControlLinearizer::LowerPlainPrimitiveToFloat64(Node* node) {
    2975             :   Node* value = node->InputAt(0);
    2976             : 
    2977        9090 :   auto if_not_smi = __ MakeDeferredLabel();
    2978        9090 :   auto if_to_number_smi = __ MakeLabel();
    2979        9090 :   auto done = __ MakeLabel(MachineRepresentation::kFloat64);
    2980             : 
    2981        9090 :   Node* check0 = ObjectIsSmi(value);
    2982        9090 :   __ GotoIfNot(check0, &if_not_smi);
    2983        9090 :   Node* from_smi = ChangeSmiToInt32(value);
    2984        9090 :   __ Goto(&done, __ ChangeInt32ToFloat64(from_smi));
    2985             : 
    2986             :   __ Bind(&if_not_smi);
    2987        9090 :   Node* to_number = __ ToNumber(value);
    2988        9090 :   Node* check1 = ObjectIsSmi(to_number);
    2989        9090 :   __ GotoIf(check1, &if_to_number_smi);
    2990             : 
    2991        9090 :   Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), to_number);
    2992             :   __ Goto(&done, number);
    2993             : 
    2994             :   __ Bind(&if_to_number_smi);
    2995        9090 :   Node* number_from_smi = ChangeSmiToInt32(to_number);
    2996        9090 :   number_from_smi = __ ChangeInt32ToFloat64(number_from_smi);
    2997             :   __ Goto(&done, number_from_smi);
    2998             : 
    2999             :   __ Bind(&done);
    3000        9090 :   return done.PhiAt(0);
    3001             : }
    3002             : 
    3003         351 : Node* EffectControlLinearizer::LowerEnsureWritableFastElements(Node* node) {
    3004             :   Node* object = node->InputAt(0);
    3005             :   Node* elements = node->InputAt(1);
    3006             : 
    3007         351 :   auto if_not_fixed_array = __ MakeDeferredLabel();
    3008         351 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    3009             : 
    3010             :   // Load the current map of {elements}.
    3011         351 :   Node* elements_map = __ LoadField(AccessBuilder::ForMap(), elements);
    3012             : 
    3013             :   // Check if {elements} is not a copy-on-write FixedArray.
    3014         351 :   Node* check = __ WordEqual(elements_map, __ FixedArrayMapConstant());
    3015         351 :   __ GotoIfNot(check, &if_not_fixed_array);
    3016             :   // Nothing to do if the {elements} are not copy-on-write.
    3017             :   __ Goto(&done, elements);
    3018             : 
    3019             :   __ Bind(&if_not_fixed_array);
    3020             :   // We need to take a copy of the {elements} and set them up for {object}.
    3021             :   Operator::Properties properties = Operator::kEliminatable;
    3022             :   Callable callable =
    3023         351 :       Builtins::CallableFor(isolate(), Builtins::kCopyFastSmiOrObjectElements);
    3024             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    3025             :   CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
    3026        1053 :       isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
    3027             :   Node* result = __ Call(desc, __ HeapConstant(callable.code()), object,
    3028         702 :                          __ NoContextConstant());
    3029             :   __ Goto(&done, result);
    3030             : 
    3031             :   __ Bind(&done);
    3032         351 :   return done.PhiAt(0);
    3033             : }
    3034             : 
    3035        2956 : Node* EffectControlLinearizer::LowerMaybeGrowFastElements(Node* node,
    3036             :                                                           Node* frame_state) {
    3037        2956 :   GrowFastElementsMode mode = GrowFastElementsModeOf(node->op());
    3038             :   Node* object = node->InputAt(0);
    3039             :   Node* elements = node->InputAt(1);
    3040             :   Node* index = node->InputAt(2);
    3041             :   Node* elements_length = node->InputAt(3);
    3042             : 
    3043        2956 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    3044        2956 :   auto if_grow = __ MakeDeferredLabel();
    3045             :   auto if_not_grow = __ MakeLabel();
    3046             : 
    3047             :   // Check if we need to grow the {elements} backing store.
    3048        2956 :   Node* check = __ Uint32LessThan(index, elements_length);
    3049        2956 :   __ GotoIfNot(check, &if_grow);
    3050             :   __ Goto(&done, elements);
    3051             : 
    3052             :   __ Bind(&if_grow);
    3053             :   // We need to grow the {elements} for {object}.
    3054             :   Operator::Properties properties = Operator::kEliminatable;
    3055             :   Callable callable =
    3056             :       (mode == GrowFastElementsMode::kDoubleElements)
    3057             :           ? Builtins::CallableFor(isolate(), Builtins::kGrowFastDoubleElements)
    3058             :           : Builtins::CallableFor(isolate(),
    3059        5912 :                                   Builtins::kGrowFastSmiOrObjectElements);
    3060             :   CallDescriptor::Flags call_flags = CallDescriptor::kNoFlags;
    3061             :   CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
    3062             :       isolate(), graph()->zone(), callable.descriptor(), 0, call_flags,
    3063        8868 :       properties);
    3064             :   Node* new_elements = __ Call(desc, __ HeapConstant(callable.code()), object,
    3065        5912 :                                ChangeInt32ToSmi(index), __ NoContextConstant());
    3066             : 
    3067             :   // Ensure that we were able to grow the {elements}.
    3068             :   // TODO(turbofan): We use kSmi as reason here similar to Crankshaft,
    3069             :   // but maybe we should just introduce a reason that makes sense.
    3070             :   __ DeoptimizeIf(DeoptimizeReason::kSmi, ObjectIsSmi(new_elements),
    3071        2956 :                   frame_state);
    3072             :   __ Goto(&done, new_elements);
    3073             : 
    3074             :   __ Bind(&done);
    3075        2956 :   return done.PhiAt(0);
    3076             : }
    3077             : 
    3078         569 : void EffectControlLinearizer::LowerTransitionElementsKind(Node* node) {
    3079         569 :   ElementsTransition const transition = ElementsTransitionOf(node->op());
    3080             :   Node* object = node->InputAt(0);
    3081             : 
    3082         569 :   auto if_map_same = __ MakeDeferredLabel();
    3083         569 :   auto done = __ MakeLabel();
    3084             : 
    3085         569 :   Node* source_map = __ HeapConstant(transition.source());
    3086         569 :   Node* target_map = __ HeapConstant(transition.target());
    3087             : 
    3088             :   // Load the current map of {object}.
    3089         569 :   Node* object_map = __ LoadField(AccessBuilder::ForMap(), object);
    3090             : 
    3091             :   // Check if {object_map} is the same as {source_map}.
    3092         569 :   Node* check = __ WordEqual(object_map, source_map);
    3093         569 :   __ GotoIf(check, &if_map_same);
    3094             :   __ Goto(&done);
    3095             : 
    3096             :   __ Bind(&if_map_same);
    3097         569 :   switch (transition.mode()) {
    3098             :     case ElementsTransition::kFastTransition:
    3099             :       // In-place migration of {object}, just store the {target_map}.
    3100         205 :       __ StoreField(AccessBuilder::ForMap(), object, target_map);
    3101         205 :       break;
    3102             :     case ElementsTransition::kSlowTransition: {
    3103             :       // Instance migration, call out to the runtime for {object}.
    3104         364 :       Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
    3105             :       Runtime::FunctionId id = Runtime::kTransitionElementsKind;
    3106             :       CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
    3107         364 :           graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags);
    3108             :       __ Call(desc, __ CEntryStubConstant(1), object, target_map,
    3109             :               __ ExternalConstant(ExternalReference(id, isolate())),
    3110         728 :               __ Int32Constant(2), __ NoContextConstant());
    3111             :       break;
    3112             :     }
    3113             :   }
    3114             :   __ Goto(&done);
    3115             : 
    3116             :   __ Bind(&done);
    3117         569 : }
    3118             : 
    3119        2119 : Node* EffectControlLinearizer::LowerLoadFieldByIndex(Node* node) {
    3120             :   Node* object = node->InputAt(0);
    3121             :   Node* index = node->InputAt(1);
    3122        2119 :   Node* zero = __ IntPtrConstant(0);
    3123        2119 :   Node* one = __ IntPtrConstant(1);
    3124             : 
    3125             :   // Sign-extend the {index} on 64-bit architectures.
    3126        2119 :   if (machine()->Is64()) {
    3127        2119 :     index = __ ChangeInt32ToInt64(index);
    3128             :   }
    3129             : 
    3130        2119 :   auto if_double = __ MakeDeferredLabel();
    3131        2119 :   auto done = __ MakeLabel(MachineRepresentation::kTagged);
    3132             : 
    3133             :   // Check if field is a mutable double field.
    3134        2119 :   __ GotoIfNot(__ WordEqual(__ WordAnd(index, one), zero), &if_double);
    3135             : 
    3136             :   // The field is a proper Tagged field on {object}. The {index} is shifted
    3137             :   // to the left by one in the code below.
    3138             :   {
    3139             :     // Check if field is in-object or out-of-object.
    3140        2119 :     auto if_outofobject = __ MakeLabel();
    3141        2119 :     __ GotoIf(__ IntLessThan(index, zero), &if_outofobject);
    3142             : 
    3143             :     // The field is located in the {object} itself.
    3144             :     {
    3145             :       Node* offset =
    3146             :           __ IntAdd(__ WordShl(index, __ IntPtrConstant(kPointerSizeLog2 - 1)),
    3147        2119 :                     __ IntPtrConstant(JSObject::kHeaderSize - kHeapObjectTag));
    3148        2119 :       Node* result = __ Load(MachineType::AnyTagged(), object, offset);
    3149             :       __ Goto(&done, result);
    3150             :     }
    3151             : 
    3152             :     // The field is located in the properties backing store of {object}.
    3153             :     // The {index} is equal to the negated out of property index plus 1.
    3154             :     __ Bind(&if_outofobject);
    3155             :     {
    3156             :       Node* properties =
    3157        2119 :           __ LoadField(AccessBuilder::ForJSObjectPropertiesOrHash(), object);
    3158             :       Node* offset =
    3159             :           __ IntAdd(__ WordShl(__ IntSub(zero, index),
    3160             :                                __ IntPtrConstant(kPointerSizeLog2 - 1)),
    3161             :                     __ IntPtrConstant((FixedArray::kHeaderSize - kPointerSize) -
    3162        2119 :                                       kHeapObjectTag));
    3163        2119 :       Node* result = __ Load(MachineType::AnyTagged(), properties, offset);
    3164             :       __ Goto(&done, result);
    3165             :     }
    3166             :   }
    3167             : 
    3168             :   // The field is a Double field, either unboxed in the object on 64-bit
    3169             :   // architectures, or as MutableHeapNumber.
    3170             :   __ Bind(&if_double);
    3171             :   {
    3172        2119 :     auto done_double = __ MakeLabel(MachineRepresentation::kFloat64);
    3173             : 
    3174        2119 :     index = __ WordSar(index, one);
    3175             : 
    3176             :     // Check if field is in-object or out-of-object.
    3177        2119 :     auto if_outofobject = __ MakeLabel();
    3178        2119 :     __ GotoIf(__ IntLessThan(index, zero), &if_outofobject);
    3179             : 
    3180             :     // The field is located in the {object} itself.
    3181             :     {
    3182             :       Node* offset =
    3183             :           __ IntAdd(__ WordShl(index, __ IntPtrConstant(kPointerSizeLog2)),
    3184        2119 :                     __ IntPtrConstant(JSObject::kHeaderSize - kHeapObjectTag));
    3185             :       if (FLAG_unbox_double_fields) {
    3186        2119 :         Node* result = __ Load(MachineType::Float64(), object, offset);
    3187             :         __ Goto(&done_double, result);
    3188             :       } else {
    3189             :         Node* result = __ Load(MachineType::AnyTagged(), object, offset);
    3190             :         result = __ LoadField(AccessBuilder::ForHeapNumberValue(), result);
    3191             :         __ Goto(&done_double, result);
    3192             :       }
    3193             :     }
    3194             : 
    3195             :     __ Bind(&if_outofobject);
    3196             :     {
    3197             :       Node* properties =
    3198        2119 :           __ LoadField(AccessBuilder::ForJSObjectPropertiesOrHash(), object);
    3199             :       Node* offset =
    3200             :           __ IntAdd(__ WordShl(__ IntSub(zero, index),
    3201             :                                __ IntPtrConstant(kPointerSizeLog2)),
    3202             :                     __ IntPtrConstant((FixedArray::kHeaderSize - kPointerSize) -
    3203        2119 :                                       kHeapObjectTag));
    3204        2119 :       Node* result = __ Load(MachineType::AnyTagged(), properties, offset);
    3205        2119 :       result = __ LoadField(AccessBuilder::ForHeapNumberValue(), result);
    3206             :       __ Goto(&done_double, result);
    3207             :     }
    3208             : 
    3209             :     __ Bind(&done_double);
    3210             :     {
    3211        2119 :       Node* result = AllocateHeapNumberWithValue(done_double.PhiAt(0));
    3212             :       __ Goto(&done, result);
    3213             :     }
    3214             :   }
    3215             : 
    3216             :   __ Bind(&done);
    3217        2119 :   return done.PhiAt(0);
    3218             : }
    3219             : 
    3220        6159 : Node* EffectControlLinearizer::LowerLoadTypedElement(Node* node) {
    3221        6159 :   ExternalArrayType array_type = ExternalArrayTypeOf(node->op());
    3222             :   Node* buffer = node->InputAt(0);
    3223             :   Node* base = node->InputAt(1);
    3224             :   Node* external = node->InputAt(2);
    3225             :   Node* index = node->InputAt(3);
    3226             : 
    3227             :   // We need to keep the {buffer} alive so that the GC will not release the
    3228             :   // ArrayBuffer (if there's any) as long as we are still operating on it.
    3229        6159 :   __ Retain(buffer);
    3230             : 
    3231             :   // Compute the effective storage pointer, handling the case where the
    3232             :   // {external} pointer is the effective storage pointer (i.e. the {base}
    3233             :   // is Smi zero).
    3234             :   Node* storage = NumberMatcher(base).Is(0) ? external : __ UnsafePointerAdd(
    3235        6159 :                                                              base, external);
    3236             : 
    3237             :   // Perform the actual typed element access.
    3238             :   return __ LoadElement(AccessBuilder::ForTypedArrayElement(array_type, true),
    3239        6159 :                         storage, index);
    3240             : }
    3241             : 
    3242        6033 : void EffectControlLinearizer::LowerStoreTypedElement(Node* node) {
    3243        6033 :   ExternalArrayType array_type = ExternalArrayTypeOf(node->op());
    3244             :   Node* buffer = node->InputAt(0);
    3245             :   Node* base = node->InputAt(1);
    3246             :   Node* external = node->InputAt(2);
    3247             :   Node* index = node->InputAt(3);
    3248             :   Node* value = node->InputAt(4);
    3249             : 
    3250             :   // We need to keep the {buffer} alive so that the GC will not release the
    3251             :   // ArrayBuffer (if there's any) as long as we are still operating on it.
    3252        6033 :   __ Retain(buffer);
    3253             : 
    3254             :   // Compute the effective storage pointer, handling the case where the
    3255             :   // {external} pointer is the effective storage pointer (i.e. the {base}
    3256             :   // is Smi zero).
    3257             :   Node* storage = NumberMatcher(base).Is(0) ? external : __ UnsafePointerAdd(
    3258        6033 :                                                              base, external);
    3259             : 
    3260             :   // Perform the actual typed element access.
    3261             :   __ StoreElement(AccessBuilder::ForTypedArrayElement(array_type, true),
    3262        6033 :                   storage, index, value);
    3263        6033 : }
    3264             : 
    3265         484 : void EffectControlLinearizer::TransitionElementsTo(Node* node, Node* array,
    3266             :                                                    ElementsKind from,
    3267             :                                                    ElementsKind to) {
    3268             :   DCHECK(IsMoreGeneralElementsKindTransition(from, to));
    3269             :   DCHECK(to == HOLEY_ELEMENTS || to == HOLEY_DOUBLE_ELEMENTS);
    3270             : 
    3271             :   Handle<Map> target(to == HOLEY_ELEMENTS ? FastMapParameterOf(node->op())
    3272         484 :                                           : DoubleMapParameterOf(node->op()));
    3273         242 :   Node* target_map = __ HeapConstant(target);
    3274             : 
    3275         242 :   if (IsSimpleMapChangeTransition(from, to)) {
    3276          76 :     __ StoreField(AccessBuilder::ForMap(), array, target_map);
    3277             :   } else {
    3278             :     // Instance migration, call out to the runtime for {array}.
    3279         166 :     Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
    3280             :     Runtime::FunctionId id = Runtime::kTransitionElementsKind;
    3281             :     CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
    3282         166 :         graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags);
    3283             :     __ Call(desc, __ CEntryStubConstant(1), array, target_map,
    3284             :             __ ExternalConstant(ExternalReference(id, isolate())),
    3285         332 :             __ Int32Constant(2), __ NoContextConstant());
    3286             :   }
    3287         242 : }
    3288             : 
    3289         303 : Node* EffectControlLinearizer::IsElementsKindGreaterThan(
    3290             :     Node* kind, ElementsKind reference_kind) {
    3291         303 :   Node* ref_kind = __ Int32Constant(reference_kind);
    3292         303 :   Node* ret = __ Int32LessThan(ref_kind, kind);
    3293         303 :   return ret;
    3294             : }
    3295             : 
    3296          70 : void EffectControlLinearizer::LowerTransitionAndStoreElement(Node* node) {
    3297             :   Node* array = node->InputAt(0);
    3298             :   Node* index = node->InputAt(1);
    3299             :   Node* value = node->InputAt(2);
    3300             : 
    3301             :   // Possibly transition array based on input and store.
    3302             :   //
    3303             :   //   -- TRANSITION PHASE -----------------
    3304             :   //   kind = ElementsKind(array)
    3305             :   //   if value is not smi {
    3306             :   //     if kind == HOLEY_SMI_ELEMENTS {
    3307             :   //       if value is heap number {
    3308             :   //         Transition array to HOLEY_DOUBLE_ELEMENTS
    3309             :   //         kind = HOLEY_DOUBLE_ELEMENTS
    3310             :   //       } else {
    3311             :   //         Transition array to HOLEY_ELEMENTS
    3312             :   //         kind = HOLEY_ELEMENTS
    3313             :   //       }
    3314             :   //     } else if kind == HOLEY_DOUBLE_ELEMENTS {
    3315             :   //       if value is not heap number {
    3316             :   //         Transition array to HOLEY_ELEMENTS
    3317             :   //         kind = HOLEY_ELEMENTS
    3318             :   //       }
    3319             :   //     }
    3320             :   //   }
    3321             :   //
    3322             :   //   -- STORE PHASE ----------------------
    3323             :   //   [make sure {kind} is up-to-date]
    3324             :   //   if kind == HOLEY_DOUBLE_ELEMENTS {
    3325             :   //     if value is smi {
    3326             :   //       float_value = convert smi to float
    3327             :   //       Store array[index] = float_value
    3328             :   //     } else {
    3329             :   //       float_value = value
    3330             :   //       Store array[index] = float_value
    3331             :   //     }
    3332             :   //   } else {
    3333             :   //     // kind is HOLEY_SMI_ELEMENTS or HOLEY_ELEMENTS
    3334             :   //     Store array[index] = value
    3335             :   //   }
    3336             :   //
    3337          70 :   Node* map = __ LoadField(AccessBuilder::ForMap(), array);
    3338             :   Node* kind;
    3339             :   {
    3340          70 :     Node* bit_field2 = __ LoadField(AccessBuilder::ForMapBitField2(), map);
    3341          70 :     Node* mask = __ Int32Constant(Map::ElementsKindBits::kMask);
    3342          70 :     Node* andit = __ Word32And(bit_field2, mask);
    3343          70 :     Node* shift = __ Int32Constant(Map::ElementsKindBits::kShift);
    3344          70 :     kind = __ Word32Shr(andit, shift);
    3345             :   }
    3346             : 
    3347          70 :   auto do_store = __ MakeLabel(MachineRepresentation::kWord32);
    3348             :   // We can store a smi anywhere.
    3349          70 :   __ GotoIf(ObjectIsSmi(value), &do_store, kind);
    3350             : 
    3351             :   // {value} is a HeapObject.
    3352          70 :   auto transition_smi_array = __ MakeDeferredLabel();
    3353          70 :   auto transition_double_to_fast = __ MakeDeferredLabel();
    3354             :   {
    3355             :     __ GotoIfNot(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS),
    3356          70 :                  &transition_smi_array);
    3357             :     __ GotoIfNot(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS), &do_store,
    3358          70 :                  kind);
    3359             : 
    3360             :     // We have double elements kind. Only a HeapNumber can be stored
    3361             :     // without effecting a transition.
    3362          70 :     Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    3363          70 :     Node* heap_number_map = __ HeapNumberMapConstant();
    3364          70 :     Node* check = __ WordEqual(value_map, heap_number_map);
    3365          70 :     __ GotoIfNot(check, &transition_double_to_fast);
    3366             :     __ Goto(&do_store, kind);
    3367             :   }
    3368             : 
    3369             :   __ Bind(&transition_smi_array);  // deferred code.
    3370             :   {
    3371             :     // Transition {array} from HOLEY_SMI_ELEMENTS to HOLEY_DOUBLE_ELEMENTS or
    3372             :     // to HOLEY_ELEMENTS.
    3373          70 :     auto if_value_not_heap_number = __ MakeLabel();
    3374          70 :     Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    3375          70 :     Node* heap_number_map = __ HeapNumberMapConstant();
    3376          70 :     Node* check = __ WordEqual(value_map, heap_number_map);
    3377          70 :     __ GotoIfNot(check, &if_value_not_heap_number);
    3378             :     {
    3379             :       // {value} is a HeapNumber.
    3380             :       TransitionElementsTo(node, array, HOLEY_SMI_ELEMENTS,
    3381          70 :                            HOLEY_DOUBLE_ELEMENTS);
    3382          70 :       __ Goto(&do_store, __ Int32Constant(HOLEY_DOUBLE_ELEMENTS));
    3383             :     }
    3384             :     __ Bind(&if_value_not_heap_number);
    3385             :     {
    3386          70 :       TransitionElementsTo(node, array, HOLEY_SMI_ELEMENTS, HOLEY_ELEMENTS);
    3387          70 :       __ Goto(&do_store, __ Int32Constant(HOLEY_ELEMENTS));
    3388             :     }
    3389             :   }
    3390             : 
    3391             :   __ Bind(&transition_double_to_fast);  // deferred code.
    3392             :   {
    3393          70 :     TransitionElementsTo(node, array, HOLEY_DOUBLE_ELEMENTS, HOLEY_ELEMENTS);
    3394          70 :     __ Goto(&do_store, __ Int32Constant(HOLEY_ELEMENTS));
    3395             :   }
    3396             : 
    3397             :   // Make sure kind is up-to-date.
    3398             :   __ Bind(&do_store);
    3399             :   kind = do_store.PhiAt(0);
    3400             : 
    3401          70 :   Node* elements = __ LoadField(AccessBuilder::ForJSObjectElements(), array);
    3402          70 :   auto if_kind_is_double = __ MakeLabel();
    3403          70 :   auto done = __ MakeLabel();
    3404             :   __ GotoIf(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS),
    3405          70 :             &if_kind_is_double);
    3406             :   {
    3407             :     // Our ElementsKind is HOLEY_SMI_ELEMENTS or HOLEY_ELEMENTS.
    3408             :     __ StoreElement(AccessBuilder::ForFixedArrayElement(HOLEY_ELEMENTS),
    3409          70 :                     elements, index, value);
    3410             :     __ Goto(&done);
    3411             :   }
    3412             :   __ Bind(&if_kind_is_double);
    3413             :   {
    3414             :     // Our ElementsKind is HOLEY_DOUBLE_ELEMENTS.
    3415          70 :     auto do_double_store = __ MakeLabel();
    3416          70 :     __ GotoIfNot(ObjectIsSmi(value), &do_double_store);
    3417             :     {
    3418          70 :       Node* int_value = ChangeSmiToInt32(value);
    3419          70 :       Node* float_value = __ ChangeInt32ToFloat64(int_value);
    3420             :       __ StoreElement(AccessBuilder::ForFixedDoubleArrayElement(), elements,
    3421          70 :                       index, float_value);
    3422             :       __ Goto(&done);
    3423             :     }
    3424             :     __ Bind(&do_double_store);
    3425             :     {
    3426             :       Node* float_value =
    3427          70 :           __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    3428             :       __ StoreElement(AccessBuilder::ForFixedDoubleArrayElement(), elements,
    3429          70 :                       index, float_value);
    3430             :       __ Goto(&done);
    3431             :     }
    3432             :   }
    3433             : 
    3434             :   __ Bind(&done);
    3435          70 : }
    3436             : 
    3437          20 : void EffectControlLinearizer::LowerTransitionAndStoreNumberElement(Node* node) {
    3438             :   Node* array = node->InputAt(0);
    3439             :   Node* index = node->InputAt(1);
    3440             :   Node* value = node->InputAt(2);  // This is a Float64, not tagged.
    3441             : 
    3442             :   // Possibly transition array based on input and store.
    3443             :   //
    3444             :   //   -- TRANSITION PHASE -----------------
    3445             :   //   kind = ElementsKind(array)
    3446             :   //   if kind == HOLEY_SMI_ELEMENTS {
    3447             :   //     Transition array to HOLEY_DOUBLE_ELEMENTS
    3448             :   //   } else if kind != HOLEY_DOUBLE_ELEMENTS {
    3449             :   //     This is UNREACHABLE, execute a debug break.
    3450             :   //   }
    3451             :   //
    3452             :   //   -- STORE PHASE ----------------------
    3453             :   //   Store array[index] = value (it's a float)
    3454             :   //
    3455          20 :   Node* map = __ LoadField(AccessBuilder::ForMap(), array);
    3456             :   Node* kind;
    3457             :   {
    3458          20 :     Node* bit_field2 = __ LoadField(AccessBuilder::ForMapBitField2(), map);
    3459          20 :     Node* mask = __ Int32Constant(Map::ElementsKindBits::kMask);
    3460          20 :     Node* andit = __ Word32And(bit_field2, mask);
    3461          20 :     Node* shift = __ Int32Constant(Map::ElementsKindBits::kShift);
    3462          20 :     kind = __ Word32Shr(andit, shift);
    3463             :   }
    3464             : 
    3465          20 :   auto do_store = __ MakeLabel();
    3466             : 
    3467             :   // {value} is a float64.
    3468          20 :   auto transition_smi_array = __ MakeDeferredLabel();
    3469             :   {
    3470             :     __ GotoIfNot(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS),
    3471          20 :                  &transition_smi_array);
    3472             :     // We expect that our input array started at HOLEY_SMI_ELEMENTS, and
    3473             :     // climbs the lattice up to HOLEY_DOUBLE_ELEMENTS. Force a debug break
    3474             :     // if this assumption is broken. It also would be the case that
    3475             :     // loop peeling can break this assumption.
    3476             :     __ GotoIf(__ Word32Equal(kind, __ Int32Constant(HOLEY_DOUBLE_ELEMENTS)),
    3477          20 :               &do_store);
    3478             :     // TODO(turbofan): It would be good to have an "Unreachable()" node type.
    3479          20 :     __ DebugBreak();
    3480             :     __ Goto(&do_store);
    3481             :   }
    3482             : 
    3483             :   __ Bind(&transition_smi_array);  // deferred code.
    3484             :   {
    3485             :     // Transition {array} from HOLEY_SMI_ELEMENTS to HOLEY_DOUBLE_ELEMENTS.
    3486             :     TransitionElementsTo(node, array, HOLEY_SMI_ELEMENTS,
    3487          20 :                          HOLEY_DOUBLE_ELEMENTS);
    3488             :     __ Goto(&do_store);
    3489             :   }
    3490             : 
    3491             :   __ Bind(&do_store);
    3492             : 
    3493          20 :   Node* elements = __ LoadField(AccessBuilder::ForJSObjectElements(), array);
    3494             :   __ StoreElement(AccessBuilder::ForFixedDoubleArrayElement(), elements, index,
    3495          20 :                   value);
    3496          20 : }
    3497             : 
    3498           6 : void EffectControlLinearizer::LowerTransitionAndStoreNonNumberElement(
    3499           6 :     Node* node) {
    3500             :   Node* array = node->InputAt(0);
    3501             :   Node* index = node->InputAt(1);
    3502             :   Node* value = node->InputAt(2);
    3503             : 
    3504             :   // Possibly transition array based on input and store.
    3505             :   //
    3506             :   //   -- TRANSITION PHASE -----------------
    3507             :   //   kind = ElementsKind(array)
    3508             :   //   if kind == HOLEY_SMI_ELEMENTS {
    3509             :   //     Transition array to HOLEY_ELEMENTS
    3510             :   //   } else if kind == HOLEY_DOUBLE_ELEMENTS {
    3511             :   //     Transition array to HOLEY_ELEMENTS
    3512             :   //   }
    3513             :   //
    3514             :   //   -- STORE PHASE ----------------------
    3515             :   //   // kind is HOLEY_ELEMENTS
    3516             :   //   Store array[index] = value
    3517             :   //
    3518           6 :   Node* map = __ LoadField(AccessBuilder::ForMap(), array);
    3519             :   Node* kind;
    3520             :   {
    3521           6 :     Node* bit_field2 = __ LoadField(AccessBuilder::ForMapBitField2(), map);
    3522           6 :     Node* mask = __ Int32Constant(Map::ElementsKindBits::kMask);
    3523           6 :     Node* andit = __ Word32And(bit_field2, mask);
    3524           6 :     Node* shift = __ Int32Constant(Map::ElementsKindBits::kShift);
    3525           6 :     kind = __ Word32Shr(andit, shift);
    3526             :   }
    3527             : 
    3528           6 :   auto do_store = __ MakeLabel();
    3529             : 
    3530           6 :   auto transition_smi_array = __ MakeDeferredLabel();
    3531           6 :   auto transition_double_to_fast = __ MakeDeferredLabel();
    3532             :   {
    3533             :     __ GotoIfNot(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS),
    3534           6 :                  &transition_smi_array);
    3535             :     __ GotoIf(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS),
    3536           6 :               &transition_double_to_fast);
    3537             :     __ Goto(&do_store);
    3538             :   }
    3539             : 
    3540             :   __ Bind(&transition_smi_array);  // deferred code.
    3541             :   {
    3542             :     // Transition {array} from HOLEY_SMI_ELEMENTS to HOLEY_ELEMENTS.
    3543           6 :     TransitionElementsTo(node, array, HOLEY_SMI_ELEMENTS, HOLEY_ELEMENTS);
    3544             :     __ Goto(&do_store);
    3545             :   }
    3546             : 
    3547             :   __ Bind(&transition_double_to_fast);  // deferred code.
    3548             :   {
    3549           6 :     TransitionElementsTo(node, array, HOLEY_DOUBLE_ELEMENTS, HOLEY_ELEMENTS);
    3550             :     __ Goto(&do_store);
    3551             :   }
    3552             : 
    3553             :   __ Bind(&do_store);
    3554             : 
    3555           6 :   Node* elements = __ LoadField(AccessBuilder::ForJSObjectElements(), array);
    3556             :   // Our ElementsKind is HOLEY_ELEMENTS.
    3557           6 :   ElementAccess access = AccessBuilder::ForFixedArrayElement(HOLEY_ELEMENTS);
    3558           6 :   Type* value_type = ValueTypeParameterOf(node->op());
    3559           6 :   if (value_type->Is(Type::BooleanOrNullOrUndefined())) {
    3560           0 :     access.type = value_type;
    3561           0 :     access.write_barrier_kind = kNoWriteBarrier;
    3562             :   }
    3563           6 :   __ StoreElement(access, elements, index, value);
    3564           6 : }
    3565             : 
    3566          61 : void EffectControlLinearizer::LowerStoreSignedSmallElement(Node* node) {
    3567             :   Node* array = node->InputAt(0);
    3568             :   Node* index = node->InputAt(1);
    3569             :   Node* value = node->InputAt(2);  // int32
    3570             : 
    3571             :   // Store a signed small in an output array.
    3572             :   //
    3573             :   //   kind = ElementsKind(array)
    3574             :   //
    3575             :   //   -- STORE PHASE ----------------------
    3576             :   //   if kind == HOLEY_DOUBLE_ELEMENTS {
    3577             :   //     float_value = convert int32 to float
    3578             :   //     Store array[index] = float_value
    3579             :   //   } else {
    3580             :   //     // kind is HOLEY_SMI_ELEMENTS or HOLEY_ELEMENTS
    3581             :   //     smi_value = convert int32 to smi
    3582             :   //     Store array[index] = smi_value
    3583             :   //   }
    3584             :   //
    3585          61 :   Node* map = __ LoadField(AccessBuilder::ForMap(), array);
    3586             :   Node* kind;
    3587             :   {
    3588          61 :     Node* bit_field2 = __ LoadField(AccessBuilder::ForMapBitField2(), map);
    3589          61 :     Node* mask = __ Int32Constant(Map::ElementsKindBits::kMask);
    3590          61 :     Node* andit = __ Word32And(bit_field2, mask);
    3591          61 :     Node* shift = __ Int32Constant(Map::ElementsKindBits::kShift);
    3592          61 :     kind = __ Word32Shr(andit, shift);
    3593             :   }
    3594             : 
    3595          61 :   Node* elements = __ LoadField(AccessBuilder::ForJSObjectElements(), array);
    3596          61 :   auto if_kind_is_double = __ MakeLabel();
    3597          61 :   auto done = __ MakeLabel();
    3598             :   __ GotoIf(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS),
    3599          61 :             &if_kind_is_double);
    3600             :   {
    3601             :     // Our ElementsKind is HOLEY_SMI_ELEMENTS or HOLEY_ELEMENTS.
    3602             :     // In this case, we know our value is a signed small, and we can optimize
    3603             :     // the ElementAccess information.
    3604          61 :     ElementAccess access = AccessBuilder::ForFixedArrayElement();
    3605          61 :     access.type = Type::SignedSmall();
    3606          61 :     access.machine_type = MachineType::TaggedSigned();
    3607          61 :     access.write_barrier_kind = kNoWriteBarrier;
    3608          61 :     Node* smi_value = ChangeInt32ToSmi(value);
    3609          61 :     __ StoreElement(access, elements, index, smi_value);
    3610             :     __ Goto(&done);
    3611             :   }
    3612             :   __ Bind(&if_kind_is_double);
    3613             :   {
    3614             :     // Our ElementsKind is HOLEY_DOUBLE_ELEMENTS.
    3615          61 :     Node* float_value = __ ChangeInt32ToFloat64(value);
    3616             :     __ StoreElement(AccessBuilder::ForFixedDoubleArrayElement(), elements,
    3617          61 :                     index, float_value);
    3618             :     __ Goto(&done);
    3619             :   }
    3620             : 
    3621             :   __ Bind(&done);
    3622          61 : }
    3623             : 
    3624        3840 : void EffectControlLinearizer::LowerRuntimeAbort(Node* node) {
    3625        1920 :   BailoutReason reason = BailoutReasonOf(node->op());
    3626        1920 :   Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
    3627             :   Runtime::FunctionId id = Runtime::kAbort;
    3628             :   CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
    3629        1920 :       graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags);
    3630             :   __ Call(desc, __ CEntryStubConstant(1), jsgraph()->SmiConstant(reason),
    3631             :           __ ExternalConstant(ExternalReference(id, isolate())),
    3632        5760 :           __ Int32Constant(1), __ NoContextConstant());
    3633        1920 : }
    3634             : 
    3635        5468 : Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundUp(Node* node) {
    3636             :   // Nothing to be done if a fast hardware instruction is available.
    3637        5468 :   if (machine()->Float64RoundUp().IsSupported()) {
    3638             :     return Nothing<Node*>();
    3639             :   }
    3640             : 
    3641             :   Node* const input = node->InputAt(0);
    3642             : 
    3643             :   // General case for ceil.
    3644             :   //
    3645             :   //   if 0.0 < input then
    3646             :   //     if 2^52 <= input then
    3647             :   //       input
    3648             :   //     else
    3649             :   //       let temp1 = (2^52 + input) - 2^52 in
    3650             :   //       if temp1 < input then
    3651             :   //         temp1 + 1
    3652             :   //       else
    3653             :   //         temp1
    3654             :   //   else
    3655             :   //     if input == 0 then
    3656             :   //       input
    3657             :   //     else
    3658             :   //       if input <= -2^52 then
    3659             :   //         input
    3660             :   //       else
    3661             :   //         let temp1 = -0 - input in
    3662             :   //         let temp2 = (2^52 + temp1) - 2^52 in
    3663             :   //         let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
    3664             :   //         -0 - temp3
    3665             : 
    3666           0 :   auto if_not_positive = __ MakeDeferredLabel();
    3667           0 :   auto if_greater_than_two_52 = __ MakeDeferredLabel();
    3668           0 :   auto if_less_than_minus_two_52 = __ MakeDeferredLabel();
    3669           0 :   auto if_zero = __ MakeDeferredLabel();
    3670           0 :   auto done_temp3 = __ MakeLabel(MachineRepresentation::kFloat64);
    3671           0 :   auto done = __ MakeLabel(MachineRepresentation::kFloat64);
    3672             : 
    3673           0 :   Node* const zero = __ Float64Constant(0.0);
    3674           0 :   Node* const two_52 = __ Float64Constant(4503599627370496.0E0);
    3675           0 :   Node* const one = __ Float64Constant(1.0);
    3676             : 
    3677           0 :   Node* check0 = __ Float64LessThan(zero, input);
    3678           0 :   __ GotoIfNot(check0, &if_not_positive);
    3679             :   {
    3680           0 :     Node* check1 = __ Float64LessThanOrEqual(two_52, input);
    3681           0 :     __ GotoIf(check1, &if_greater_than_two_52);
    3682             :     {
    3683           0 :       Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52);
    3684           0 :       __ GotoIfNot(__ Float64LessThan(temp1, input), &done, temp1);
    3685           0 :       __ Goto(&done, __ Float64Add(temp1, one));
    3686             :     }
    3687             : 
    3688             :     __ Bind(&if_greater_than_two_52);
    3689             :     __ Goto(&done, input);
    3690             :   }
    3691             : 
    3692             :   __ Bind(&if_not_positive);
    3693             :   {
    3694           0 :     Node* check1 = __ Float64Equal(input, zero);
    3695           0 :     __ GotoIf(check1, &if_zero);
    3696             : 
    3697           0 :     Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0);
    3698           0 :     Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52);
    3699           0 :     __ GotoIf(check2, &if_less_than_minus_two_52);
    3700             : 
    3701             :     {
    3702           0 :       Node* const minus_zero = __ Float64Constant(-0.0);
    3703           0 :       Node* temp1 = __ Float64Sub(minus_zero, input);
    3704           0 :       Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52);
    3705           0 :       Node* check3 = __ Float64LessThan(temp1, temp2);
    3706           0 :       __ GotoIfNot(check3, &done_temp3, temp2);
    3707           0 :       __ Goto(&done_temp3, __ Float64Sub(temp2, one));
    3708             : 
    3709             :       __ Bind(&done_temp3);
    3710             :       Node* temp3 = done_temp3.PhiAt(0);
    3711           0 :       __ Goto(&done, __ Float64Sub(minus_zero, temp3));
    3712             :     }
    3713             :     __ Bind(&if_less_than_minus_two_52);
    3714             :     __ Goto(&done, input);
    3715             : 
    3716             :     __ Bind(&if_zero);
    3717             :     __ Goto(&done, input);
    3718             :   }
    3719             :   __ Bind(&done);
    3720             :   return Just(done.PhiAt(0));
    3721             : }
    3722             : 
    3723           0 : Node* EffectControlLinearizer::BuildFloat64RoundDown(Node* value) {
    3724           0 :   Node* round_down = __ Float64RoundDown(value);
    3725           0 :   if (round_down != nullptr) {
    3726             :     return round_down;
    3727             :   }
    3728             : 
    3729             :   Node* const input = value;
    3730             : 
    3731             :   // General case for floor.
    3732             :   //
    3733             :   //   if 0.0 < input then
    3734             :   //     if 2^52 <= input then
    3735             :   //       input
    3736             :   //     else
    3737             :   //       let temp1 = (2^52 + input) - 2^52 in
    3738             :   //       if input < temp1 then
    3739             :   //         temp1 - 1
    3740             :   //       else
    3741             :   //         temp1
    3742             :   //   else
    3743             :   //     if input == 0 then
    3744             :   //       input
    3745             :   //     else
    3746             :   //       if input <= -2^52 then
    3747             :   //         input
    3748             :   //       else
    3749             :   //         let temp1 = -0 - input in
    3750             :   //         let temp2 = (2^52 + temp1) - 2^52 in
    3751             :   //         if temp2 < temp1 then
    3752             :   //           -1 - temp2
    3753             :   //         else
    3754             :   //           -0 - temp2
    3755             : 
    3756           0 :   auto if_not_positive = __ MakeDeferredLabel();
    3757           0 :   auto if_greater_than_two_52 = __ MakeDeferredLabel();
    3758           0 :   auto if_less_than_minus_two_52 = __ MakeDeferredLabel();
    3759           0 :   auto if_temp2_lt_temp1 = __ MakeLabel();
    3760           0 :   auto if_zero = __ MakeDeferredLabel();
    3761           0 :   auto done = __ MakeLabel(MachineRepresentation::kFloat64);
    3762             : 
    3763           0 :   Node* const zero = __ Float64Constant(0.0);
    3764           0 :   Node* const two_52 = __ Float64Constant(4503599627370496.0E0);
    3765             : 
    3766           0 :   Node* check0 = __ Float64LessThan(zero, input);
    3767           0 :   __ GotoIfNot(check0, &if_not_positive);
    3768             :   {
    3769           0 :     Node* check1 = __ Float64LessThanOrEqual(two_52, input);
    3770           0 :     __ GotoIf(check1, &if_greater_than_two_52);
    3771             :     {
    3772           0 :       Node* const one = __ Float64Constant(1.0);
    3773           0 :       Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52);
    3774           0 :       __ GotoIfNot(__ Float64LessThan(input, temp1), &done, temp1);
    3775           0 :       __ Goto(&done, __ Float64Sub(temp1, one));
    3776             :     }
    3777             : 
    3778             :     __ Bind(&if_greater_than_two_52);
    3779             :     __ Goto(&done, input);
    3780             :   }
    3781             : 
    3782             :   __ Bind(&if_not_positive);
    3783             :   {
    3784           0 :     Node* check1 = __ Float64Equal(input, zero);
    3785           0 :     __ GotoIf(check1, &if_zero);
    3786             : 
    3787           0 :     Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0);
    3788           0 :     Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52);
    3789           0 :     __ GotoIf(check2, &if_less_than_minus_two_52);
    3790             : 
    3791             :     {
    3792           0 :       Node* const minus_zero = __ Float64Constant(-0.0);
    3793           0 :       Node* temp1 = __ Float64Sub(minus_zero, input);
    3794           0 :       Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52);
    3795           0 :       Node* check3 = __ Float64LessThan(temp2, temp1);
    3796           0 :       __ GotoIf(check3, &if_temp2_lt_temp1);
    3797           0 :       __ Goto(&done, __ Float64Sub(minus_zero, temp2));
    3798             : 
    3799             :       __ Bind(&if_temp2_lt_temp1);
    3800           0 :       __ Goto(&done, __ Float64Sub(__ Float64Constant(-1.0), temp2));
    3801             :     }
    3802             :     __ Bind(&if_less_than_minus_two_52);
    3803             :     __ Goto(&done, input);
    3804             : 
    3805             :     __ Bind(&if_zero);
    3806             :     __ Goto(&done, input);
    3807             :   }
    3808             :   __ Bind(&done);
    3809             :   return done.PhiAt(0);
    3810             : }
    3811             : 
    3812        8374 : Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundDown(Node* node) {
    3813             :   // Nothing to be done if a fast hardware instruction is available.
    3814        8374 :   if (machine()->Float64RoundDown().IsSupported()) {
    3815             :     return Nothing<Node*>();
    3816             :   }
    3817             : 
    3818             :   Node* const input = node->InputAt(0);
    3819           0 :   return Just(BuildFloat64RoundDown(input));
    3820             : }
    3821             : 
    3822         325 : Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundTiesEven(Node* node) {
    3823             :   // Nothing to be done if a fast hardware instruction is available.
    3824         325 :   if (machine()->Float64RoundTiesEven().IsSupported()) {
    3825             :     return Nothing<Node*>();
    3826             :   }
    3827             : 
    3828             :   Node* const input = node->InputAt(0);
    3829             : 
    3830             :   // Generate case for round ties to even:
    3831             :   //
    3832             :   //   let value = floor(input) in
    3833             :   //   let temp1 = input - value in
    3834             :   //   if temp1 < 0.5 then
    3835             :   //     value
    3836             :   //   else if 0.5 < temp1 then
    3837             :   //     value + 1.0
    3838             :   //   else
    3839             :   //     let temp2 = value % 2.0 in
    3840             :   //     if temp2 == 0.0 then
    3841             :   //       value
    3842             :   //     else
    3843             :   //       value + 1.0
    3844             : 
    3845           0 :   auto if_is_half = __ MakeLabel();
    3846           0 :   auto done = __ MakeLabel(MachineRepresentation::kFloat64);
    3847             : 
    3848           0 :   Node* value = BuildFloat64RoundDown(input);
    3849           0 :   Node* temp1 = __ Float64Sub(input, value);
    3850             : 
    3851           0 :   Node* const half = __ Float64Constant(0.5);
    3852           0 :   Node* check0 = __ Float64LessThan(temp1, half);
    3853           0 :   __ GotoIf(check0, &done, value);
    3854             : 
    3855           0 :   Node* const one = __ Float64Constant(1.0);
    3856           0 :   Node* check1 = __ Float64LessThan(half, temp1);
    3857           0 :   __ GotoIfNot(check1, &if_is_half);
    3858           0 :   __ Goto(&done, __ Float64Add(value, one));
    3859             : 
    3860             :   __ Bind(&if_is_half);
    3861           0 :   Node* temp2 = __ Float64Mod(value, __ Float64Constant(2.0));
    3862           0 :   Node* check2 = __ Float64Equal(temp2, __ Float64Constant(0.0));
    3863           0 :   __ GotoIf(check2, &done, value);
    3864           0 :   __ Goto(&done, __ Float64Add(value, one));
    3865             : 
    3866             :   __ Bind(&done);
    3867             :   return Just(done.PhiAt(0));
    3868             : }
    3869             : 
    3870        1337 : Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundTruncate(Node* node) {
    3871             :   // Nothing to be done if a fast hardware instruction is available.
    3872        1337 :   if (machine()->Float64RoundTruncate().IsSupported()) {
    3873             :     return Nothing<Node*>();
    3874             :   }
    3875             : 
    3876             :   Node* const input = node->InputAt(0);
    3877             : 
    3878             :   // General case for trunc.
    3879             :   //
    3880             :   //   if 0.0 < input then
    3881             :   //     if 2^52 <= input then
    3882             :   //       input
    3883             :   //     else
    3884             :   //       let temp1 = (2^52 + input) - 2^52 in
    3885             :   //       if input < temp1 then
    3886             :   //         temp1 - 1
    3887             :   //       else
    3888             :   //         temp1
    3889             :   //   else
    3890             :   //     if input == 0 then
    3891             :   //       input
    3892             :   //     else
    3893             :   //       if input <= -2^52 then
    3894             :   //         input
    3895             :   //       else
    3896             :   //         let temp1 = -0 - input in
    3897             :   //         let temp2 = (2^52 + temp1) - 2^52 in
    3898             :   //         let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
    3899             :   //         -0 - temp3
    3900             :   //
    3901             :   // Note: We do not use the Diamond helper class here, because it really hurts
    3902             :   // readability with nested diamonds.
    3903             : 
    3904           0 :   auto if_not_positive = __ MakeDeferredLabel();
    3905           0 :   auto if_greater_than_two_52 = __ MakeDeferredLabel();
    3906           0 :   auto if_less_than_minus_two_52 = __ MakeDeferredLabel();
    3907           0 :   auto if_zero = __ MakeDeferredLabel();
    3908           0 :   auto done_temp3 = __ MakeLabel(MachineRepresentation::kFloat64);
    3909           0 :   auto done = __ MakeLabel(MachineRepresentation::kFloat64);
    3910             : 
    3911           0 :   Node* const zero = __ Float64Constant(0.0);
    3912           0 :   Node* const two_52 = __ Float64Constant(4503599627370496.0E0);
    3913           0 :   Node* const one = __ Float64Constant(1.0);
    3914             : 
    3915           0 :   Node* check0 = __ Float64LessThan(zero, input);
    3916           0 :   __ GotoIfNot(check0, &if_not_positive);
    3917             :   {
    3918           0 :     Node* check1 = __ Float64LessThanOrEqual(two_52, input);
    3919           0 :     __ GotoIf(check1, &if_greater_than_two_52);
    3920             :     {
    3921           0 :       Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52);
    3922           0 :       __ GotoIfNot(__ Float64LessThan(input, temp1), &done, temp1);
    3923           0 :       __ Goto(&done, __ Float64Sub(temp1, one));
    3924             :     }
    3925             : 
    3926             :     __ Bind(&if_greater_than_two_52);
    3927             :     __ Goto(&done, input);
    3928             :   }
    3929             : 
    3930             :   __ Bind(&if_not_positive);
    3931             :   {
    3932           0 :     Node* check1 = __ Float64Equal(input, zero);
    3933           0 :     __ GotoIf(check1, &if_zero);
    3934             : 
    3935           0 :     Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0);
    3936           0 :     Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52);
    3937           0 :     __ GotoIf(check2, &if_less_than_minus_two_52);
    3938             : 
    3939             :     {
    3940           0 :       Node* const minus_zero = __ Float64Constant(-0.0);
    3941           0 :       Node* temp1 = __ Float64Sub(minus_zero, input);
    3942           0 :       Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52);
    3943           0 :       Node* check3 = __ Float64LessThan(temp1, temp2);
    3944           0 :       __ GotoIfNot(check3, &done_temp3, temp2);
    3945           0 :       __ Goto(&done_temp3, __ Float64Sub(temp2, one));
    3946             : 
    3947             :       __ Bind(&done_temp3);
    3948             :       Node* temp3 = done_temp3.PhiAt(0);
    3949           0 :       __ Goto(&done, __ Float64Sub(minus_zero, temp3));
    3950             :     }
    3951             :     __ Bind(&if_less_than_minus_two_52);
    3952             :     __ Goto(&done, input);
    3953             : 
    3954             :     __ Bind(&if_zero);
    3955             :     __ Goto(&done, input);
    3956             :   }
    3957             :   __ Bind(&done);
    3958             :   return Just(done.PhiAt(0));
    3959             : }
    3960             : 
    3961          16 : Node* EffectControlLinearizer::LowerFindOrderedHashMapEntry(Node* node) {
    3962           8 :   Node* table = NodeProperties::GetValueInput(node, 0);
    3963           8 :   Node* key = NodeProperties::GetValueInput(node, 1);
    3964             : 
    3965             :   {
    3966             :     Callable const callable =
    3967           8 :         Builtins::CallableFor(isolate(), Builtins::kFindOrderedHashMapEntry);
    3968           8 :     Operator::Properties const properties = node->op()->properties();
    3969             :     CallDescriptor::Flags const flags = CallDescriptor::kNoFlags;
    3970             :     CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    3971             :         isolate(), graph()->zone(), callable.descriptor(), 0, flags,
    3972          24 :         properties);
    3973             :     return __ Call(desc, __ HeapConstant(callable.code()), table, key,
    3974          16 :                    __ NoContextConstant());
    3975             :   }
    3976             : }
    3977             : 
    3978           0 : Node* EffectControlLinearizer::ComputeIntegerHash(Node* value) {
    3979             :   // See v8::internal::ComputeIntegerHash()
    3980             :   value = __ Int32Add(__ Word32Xor(value, __ Int32Constant(0xffffffff)),
    3981           0 :                       __ Word32Shl(value, __ Int32Constant(15)));
    3982           0 :   value = __ Word32Xor(value, __ Word32Shr(value, __ Int32Constant(12)));
    3983           0 :   value = __ Int32Add(value, __ Word32Shl(value, __ Int32Constant(2)));
    3984           0 :   value = __ Word32Xor(value, __ Word32Shr(value, __ Int32Constant(4)));
    3985           0 :   value = __ Int32Mul(value, __ Int32Constant(2057));
    3986           0 :   value = __ Word32Xor(value, __ Word32Shr(value, __ Int32Constant(16)));
    3987           0 :   value = __ Word32And(value, __ Int32Constant(0x3fffffff));
    3988           0 :   return value;
    3989             : }
    3990             : 
    3991           0 : Node* EffectControlLinearizer::LowerFindOrderedHashMapEntryForInt32Key(
    3992             :     Node* node) {
    3993           0 :   Node* table = NodeProperties::GetValueInput(node, 0);
    3994           0 :   Node* key = NodeProperties::GetValueInput(node, 1);
    3995             : 
    3996             :   // Compute the integer hash code.
    3997           0 :   Node* hash = ChangeUint32ToUintPtr(ComputeIntegerHash(key));
    3998             : 
    3999             :   Node* number_of_buckets = ChangeSmiToIntPtr(__ LoadField(
    4000           0 :       AccessBuilder::ForOrderedHashTableBaseNumberOfBuckets(), table));
    4001           0 :   hash = __ WordAnd(hash, __ IntSub(number_of_buckets, __ IntPtrConstant(1)));
    4002             :   Node* first_entry = ChangeSmiToIntPtr(__ Load(
    4003             :       MachineType::TaggedSigned(), table,
    4004             :       __ IntAdd(__ WordShl(hash, __ IntPtrConstant(kPointerSizeLog2)),
    4005             :                 __ IntPtrConstant(OrderedHashMap::kHashTableStartOffset -
    4006           0 :                                   kHeapObjectTag))));
    4007             : 
    4008           0 :   auto loop = __ MakeLoopLabel(MachineType::PointerRepresentation());
    4009           0 :   auto done = __ MakeLabel(MachineRepresentation::kWord32);
    4010             :   __ Goto(&loop, first_entry);
    4011             :   __ Bind(&loop);
    4012             :   {
    4013             :     Node* entry = loop.PhiAt(0);
    4014             :     Node* check =
    4015           0 :         __ WordEqual(entry, __ IntPtrConstant(OrderedHashMap::kNotFound));
    4016           0 :     __ GotoIf(check, &done, __ Int32Constant(-1));
    4017             :     entry = __ IntAdd(
    4018             :         __ IntMul(entry, __ IntPtrConstant(OrderedHashMap::kEntrySize)),
    4019           0 :         number_of_buckets);
    4020             : 
    4021             :     Node* candidate_key = __ Load(
    4022             :         MachineType::AnyTagged(), table,
    4023             :         __ IntAdd(__ WordShl(entry, __ IntPtrConstant(kPointerSizeLog2)),
    4024             :                   __ IntPtrConstant(OrderedHashMap::kHashTableStartOffset -
    4025           0 :                                     kHeapObjectTag)));
    4026             : 
    4027           0 :     auto if_match = __ MakeLabel();
    4028           0 :     auto if_notmatch = __ MakeLabel();
    4029           0 :     auto if_notsmi = __ MakeDeferredLabel();
    4030           0 :     __ GotoIfNot(ObjectIsSmi(candidate_key), &if_notsmi);
    4031             :     __ Branch(__ Word32Equal(ChangeSmiToInt32(candidate_key), key), &if_match,
    4032           0 :               &if_notmatch);
    4033             : 
    4034             :     __ Bind(&if_notsmi);
    4035             :     __ GotoIfNot(
    4036             :         __ WordEqual(__ LoadField(AccessBuilder::ForMap(), candidate_key),
    4037             :                      __ HeapNumberMapConstant()),
    4038           0 :         &if_notmatch);
    4039             :     __ Branch(__ Float64Equal(__ LoadField(AccessBuilder::ForHeapNumberValue(),
    4040             :                                            candidate_key),
    4041             :                               __ ChangeInt32ToFloat64(key)),
    4042           0 :               &if_match, &if_notmatch);
    4043             : 
    4044             :     __ Bind(&if_match);
    4045             :     {
    4046             :       Node* index = ChangeIntPtrToInt32(entry);
    4047             :       __ Goto(&done, index);
    4048             :     }
    4049             : 
    4050             :     __ Bind(&if_notmatch);
    4051             :     {
    4052             :       Node* next_entry = ChangeSmiToIntPtr(__ Load(
    4053             :           MachineType::TaggedSigned(), table,
    4054             :           __ IntAdd(
    4055             :               __ WordShl(entry, __ IntPtrConstant(kPointerSizeLog2)),
    4056             :               __ IntPtrConstant(OrderedHashMap::kHashTableStartOffset +
    4057             :                                 OrderedHashMap::kChainOffset * kPointerSize -
    4058           0 :                                 kHeapObjectTag))));
    4059             :       __ Goto(&loop, next_entry);
    4060             :     }
    4061             :   }
    4062             : 
    4063             :   __ Bind(&done);
    4064           0 :   return done.PhiAt(0);
    4065             : }
    4066             : 
    4067             : #undef __
    4068             : 
    4069           0 : Factory* EffectControlLinearizer::factory() const {
    4070           0 :   return isolate()->factory();
    4071             : }
    4072             : 
    4073       51204 : Isolate* EffectControlLinearizer::isolate() const {
    4074       98789 :   return jsgraph()->isolate();
    4075             : }
    4076             : 
    4077             : }  // namespace compiler
    4078             : }  // namespace internal
    4079             : }  // namespace v8

Generated by: LCOV version 1.10