LCOV - code coverage report
Current view: top level - src/compiler - effect-control-linearizer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1073 1217 88.2 %
Date: 2017-04-26 Functions: 90 101 89.1 %

          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/objects-inl.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : namespace compiler {
      21             : 
      22      395305 : 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      395305 :       frame_state_zapper_(nullptr) {}
      31             : 
      32     1845045 : Graph* EffectControlLinearizer::graph() const { return js_graph_->graph(); }
      33           0 : CommonOperatorBuilder* EffectControlLinearizer::common() const {
      34     1202978 :   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      419386 :   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    21393961 :   BlockEffectControlData& For(BasicBlock* from, BasicBlock* to) {
      56    21393961 :     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       43663 :       : effect_phi(effect_phi), block(block) {}
      77             : };
      78             : 
      79     3928363 : 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     9022656 :   for (int i = 0; i < node->op()->EffectInputCount(); i++) {
      87             :     Node* input = node->InputAt(i);
      88     2086733 :     BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i));
      89             :     const BlockEffectControlData& block_effect =
      90             :         block_effects->For(predecessor, block);
      91     2086739 :     if (input != block_effect.current_effect) {
      92      717024 :       node->ReplaceInput(i, block_effect.current_effect);
      93             :     }
      94             :   }
      95      920819 : }
      96             : 
      97     4627309 : void UpdateBlockControl(BasicBlock* block,
      98             :                         BlockEffectControlMap* block_effects) {
      99    13399526 :   Node* control = block->NodeAt(0);
     100             :   DCHECK(NodeProperties::IsControl(control));
     101             : 
     102             :   // Do not rewire the end node.
     103     4627309 :   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    12701541 :   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    22355562 :   for (int i = 0; i < control->op()->ControlInputCount(); i++) {
     114     4811137 :     Node* input = NodeProperties::GetControlInput(control, i);
     115     4811131 :     BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i));
     116             :     const BlockEffectControlData& block_effect =
     117             :         block_effects->For(predecessor, block);
     118     4811126 :     if (input != block_effect.current_control) {
     119             :       NodeProperties::ReplaceControlInput(control, block_effect.current_control,
     120       39683 :                                           i);
     121             :     }
     122             :   }
     123             : }
     124             : 
     125     7711601 : bool HasIncomingBackEdges(BasicBlock* block) {
     126    20869481 :   for (BasicBlock* pred : block->predecessors()) {
     127     7711601 :     if (pred->rpo_number() >= block->rpo_number()) {
     128             :       return true;
     129             :     }
     130             :   }
     131             :   return false;
     132             : }
     133             : 
     134      188896 : 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     2939894 :   for (Edge edge : node->use_edges()) {
     140             :     DCHECK(!edge.from()->IsDead());
     141     1375499 :     if (NodeProperties::IsEffectEdge(edge)) {
     142      189716 :       edge.UpdateTo(NodeProperties::GetEffectInput(node));
     143             :     } else {
     144             :       DCHECK(!NodeProperties::IsControlEdge(edge));
     145             :       DCHECK(!NodeProperties::IsFrameStateEdge(edge));
     146     1185783 :       edge.UpdateTo(node->InputAt(0));
     147             :     }
     148             :   }
     149      188896 :   node->Kill();
     150      188896 : }
     151             : 
     152     1324829 : void TryCloneBranch(Node* node, BasicBlock* block, Zone* temp_zone,
     153     1277291 :                     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     1188449 :                                    source_positions->GetSourcePosition(node));
     209      136381 :   Node* branch = node;
     210     2348941 :   Node* cond = NodeProperties::GetValueInput(branch, 0);
     211     2348940 :   if (!cond->OwnedBy(branch) || cond->opcode() != IrOpcode::kPhi) return;
     212      280776 :   Node* merge = NodeProperties::GetControlInput(branch);
     213      282450 :   if (merge->opcode() != IrOpcode::kMerge ||
     214      138055 :       NodeProperties::GetControlInput(cond) != merge) {
     215             :     return;
     216             :   }
     217             :   // Grab the IfTrue/IfFalse projections of the Branch.
     218      137985 :   BranchMatcher matcher(branch);
     219             :   // Check/collect other Phi/EffectPhi nodes hanging off the Merge.
     220             :   NodeVector phis(temp_zone);
     221      960805 :   for (Node* const use : merge->uses()) {
     222      412212 :     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      139511 :     if (!NodeProperties::IsPhi(use)) return;
     228      138259 :     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        1956 :       if (edge.from()->op()->ControlInputCount() != 1) return;
     233        1923 :       Node* control = NodeProperties::GetControlInput(edge.from());
     234        1923 :       if (NodeProperties::IsPhi(edge.from())) {
     235         287 :         control = NodeProperties::GetControlInput(control, edge.index());
     236             :       }
     237        1923 :       if (control != matcher.IfTrue() && control != matcher.IfFalse()) return;
     238             :     }
     239      136303 :     phis.push_back(use);
     240             :   }
     241      136381 :   BranchHint const hint = BranchHintOf(branch->op());
     242      136381 :   int const input_count = merge->op()->ControlInputCount();
     243             :   DCHECK_LE(1, input_count);
     244      136381 :   Node** const inputs = graph->zone()->NewArray<Node*>(2 * input_count);
     245             :   Node** const merge_true_inputs = &inputs[0];
     246      136381 :   Node** const merge_false_inputs = &inputs[input_count];
     247      706836 :   for (int index = 0; index < input_count; ++index) {
     248      570455 :     Node* cond1 = NodeProperties::GetValueInput(cond, index);
     249      570455 :     Node* control1 = NodeProperties::GetControlInput(merge, index);
     250      570455 :     Node* branch1 = graph->NewNode(common->Branch(hint), cond1, control1);
     251     1140910 :     merge_true_inputs[index] = graph->NewNode(common->IfTrue(), branch1);
     252     1140910 :     merge_false_inputs[index] = graph->NewNode(common->IfFalse(), branch1);
     253             :   }
     254      136381 :   Node* const merge_true = matcher.IfTrue();
     255      136381 :   Node* const merge_false = matcher.IfFalse();
     256      136381 :   merge_true->TrimInputCount(0);
     257      136381 :   merge_false->TrimInputCount(0);
     258      706836 :   for (int i = 0; i < input_count; ++i) {
     259     1140910 :     merge_true->AppendInput(graph->zone(), merge_true_inputs[i]);
     260     1140910 :     merge_false->AppendInput(graph->zone(), merge_false_inputs[i]);
     261             :   }
     262             :   DCHECK_EQ(2u, block->SuccessorCount());
     263      136381 :   NodeProperties::ChangeOp(matcher.IfTrue(), common->Merge(input_count));
     264      136381 :   NodeProperties::ChangeOp(matcher.IfFalse(), common->Merge(input_count));
     265             :   int const true_index =
     266      136381 :       block->SuccessorAt(0)->NodeAt(0) == matcher.IfTrue() ? 0 : 1;
     267             :   BlockEffectControlData* true_block_data =
     268      136381 :       &block_effects->For(block, block->SuccessorAt(true_index));
     269             :   BlockEffectControlData* false_block_data =
     270      136381 :       &block_effects->For(block, block->SuccessorAt(true_index ^ 1));
     271      817963 :   for (Node* const phi : phis) {
     272      706550 :     for (int index = 0; index < input_count; ++index) {
     273     1140498 :       inputs[index] = phi->InputAt(index);
     274             :     }
     275      136301 :     inputs[input_count] = merge_true;
     276      272602 :     Node* phi_true = graph->NewNode(phi->op(), input_count + 1, inputs);
     277      136300 :     inputs[input_count] = merge_false;
     278      136300 :     Node* phi_false = graph->NewNode(phi->op(), input_count + 1, inputs);
     279      136300 :     if (phi->UseCount() == 0) {
     280             :       DCHECK_EQ(phi->opcode(), IrOpcode::kEffectPhi);
     281             :     } else {
     282        3280 :       for (Edge edge : phi->use_edges()) {
     283        1312 :         Node* control = NodeProperties::GetControlInput(edge.from());
     284        2624 :         if (NodeProperties::IsPhi(edge.from())) {
     285         272 :           control = NodeProperties::GetControlInput(control, edge.index());
     286             :         }
     287             :         DCHECK(control == matcher.IfTrue() || control == matcher.IfFalse());
     288        1312 :         edge.UpdateTo((control == matcher.IfTrue()) ? phi_true : phi_false);
     289             :       }
     290             :     }
     291      136300 :     if (phi->opcode() == IrOpcode::kEffectPhi) {
     292      136300 :       true_block_data->current_effect = phi_true;
     293      136300 :       false_block_data->current_effect = phi_false;
     294             :     }
     295      136300 :     phi->Kill();
     296             :   }
     297             :   // Fix up IfTrue and IfFalse and kill all dead nodes.
     298      136380 :   if (branch == block->control_input()) {
     299      136380 :     true_block_data->current_control = merge_true;
     300      136380 :     false_block_data->current_control = merge_false;
     301             :   }
     302      136380 :   branch->Kill();
     303      136380 :   cond->Kill();
     304      136380 :   merge->Kill();
     305             : }
     306             : }  // namespace
     307             : 
     308    10341948 : 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     5417916 :   for (BasicBlock* block : *(schedule()->rpo_order())) {
     315             :     size_t instr = 0;
     316             : 
     317             :     // The control node should be the first.
     318    12434888 :     Node* control = block->NodeAt(instr);
     319             :     DCHECK(NodeProperties::IsControl(control));
     320             :     // Update the control inputs.
     321     4627305 :     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       43660 :       pending_block_controls.push_back(block);
     326             :     } else {
     327             :       // If there are no back edges, we can update now.
     328     4583645 :       UpdateBlockControl(block, &block_effects);
     329             :     }
     330             :     instr++;
     331             : 
     332             :     // Iterate over the phis and update the effect phis.
     333     4627289 :     Node* effect = nullptr;
     334             :     Node* terminate = nullptr;
     335    12241494 :     for (; instr < block->NodeCount(); instr++) {
     336     4321602 :       Node* node = block->NodeAt(instr);
     337             :       // Only go through the phis and effect phis.
     338     4321602 :       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      906297 :         effect = node;
     344             : 
     345             :         // Make sure we update the inputs to the incoming blocks' effects.
     346      906297 :         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       43663 :           pending_effect_phis.push_back(PendingEffectPhi(node, block));
     351             :         } else {
     352      862634 :           UpdateEffectPhi(node, block, &block_effects);
     353             :         }
     354     3415305 :       } else if (node->opcode() == IrOpcode::kPhi) {
     355             :         // Just skip phis.
     356     2870837 :       } else if (node->opcode() == IrOpcode::kTerminate) {
     357             :         DCHECK(terminate == nullptr);
     358             :         terminate = node;
     359             :       } else {
     360             :         break;
     361             :       }
     362             :     }
     363             : 
     364     4627353 :     if (effect == nullptr) {
     365             :       // There was no effect phi.
     366             :       DCHECK(!HasIncomingBackEdges(block));
     367     3721008 :       if (block == schedule()->start()) {
     368             :         // Start block => effect is start.
     369             :         DCHECK_EQ(graph()->start(), control);
     370      395306 :         effect = graph()->start();
     371     9583635 :       } 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      393466 :         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     2932232 :             block_effects.For(block->PredecessorAt(0), block).current_effect;
     381     6023420 :         for (size_t i = 1; i < block->PredecessorCount(); ++i) {
     382       94002 :           if (block_effects.For(block->PredecessorAt(i), block)
     383       94002 :                   .current_effect != effect) {
     384       14524 :             effect = nullptr;
     385       14524 :             break;
     386             :           }
     387             :         }
     388     2932231 :         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       29048 :           inputs_buffer.resize(block->PredecessorCount(), jsgraph()->Dead());
     394       14524 :           inputs_buffer.push_back(control);
     395             :           effect = graph()->NewNode(
     396       14524 :               common()->EffectPhi(static_cast<int>(block->PredecessorCount())),
     397       72620 :               static_cast<int>(inputs_buffer.size()), &(inputs_buffer.front()));
     398             :           // For loops, we update the effect phi node later to break cycles.
     399       29048 :           if (control->opcode() == IrOpcode::kLoop) {
     400           0 :             pending_effect_phis.push_back(PendingEffectPhi(effect, block));
     401             :           } else {
     402       14524 :             UpdateEffectPhi(effect, block, &block_effects);
     403             :           }
     404     5835414 :         } 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      232513 :           NodeProperties::ReplaceEffectInput(control, effect);
     408      232513 :           effect = control;
     409             :         }
     410             :       }
     411             :     }
     412             : 
     413             :     // Fixup the Terminate node.
     414     4627348 :     if (terminate != nullptr) {
     415       42684 :       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     4627348 :     Node* frame_state = nullptr;
     424     4627348 :     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     4231984 :           block_effects.For(block->PredecessorAt(0), block).current_frame_state;
     429    10610742 :       for (size_t i = 1; i < block->PredecessorCount(); i++) {
     430     1310364 :         if (block_effects.For(block->PredecessorAt(i), block)
     431     1310364 :                 .current_frame_state != frame_state) {
     432      236977 :           frame_state = nullptr;
     433      236977 :           frame_state_zapper_ = graph()->end();
     434      236977 :           break;
     435             :         }
     436             :       }
     437             :     }
     438             : 
     439             :     // Process the ordinary instructions.
     440    61228288 :     for (; instr < block->NodeCount(); instr++) {
     441             :       Node* node = block->NodeAt(instr);
     442    28300549 :       ProcessNode(node, &frame_state, &effect, &control);
     443             :     }
     444             : 
     445     4627276 :     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      803403 :         ProcessNode(block->control_input(), &frame_state, &effect, &control);
     457      803401 :         break;
     458             : 
     459             :       case BasicBlock::kBranch:
     460     1188450 :         ProcessNode(block->control_input(), &frame_state, &effect, &control);
     461             :         TryCloneBranch(block->control_input(), block, temp_zone(), graph(),
     462     3565362 :                        common(), &block_effects, source_positions_);
     463     1188449 :         break;
     464             :     }
     465             : 
     466             :     // Store the effect, control and frame state for later use.
     467    19536610 :     for (BasicBlock* successor : block->successors()) {
     468     5654762 :       BlockEffectControlData* data = &block_effects.For(block, successor);
     469     5654791 :       if (data->current_effect == nullptr) {
     470     5382192 :         data->current_effect = effect;
     471             :       }
     472     5654791 :       if (data->current_control == nullptr) {
     473     5382037 :         data->current_control = control;
     474             :       }
     475     5654791 :       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      834271 :   for (const PendingEffectPhi& pending_effect_phi : pending_effect_phis) {
     482             :     UpdateEffectPhi(pending_effect_phi.effect_phi, pending_effect_phi.block,
     483       43663 :                     &block_effects);
     484             :   }
     485      834271 :   for (BasicBlock* pending_block_control : pending_block_controls) {
     486       43663 :     UpdateBlockControl(pending_block_control, &block_effects);
     487             :   }
     488      395303 : }
     489             : 
     490   128381765 : void EffectControlLinearizer::ProcessNode(Node* node, Node** frame_state,
     491             :                                           Node** effect, Node** control) {
     492             :   SourcePositionTable::Scope scope(source_positions_,
     493    30292249 :                                    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    30292257 :   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    57979368 :   if (region_observability_ == RegionObservability::kObservable &&
     505             :       !node->op()->HasProperty(Operator::kNoWrite)) {
     506     3112768 :     *frame_state = nullptr;
     507     3112768 :     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    29417881 :   if (node->opcode() == IrOpcode::kFinishRegion) {
     513             :     // Reset the current region observability.
     514       94448 :     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       94448 :     return RemoveRegionNode(node);
     518             :   }
     519    29323433 :   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       94448 :     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       94448 :     return RemoveRegionNode(node);
     528             :   }
     529             : 
     530             :   // Special treatment for checkpoint nodes.
     531    29228985 :   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     2192055 :     *frame_state = NodeProperties::GetFrameStateInput(node);
     536     2192054 :     return;
     537             :   }
     538             : 
     539    27036930 :   if (node->opcode() == IrOpcode::kIfSuccess) {
     540             :     // We always schedule IfSuccess with its call, so skip it here.
     541             :     DCHECK_EQ(IrOpcode::kCall, node->InputAt(0)->opcode());
     542             :     // The IfSuccess node should not belong to an exceptional call node
     543             :     // because such IfSuccess nodes should only start a basic block (and
     544             :     // basic block start nodes are not handled in the ProcessNode method).
     545             :     DCHECK(!NodeProperties::IsExceptionalCall(node->InputAt(0)));
     546             :     return;
     547             :   }
     548             : 
     549             :   // If the node takes an effect, replace with the current one.
     550    54073874 :   if (node->op()->EffectInputCount() > 0) {
     551             :     DCHECK_EQ(1, node->op()->EffectInputCount());
     552     5990738 :     Node* input_effect = NodeProperties::GetEffectInput(node);
     553             : 
     554     5990737 :     if (input_effect != *effect) {
     555     2658059 :       NodeProperties::ReplaceEffectInput(node, *effect);
     556             :     }
     557             : 
     558             :     // If the node produces an effect, update our current effect. (However,
     559             :     // ignore new effect chains started with ValueEffect.)
     560    11981392 :     if (node->op()->EffectOutputCount() > 0) {
     561             :       DCHECK_EQ(1, node->op()->EffectOutputCount());
     562     5419844 :       *effect = node;
     563             :     }
     564             :   } else {
     565             :     // New effect chain is only started with a Start or ValueEffect node.
     566             :     DCHECK(node->op()->EffectOutputCount() == 0 ||
     567             :            node->opcode() == IrOpcode::kStart);
     568             :   }
     569             : 
     570             :   // Rewire control inputs.
     571    75321461 :   for (int i = 0; i < node->op()->ControlInputCount(); i++) {
     572     7082562 :     NodeProperties::ReplaceControlInput(node, *control, i);
     573             :   }
     574             :   // Update the current control.
     575    54073780 :   if (node->op()->ControlOutputCount() > 0) {
     576     4168069 :     *control = node;
     577             :   }
     578             : }
     579             : 
     580    60584543 : bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
     581             :                                                    Node* frame_state,
     582             :                                                    Node** effect,
     583             :                                                    Node** control) {
     584    30292274 :   gasm()->Reset(*effect, *control);
     585             :   Node* result = nullptr;
     586    30292269 :   switch (node->opcode()) {
     587             :     case IrOpcode::kChangeBitToTagged:
     588       17544 :       result = LowerChangeBitToTagged(node);
     589       17544 :       break;
     590             :     case IrOpcode::kChangeInt31ToTaggedSigned:
     591       15150 :       result = LowerChangeInt31ToTaggedSigned(node);
     592       15150 :       break;
     593             :     case IrOpcode::kChangeInt32ToTagged:
     594       35722 :       result = LowerChangeInt32ToTagged(node);
     595       35722 :       break;
     596             :     case IrOpcode::kChangeUint32ToTagged:
     597         684 :       result = LowerChangeUint32ToTagged(node);
     598         684 :       break;
     599             :     case IrOpcode::kChangeFloat64ToTagged:
     600       46542 :       result = LowerChangeFloat64ToTagged(node);
     601       46543 :       break;
     602             :     case IrOpcode::kChangeFloat64ToTaggedPointer:
     603          62 :       result = LowerChangeFloat64ToTaggedPointer(node);
     604          62 :       break;
     605             :     case IrOpcode::kChangeTaggedSignedToInt32:
     606       59991 :       result = LowerChangeTaggedSignedToInt32(node);
     607       59992 :       break;
     608             :     case IrOpcode::kChangeTaggedToBit:
     609      182395 :       result = LowerChangeTaggedToBit(node);
     610      182394 :       break;
     611             :     case IrOpcode::kChangeTaggedToInt32:
     612        4769 :       result = LowerChangeTaggedToInt32(node);
     613        4769 :       break;
     614             :     case IrOpcode::kChangeTaggedToUint32:
     615         331 :       result = LowerChangeTaggedToUint32(node);
     616         331 :       break;
     617             :     case IrOpcode::kChangeTaggedToFloat64:
     618             :       result = LowerChangeTaggedToFloat64(node);
     619       32644 :       break;
     620             :     case IrOpcode::kChangeTaggedToTaggedSigned:
     621           8 :       result = LowerChangeTaggedToTaggedSigned(node);
     622           8 :       break;
     623             :     case IrOpcode::kTruncateTaggedToBit:
     624       79122 :       result = LowerTruncateTaggedToBit(node);
     625       79122 :       break;
     626             :     case IrOpcode::kTruncateTaggedPointerToBit:
     627         142 :       result = LowerTruncateTaggedPointerToBit(node);
     628         142 :       break;
     629             :     case IrOpcode::kTruncateTaggedToFloat64:
     630         231 :       result = LowerTruncateTaggedToFloat64(node);
     631         231 :       break;
     632             :     case IrOpcode::kCheckBounds:
     633       24906 :       result = LowerCheckBounds(node, frame_state);
     634       24906 :       break;
     635             :     case IrOpcode::kCheckMaps:
     636       47324 :       result = LowerCheckMaps(node, frame_state);
     637       47324 :       break;
     638             :     case IrOpcode::kCheckNumber:
     639         451 :       result = LowerCheckNumber(node, frame_state);
     640         451 :       break;
     641             :     case IrOpcode::kCheckReceiver:
     642         473 :       result = LowerCheckReceiver(node, frame_state);
     643         473 :       break;
     644             :     case IrOpcode::kCheckString:
     645        1196 :       result = LowerCheckString(node, frame_state);
     646        1196 :       break;
     647             :     case IrOpcode::kCheckInternalizedString:
     648        1757 :       result = LowerCheckInternalizedString(node, frame_state);
     649        1757 :       break;
     650             :     case IrOpcode::kCheckIf:
     651       29523 :       result = LowerCheckIf(node, frame_state);
     652       29523 :       break;
     653             :     case IrOpcode::kCheckedInt32Add:
     654       42749 :       result = LowerCheckedInt32Add(node, frame_state);
     655       42748 :       break;
     656             :     case IrOpcode::kCheckedInt32Sub:
     657       18699 :       result = LowerCheckedInt32Sub(node, frame_state);
     658       18699 :       break;
     659             :     case IrOpcode::kCheckedInt32Div:
     660         228 :       result = LowerCheckedInt32Div(node, frame_state);
     661         228 :       break;
     662             :     case IrOpcode::kCheckedInt32Mod:
     663        1017 :       result = LowerCheckedInt32Mod(node, frame_state);
     664        1017 :       break;
     665             :     case IrOpcode::kCheckedUint32Div:
     666         100 :       result = LowerCheckedUint32Div(node, frame_state);
     667         100 :       break;
     668             :     case IrOpcode::kCheckedUint32Mod:
     669          69 :       result = LowerCheckedUint32Mod(node, frame_state);
     670          69 :       break;
     671             :     case IrOpcode::kCheckedInt32Mul:
     672        6747 :       result = LowerCheckedInt32Mul(node, frame_state);
     673        6747 :       break;
     674             :     case IrOpcode::kCheckedInt32ToTaggedSigned:
     675           0 :       result = LowerCheckedInt32ToTaggedSigned(node, frame_state);
     676           0 :       break;
     677             :     case IrOpcode::kCheckedUint32ToInt32:
     678         219 :       result = LowerCheckedUint32ToInt32(node, frame_state);
     679         219 :       break;
     680             :     case IrOpcode::kCheckedUint32ToTaggedSigned:
     681          24 :       result = LowerCheckedUint32ToTaggedSigned(node, frame_state);
     682          24 :       break;
     683             :     case IrOpcode::kCheckedFloat64ToInt32:
     684        6193 :       result = LowerCheckedFloat64ToInt32(node, frame_state);
     685        6193 :       break;
     686             :     case IrOpcode::kCheckedTaggedSignedToInt32:
     687       27194 :       if (frame_state == nullptr) {
     688             :         V8_Fatal(__FILE__, __LINE__, "No frame state (zapped by #%d: %s)",
     689             :                  frame_state_zapper_->id(),
     690           0 :                  frame_state_zapper_->op()->mnemonic());
     691             :       }
     692       27194 :       result = LowerCheckedTaggedSignedToInt32(node, frame_state);
     693       27194 :       break;
     694             :     case IrOpcode::kCheckedTaggedToInt32:
     695        2490 :       result = LowerCheckedTaggedToInt32(node, frame_state);
     696        2490 :       break;
     697             :     case IrOpcode::kCheckedTaggedToFloat64:
     698       20767 :       result = LowerCheckedTaggedToFloat64(node, frame_state);
     699       20767 :       break;
     700             :     case IrOpcode::kCheckedTaggedToTaggedSigned:
     701       23022 :       result = LowerCheckedTaggedToTaggedSigned(node, frame_state);
     702       23022 :       break;
     703             :     case IrOpcode::kCheckedTaggedToTaggedPointer:
     704       19690 :       result = LowerCheckedTaggedToTaggedPointer(node, frame_state);
     705       19690 :       break;
     706             :     case IrOpcode::kTruncateTaggedToWord32:
     707        1155 :       result = LowerTruncateTaggedToWord32(node);
     708        1155 :       break;
     709             :     case IrOpcode::kCheckedTruncateTaggedToWord32:
     710        2075 :       result = LowerCheckedTruncateTaggedToWord32(node, frame_state);
     711        2076 :       break;
     712             :     case IrOpcode::kObjectIsDetectableCallable:
     713       17020 :       result = LowerObjectIsDetectableCallable(node);
     714       17020 :       break;
     715             :     case IrOpcode::kObjectIsNaN:
     716        2976 :       result = LowerObjectIsNaN(node);
     717        2976 :       break;
     718             :     case IrOpcode::kObjectIsNonCallable:
     719        8189 :       result = LowerObjectIsNonCallable(node);
     720        8189 :       break;
     721             :     case IrOpcode::kObjectIsNumber:
     722       11024 :       result = LowerObjectIsNumber(node);
     723       11024 :       break;
     724             :     case IrOpcode::kObjectIsReceiver:
     725       21909 :       result = LowerObjectIsReceiver(node);
     726       21909 :       break;
     727             :     case IrOpcode::kObjectIsSmi:
     728        8555 :       result = LowerObjectIsSmi(node);
     729        8556 :       break;
     730             :     case IrOpcode::kObjectIsString:
     731        4846 :       result = LowerObjectIsString(node);
     732        4846 :       break;
     733             :     case IrOpcode::kObjectIsSymbol:
     734         665 :       result = LowerObjectIsSymbol(node);
     735         665 :       break;
     736             :     case IrOpcode::kObjectIsUndetectable:
     737        8923 :       result = LowerObjectIsUndetectable(node);
     738        8923 :       break;
     739             :     case IrOpcode::kArgumentsFrame:
     740        3951 :       result = LowerArgumentsFrame(node);
     741        3951 :       break;
     742             :     case IrOpcode::kArgumentsLength:
     743        3998 :       result = LowerArgumentsLength(node);
     744        3998 :       break;
     745             :     case IrOpcode::kNewUnmappedArgumentsElements:
     746        3798 :       result = LowerNewUnmappedArgumentsElements(node);
     747        3798 :       break;
     748             :     case IrOpcode::kArrayBufferWasNeutered:
     749         325 :       result = LowerArrayBufferWasNeutered(node);
     750         325 :       break;
     751             :     case IrOpcode::kStringFromCharCode:
     752         752 :       result = LowerStringFromCharCode(node);
     753         752 :       break;
     754             :     case IrOpcode::kStringFromCodePoint:
     755          57 :       result = LowerStringFromCodePoint(node);
     756          57 :       break;
     757             :     case IrOpcode::kStringIndexOf:
     758         168 :       result = LowerStringIndexOf(node);
     759         168 :       break;
     760             :     case IrOpcode::kStringCharAt:
     761         287 :       result = LowerStringCharAt(node);
     762         287 :       break;
     763             :     case IrOpcode::kStringCharCodeAt:
     764         379 :       result = LowerStringCharCodeAt(node);
     765         379 :       break;
     766             :     case IrOpcode::kStringEqual:
     767        2205 :       result = LowerStringEqual(node);
     768        2205 :       break;
     769             :     case IrOpcode::kStringLessThan:
     770         379 :       result = LowerStringLessThan(node);
     771         379 :       break;
     772             :     case IrOpcode::kStringLessThanOrEqual:
     773         105 :       result = LowerStringLessThanOrEqual(node);
     774         105 :       break;
     775             :     case IrOpcode::kCheckFloat64Hole:
     776         651 :       result = LowerCheckFloat64Hole(node, frame_state);
     777         651 :       break;
     778             :     case IrOpcode::kCheckTaggedHole:
     779         917 :       result = LowerCheckTaggedHole(node, frame_state);
     780         917 :       break;
     781             :     case IrOpcode::kConvertTaggedHoleToUndefined:
     782        1529 :       result = LowerConvertTaggedHoleToUndefined(node);
     783        1529 :       break;
     784             :     case IrOpcode::kPlainPrimitiveToNumber:
     785          16 :       result = LowerPlainPrimitiveToNumber(node);
     786          16 :       break;
     787             :     case IrOpcode::kPlainPrimitiveToWord32:
     788        6372 :       result = LowerPlainPrimitiveToWord32(node);
     789        6370 :       break;
     790             :     case IrOpcode::kPlainPrimitiveToFloat64:
     791        1891 :       result = LowerPlainPrimitiveToFloat64(node);
     792        1891 :       break;
     793             :     case IrOpcode::kEnsureWritableFastElements:
     794         181 :       result = LowerEnsureWritableFastElements(node);
     795         181 :       break;
     796             :     case IrOpcode::kMaybeGrowFastElements:
     797        2054 :       result = LowerMaybeGrowFastElements(node, frame_state);
     798        2054 :       break;
     799             :     case IrOpcode::kTransitionElementsKind:
     800         462 :       LowerTransitionElementsKind(node);
     801         462 :       break;
     802             :     case IrOpcode::kLoadTypedElement:
     803        3452 :       result = LowerLoadTypedElement(node);
     804        3452 :       break;
     805             :     case IrOpcode::kStoreTypedElement:
     806        3062 :       LowerStoreTypedElement(node);
     807        3062 :       break;
     808             :     case IrOpcode::kFloat64RoundUp:
     809       11544 :       if (!LowerFloat64RoundUp(node).To(&result)) {
     810             :         return false;
     811             :       }
     812             :       break;
     813             :     case IrOpcode::kFloat64RoundDown:
     814       17750 :       if (!LowerFloat64RoundDown(node).To(&result)) {
     815             :         return false;
     816             :       }
     817             :       break;
     818             :     case IrOpcode::kFloat64RoundTruncate:
     819        2778 :       if (!LowerFloat64RoundTruncate(node).To(&result)) {
     820             :         return false;
     821             :       }
     822             :       break;
     823             :     case IrOpcode::kFloat64RoundTiesEven:
     824         600 :       if (!LowerFloat64RoundTiesEven(node).To(&result)) {
     825             :         return false;
     826             :       }
     827             :       break;
     828             :     default:
     829             :       return false;
     830             :   }
     831      874503 :   *effect = gasm()->ExtractCurrentEffect();
     832      874498 :   *control = gasm()->ExtractCurrentControl();
     833      874499 :   NodeProperties::ReplaceUses(node, result, *effect, *control);
     834      874505 :   return true;
     835             : }
     836             : 
     837             : #define __ gasm()->
     838             : 
     839       46542 : Node* EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node) {
     840       46542 :   CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
     841             :   Node* value = node->InputAt(0);
     842             : 
     843       46543 :   auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
     844             :   auto if_heapnumber =
     845             :       __ MakeLabelFor(GraphAssemblerLabelType::kNonDeferred,
     846       93086 :                       1 + (mode == CheckForMinusZeroMode::kCheckForMinusZero) +
     847      139629 :                           !machine()->Is64());
     848       46542 :   auto if_int32 = __ MakeLabel<1>();
     849             : 
     850       46542 :   Node* value32 = __ RoundFloat64ToInt32(value);
     851             :   __ GotoIf(__ Float64Equal(value, __ ChangeInt32ToFloat64(value32)),
     852       46543 :             &if_int32);
     853             :   __ Goto(&if_heapnumber);
     854             : 
     855             :   __ Bind(&if_int32);
     856             :   {
     857       46542 :     if (mode == CheckForMinusZeroMode::kCheckForMinusZero) {
     858       26068 :       Node* zero = __ Int32Constant(0);
     859       26069 :       auto if_zero = __ MakeDeferredLabel<1>();
     860       26069 :       auto if_smi = __ MakeLabel<2>();
     861             : 
     862       26069 :       __ GotoIf(__ Word32Equal(value32, zero), &if_zero);
     863             :       __ Goto(&if_smi);
     864             : 
     865             :       __ Bind(&if_zero);
     866             :       {
     867             :         // In case of 0, we need to check the high bits for the IEEE -0 pattern.
     868             :         __ GotoIf(__ Int32LessThan(__ Float64ExtractHighWord32(value), zero),
     869       26069 :                   &if_heapnumber);
     870             :         __ Goto(&if_smi);
     871             :       }
     872             : 
     873       26069 :       __ Bind(&if_smi);
     874             :     }
     875             : 
     876       46543 :     if (machine()->Is64()) {
     877       46543 :       Node* value_smi = ChangeInt32ToSmi(value32);
     878             :       __ Goto(&done, value_smi);
     879             :     } else {
     880           0 :       Node* add = __ Int32AddWithOverflow(value32, value32);
     881           0 :       Node* ovf = __ Projection(1, add);
     882           0 :       __ GotoIf(ovf, &if_heapnumber);
     883           0 :       Node* value_smi = __ Projection(0, add);
     884             :       __ Goto(&done, value_smi);
     885             :     }
     886             :   }
     887             : 
     888       46542 :   __ Bind(&if_heapnumber);
     889             :   {
     890       46542 :     Node* value_number = AllocateHeapNumberWithValue(value);
     891             :     __ Goto(&done, value_number);
     892             :   }
     893             : 
     894       46543 :   __ Bind(&done);
     895       46543 :   return done.PhiAt(0);
     896             : }
     897             : 
     898          62 : Node* EffectControlLinearizer::LowerChangeFloat64ToTaggedPointer(Node* node) {
     899             :   Node* value = node->InputAt(0);
     900          62 :   return AllocateHeapNumberWithValue(value);
     901             : }
     902             : 
     903       17544 : Node* EffectControlLinearizer::LowerChangeBitToTagged(Node* node) {
     904             :   Node* value = node->InputAt(0);
     905             : 
     906       17544 :   auto if_true = __ MakeLabel<1>();
     907       17544 :   auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
     908             : 
     909       17544 :   __ GotoIf(value, &if_true);
     910       17544 :   __ Goto(&done, __ FalseConstant());
     911             : 
     912             :   __ Bind(&if_true);
     913       17544 :   __ Goto(&done, __ TrueConstant());
     914             : 
     915       17544 :   __ Bind(&done);
     916       17544 :   return done.PhiAt(0);
     917             : }
     918             : 
     919       15150 : Node* EffectControlLinearizer::LowerChangeInt31ToTaggedSigned(Node* node) {
     920             :   Node* value = node->InputAt(0);
     921       15150 :   return ChangeInt32ToSmi(value);
     922             : }
     923             : 
     924       35721 : Node* EffectControlLinearizer::LowerChangeInt32ToTagged(Node* node) {
     925             :   Node* value = node->InputAt(0);
     926             : 
     927       35721 :   if (machine()->Is64()) {
     928       35721 :     return ChangeInt32ToSmi(value);
     929             :   }
     930             : 
     931           0 :   auto if_overflow = __ MakeDeferredLabel<1>();
     932           0 :   auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
     933             : 
     934           0 :   Node* add = __ Int32AddWithOverflow(value, value);
     935           0 :   Node* ovf = __ Projection(1, add);
     936           0 :   __ GotoIf(ovf, &if_overflow);
     937           0 :   __ Goto(&done, __ Projection(0, add));
     938             : 
     939             :   __ Bind(&if_overflow);
     940           0 :   Node* number = AllocateHeapNumberWithValue(__ ChangeInt32ToFloat64(value));
     941             :   __ Goto(&done, number);
     942             : 
     943           0 :   __ Bind(&done);
     944             :   return done.PhiAt(0);
     945             : }
     946             : 
     947         684 : Node* EffectControlLinearizer::LowerChangeUint32ToTagged(Node* node) {
     948             :   Node* value = node->InputAt(0);
     949             : 
     950         684 :   auto if_not_in_smi_range = __ MakeDeferredLabel<1>();
     951         684 :   auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
     952             : 
     953         684 :   Node* check = __ Uint32LessThanOrEqual(value, SmiMaxValueConstant());
     954         684 :   __ GotoUnless(check, &if_not_in_smi_range);
     955         684 :   __ Goto(&done, ChangeUint32ToSmi(value));
     956             : 
     957             :   __ Bind(&if_not_in_smi_range);
     958         684 :   Node* number = AllocateHeapNumberWithValue(__ ChangeUint32ToFloat64(value));
     959             : 
     960             :   __ Goto(&done, number);
     961         684 :   __ Bind(&done);
     962             : 
     963         684 :   return done.PhiAt(0);
     964             : }
     965             : 
     966       59991 : Node* EffectControlLinearizer::LowerChangeTaggedSignedToInt32(Node* node) {
     967             :   Node* value = node->InputAt(0);
     968       59991 :   return ChangeSmiToInt32(value);
     969             : }
     970             : 
     971      182395 : Node* EffectControlLinearizer::LowerChangeTaggedToBit(Node* node) {
     972             :   Node* value = node->InputAt(0);
     973      182395 :   return __ WordEqual(value, __ TrueConstant());
     974             : }
     975             : 
     976       79122 : Node* EffectControlLinearizer::LowerTruncateTaggedToBit(Node* node) {
     977             :   Node* value = node->InputAt(0);
     978             : 
     979       79122 :   auto if_smi = __ MakeDeferredLabel<1>();
     980       79122 :   auto if_heapnumber = __ MakeDeferredLabel<1>();
     981       79122 :   auto done = __ MakeLabel<6>(MachineRepresentation::kBit);
     982             : 
     983       79122 :   Node* zero = __ Int32Constant(0);
     984       79122 :   Node* fzero = __ Float64Constant(0.0);
     985             : 
     986             :   // Check if {value} is false.
     987       79122 :   __ GotoIf(__ WordEqual(value, __ FalseConstant()), &done, zero);
     988             : 
     989             :   // Check if {value} is a Smi.
     990       79122 :   Node* check_smi = ObjectIsSmi(value);
     991       79122 :   __ GotoIf(check_smi, &if_smi);
     992             : 
     993             :   // Check if {value} is the empty string.
     994       79122 :   __ GotoIf(__ WordEqual(value, __ EmptyStringConstant()), &done, zero);
     995             : 
     996             :   // Load the map of {value}.
     997       79122 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
     998             : 
     999             :   // Check if the {value} is undetectable and immediately return false.
    1000             :   Node* value_map_bitfield =
    1001       79122 :       __ LoadField(AccessBuilder::ForMapBitField(), value_map);
    1002             :   __ GotoUnless(
    1003             :       __ Word32Equal(__ Word32And(value_map_bitfield,
    1004             :                                   __ Int32Constant(1 << Map::kIsUndetectable)),
    1005             :                      zero),
    1006       79122 :       &done, zero);
    1007             : 
    1008             :   // Check if {value} is a HeapNumber.
    1009             :   __ GotoIf(__ WordEqual(value_map, __ HeapNumberMapConstant()),
    1010       79122 :             &if_heapnumber);
    1011             : 
    1012             :   // All other values that reach here are true.
    1013       79122 :   __ Goto(&done, __ Int32Constant(1));
    1014             : 
    1015             :   __ Bind(&if_heapnumber);
    1016             :   {
    1017             :     // For HeapNumber {value}, just check that its value is not 0.0, -0.0 or
    1018             :     // NaN.
    1019             :     Node* value_value =
    1020       79122 :         __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1021       79122 :     __ Goto(&done, __ Float64LessThan(fzero, __ Float64Abs(value_value)));
    1022             :   }
    1023             : 
    1024             :   __ Bind(&if_smi);
    1025             :   {
    1026             :     // If {value} is a Smi, then we only need to check that it's not zero.
    1027             :     __ Goto(&done,
    1028       79122 :             __ Word32Equal(__ WordEqual(value, __ IntPtrConstant(0)), zero));
    1029             :   }
    1030             : 
    1031       79122 :   __ Bind(&done);
    1032       79122 :   return done.PhiAt(0);
    1033             : }
    1034             : 
    1035         142 : Node* EffectControlLinearizer::LowerTruncateTaggedPointerToBit(Node* node) {
    1036             :   Node* value = node->InputAt(0);
    1037             : 
    1038         142 :   auto if_heapnumber = __ MakeDeferredLabel<1>();
    1039         142 :   auto done = __ MakeLabel<5>(MachineRepresentation::kBit);
    1040             : 
    1041         142 :   Node* zero = __ Int32Constant(0);
    1042         142 :   Node* fzero = __ Float64Constant(0.0);
    1043             : 
    1044             :   // Check if {value} is false.
    1045         142 :   __ GotoIf(__ WordEqual(value, __ FalseConstant()), &done, zero);
    1046             : 
    1047             :   // Check if {value} is the empty string.
    1048         142 :   __ GotoIf(__ WordEqual(value, __ EmptyStringConstant()), &done, zero);
    1049             : 
    1050             :   // Load the map of {value}.
    1051         142 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1052             : 
    1053             :   // Check if the {value} is undetectable and immediately return false.
    1054             :   Node* value_map_bitfield =
    1055         142 :       __ LoadField(AccessBuilder::ForMapBitField(), value_map);
    1056             :   __ GotoUnless(
    1057             :       __ Word32Equal(__ Word32And(value_map_bitfield,
    1058             :                                   __ Int32Constant(1 << Map::kIsUndetectable)),
    1059             :                      zero),
    1060         142 :       &done, zero);
    1061             : 
    1062             :   // Check if {value} is a HeapNumber.
    1063             :   __ GotoIf(__ WordEqual(value_map, __ HeapNumberMapConstant()),
    1064         142 :             &if_heapnumber);
    1065             : 
    1066             :   // All other values that reach here are true.
    1067         142 :   __ Goto(&done, __ Int32Constant(1));
    1068             : 
    1069             :   __ Bind(&if_heapnumber);
    1070             :   {
    1071             :     // For HeapNumber {value}, just check that its value is not 0.0, -0.0 or
    1072             :     // NaN.
    1073             :     Node* value_value =
    1074         142 :         __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1075         142 :     __ Goto(&done, __ Float64LessThan(fzero, __ Float64Abs(value_value)));
    1076             :   }
    1077             : 
    1078         142 :   __ Bind(&done);
    1079         142 :   return done.PhiAt(0);
    1080             : }
    1081             : 
    1082        4769 : Node* EffectControlLinearizer::LowerChangeTaggedToInt32(Node* node) {
    1083             :   Node* value = node->InputAt(0);
    1084             : 
    1085        4769 :   auto if_not_smi = __ MakeDeferredLabel<1>();
    1086        4769 :   auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
    1087             : 
    1088        4769 :   Node* check = ObjectIsSmi(value);
    1089        4769 :   __ GotoUnless(check, &if_not_smi);
    1090        4769 :   __ Goto(&done, ChangeSmiToInt32(value));
    1091             : 
    1092             :   __ Bind(&if_not_smi);
    1093             :   STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    1094        4769 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1095        4769 :   vfalse = __ ChangeFloat64ToInt32(vfalse);
    1096             :   __ Goto(&done, vfalse);
    1097             : 
    1098        4769 :   __ Bind(&done);
    1099        4769 :   return done.PhiAt(0);
    1100             : }
    1101             : 
    1102         331 : Node* EffectControlLinearizer::LowerChangeTaggedToUint32(Node* node) {
    1103             :   Node* value = node->InputAt(0);
    1104             : 
    1105         331 :   auto if_not_smi = __ MakeDeferredLabel<1>();
    1106         331 :   auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
    1107             : 
    1108         331 :   Node* check = ObjectIsSmi(value);
    1109         331 :   __ GotoUnless(check, &if_not_smi);
    1110         331 :   __ Goto(&done, ChangeSmiToInt32(value));
    1111             : 
    1112             :   __ Bind(&if_not_smi);
    1113             :   STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    1114         331 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1115         331 :   vfalse = __ ChangeFloat64ToUint32(vfalse);
    1116             :   __ Goto(&done, vfalse);
    1117             : 
    1118         331 :   __ Bind(&done);
    1119         331 :   return done.PhiAt(0);
    1120             : }
    1121             : 
    1122           0 : Node* EffectControlLinearizer::LowerChangeTaggedToFloat64(Node* node) {
    1123       32644 :   return LowerTruncateTaggedToFloat64(node);
    1124             : }
    1125             : 
    1126           8 : Node* EffectControlLinearizer::LowerChangeTaggedToTaggedSigned(Node* node) {
    1127             :   Node* value = node->InputAt(0);
    1128             : 
    1129           8 :   auto if_not_smi = __ MakeDeferredLabel<1>();
    1130           8 :   auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
    1131             : 
    1132           8 :   Node* check = ObjectIsSmi(value);
    1133           8 :   __ GotoUnless(check, &if_not_smi);
    1134             :   __ Goto(&done, value);
    1135             : 
    1136             :   __ Bind(&if_not_smi);
    1137             :   STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    1138           8 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1139           8 :   vfalse = __ ChangeFloat64ToInt32(vfalse);
    1140           8 :   vfalse = ChangeInt32ToSmi(vfalse);
    1141             :   __ Goto(&done, vfalse);
    1142             : 
    1143           8 :   __ Bind(&done);
    1144           8 :   return done.PhiAt(0);
    1145             : }
    1146             : 
    1147       32875 : Node* EffectControlLinearizer::LowerTruncateTaggedToFloat64(Node* node) {
    1148             :   Node* value = node->InputAt(0);
    1149             : 
    1150       32875 :   auto if_not_smi = __ MakeDeferredLabel<1>();
    1151       32875 :   auto done = __ MakeLabel<2>(MachineRepresentation::kFloat64);
    1152             : 
    1153       32875 :   Node* check = ObjectIsSmi(value);
    1154       32875 :   __ GotoUnless(check, &if_not_smi);
    1155       32875 :   Node* vtrue = ChangeSmiToInt32(value);
    1156       32875 :   vtrue = __ ChangeInt32ToFloat64(vtrue);
    1157             :   __ Goto(&done, vtrue);
    1158             : 
    1159             :   __ Bind(&if_not_smi);
    1160             :   STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    1161       32875 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1162             :   __ Goto(&done, vfalse);
    1163             : 
    1164       32875 :   __ Bind(&done);
    1165       32875 :   return done.PhiAt(0);
    1166             : }
    1167             : 
    1168       24906 : Node* EffectControlLinearizer::LowerCheckBounds(Node* node, Node* frame_state) {
    1169             :   Node* index = node->InputAt(0);
    1170             :   Node* limit = node->InputAt(1);
    1171             : 
    1172       24906 :   Node* check = __ Uint32LessThan(index, limit);
    1173       24906 :   __ DeoptimizeUnless(DeoptimizeReason::kOutOfBounds, check, frame_state);
    1174       24906 :   return index;
    1175             : }
    1176             : 
    1177       47324 : Node* EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
    1178       47324 :   CheckMapsParameters const& p = CheckMapsParametersOf(node->op());
    1179             :   Node* value = node->InputAt(0);
    1180             : 
    1181             :   ZoneHandleSet<Map> const& maps = p.maps();
    1182             :   size_t const map_count = maps.size();
    1183             : 
    1184       47324 :   if (p.flags() & CheckMapsFlag::kTryMigrateInstance) {
    1185             :     auto done =
    1186         697 :         __ MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, map_count * 2);
    1187         697 :     auto migrate = __ MakeDeferredLabel<1>();
    1188             : 
    1189             :     // Load the current map of the {value}.
    1190         697 :     Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1191             : 
    1192             :     // Perform the map checks.
    1193        1500 :     for (size_t i = 0; i < map_count; ++i) {
    1194         803 :       Node* map = __ HeapConstant(maps[i]);
    1195         803 :       Node* check = __ WordEqual(value_map, map);
    1196         803 :       if (i == map_count - 1) {
    1197         697 :         __ GotoUnless(check, &migrate);
    1198             :         __ Goto(&done);
    1199             :       } else {
    1200         106 :         __ GotoIf(check, &done);
    1201             :       }
    1202             :     }
    1203             : 
    1204             :     // Perform the (deferred) instance migration.
    1205             :     __ Bind(&migrate);
    1206             :     {
    1207             :       // If map is not deprecated the migration attempt does not make sense.
    1208             :       Node* bitfield3 =
    1209         697 :           __ LoadField(AccessBuilder::ForMapBitField3(), value_map);
    1210             :       Node* if_not_deprecated = __ WordEqual(
    1211             :           __ Word32And(bitfield3, __ Int32Constant(Map::Deprecated::kMask)),
    1212         697 :           __ Int32Constant(0));
    1213             :       __ DeoptimizeIf(DeoptimizeReason::kWrongMap, if_not_deprecated,
    1214         697 :                       frame_state);
    1215             : 
    1216         697 :       Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
    1217             :       Runtime::FunctionId id = Runtime::kTryMigrateInstance;
    1218             :       CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
    1219         697 :           graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags);
    1220             :       Node* result =
    1221             :           __ Call(desc, __ CEntryStubConstant(1), value,
    1222             :                   __ ExternalConstant(ExternalReference(id, isolate())),
    1223        1394 :                   __ Int32Constant(1), __ NoContextConstant());
    1224         697 :       Node* check = ObjectIsSmi(result);
    1225             :       __ DeoptimizeIf(DeoptimizeReason::kInstanceMigrationFailed, check,
    1226         697 :                       frame_state);
    1227             :     }
    1228             : 
    1229             :     // Reload the current map of the {value}.
    1230         697 :     value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1231             : 
    1232             :     // Perform the map checks again.
    1233        1500 :     for (size_t i = 0; i < map_count; ++i) {
    1234         803 :       Node* map = __ HeapConstant(maps[i]);
    1235         803 :       Node* check = __ WordEqual(value_map, map);
    1236         803 :       if (i == map_count - 1) {
    1237         697 :         __ DeoptimizeUnless(DeoptimizeReason::kWrongMap, check, frame_state);
    1238             :       } else {
    1239         106 :         __ GotoIf(check, &done);
    1240             :       }
    1241             :     }
    1242             : 
    1243             :     __ Goto(&done);
    1244         697 :     __ Bind(&done);
    1245             :   } else {
    1246             :     auto done =
    1247             :         __ MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, map_count);
    1248             : 
    1249             :     // Load the current map of the {value}.
    1250       46627 :     Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1251             : 
    1252       95617 :     for (size_t i = 0; i < map_count; ++i) {
    1253       48990 :       Node* map = __ HeapConstant(maps[i]);
    1254       48990 :       Node* check = __ WordEqual(value_map, map);
    1255       48990 :       if (i == map_count - 1) {
    1256       46627 :         __ DeoptimizeUnless(DeoptimizeReason::kWrongMap, check, frame_state);
    1257             :       } else {
    1258        2363 :         __ GotoIf(check, &done);
    1259             :       }
    1260             :     }
    1261             :     __ Goto(&done);
    1262       46627 :     __ Bind(&done);
    1263             :   }
    1264       47324 :   return value;
    1265             : }
    1266             : 
    1267         451 : Node* EffectControlLinearizer::LowerCheckNumber(Node* node, Node* frame_state) {
    1268             :   Node* value = node->InputAt(0);
    1269             : 
    1270         451 :   auto if_not_smi = __ MakeDeferredLabel<1>();
    1271         451 :   auto done = __ MakeLabel<2>();
    1272             : 
    1273         451 :   Node* check0 = ObjectIsSmi(value);
    1274         451 :   __ GotoUnless(check0, &if_not_smi);
    1275             :   __ Goto(&done);
    1276             : 
    1277             :   __ Bind(&if_not_smi);
    1278         451 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1279         451 :   Node* check1 = __ WordEqual(value_map, __ HeapNumberMapConstant());
    1280         451 :   __ DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber, check1, frame_state);
    1281             :   __ Goto(&done);
    1282             : 
    1283         451 :   __ Bind(&done);
    1284         451 :   return value;
    1285             : }
    1286             : 
    1287         473 : Node* EffectControlLinearizer::LowerCheckReceiver(Node* node,
    1288             :                                                   Node* frame_state) {
    1289             :   Node* value = node->InputAt(0);
    1290             : 
    1291         473 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1292             :   Node* value_instance_type =
    1293         473 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1294             : 
    1295             :   STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
    1296             :   Node* check = __ Uint32LessThanOrEqual(
    1297         473 :       __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type);
    1298             :   __ DeoptimizeUnless(DeoptimizeReason::kNotAJavaScriptObject, check,
    1299         473 :                       frame_state);
    1300         473 :   return value;
    1301             : }
    1302             : 
    1303        1196 : Node* EffectControlLinearizer::LowerCheckString(Node* node, Node* frame_state) {
    1304             :   Node* value = node->InputAt(0);
    1305             : 
    1306        1196 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1307             :   Node* value_instance_type =
    1308        1196 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1309             : 
    1310             :   Node* check = __ Uint32LessThan(value_instance_type,
    1311        1196 :                                   __ Uint32Constant(FIRST_NONSTRING_TYPE));
    1312        1196 :   __ DeoptimizeUnless(DeoptimizeReason::kWrongInstanceType, check, frame_state);
    1313        1196 :   return value;
    1314             : }
    1315             : 
    1316        1757 : Node* EffectControlLinearizer::LowerCheckInternalizedString(Node* node,
    1317             :                                                             Node* frame_state) {
    1318             :   Node* value = node->InputAt(0);
    1319             : 
    1320        1757 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1321             :   Node* value_instance_type =
    1322        1757 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1323             : 
    1324             :   Node* check = __ Word32Equal(
    1325             :       __ Word32And(value_instance_type,
    1326             :                    __ Int32Constant(kIsNotStringMask | kIsNotInternalizedMask)),
    1327        1757 :       __ Int32Constant(kInternalizedTag));
    1328        1757 :   __ DeoptimizeUnless(DeoptimizeReason::kWrongInstanceType, check, frame_state);
    1329             : 
    1330        1757 :   return value;
    1331             : }
    1332             : 
    1333       29523 : Node* EffectControlLinearizer::LowerCheckIf(Node* node, Node* frame_state) {
    1334             :   Node* value = node->InputAt(0);
    1335             :   __ DeoptimizeUnless(DeoptimizeKind::kEager, DeoptimizeReason::kNoReason,
    1336       29523 :                       value, frame_state);
    1337       29523 :   return value;
    1338             : }
    1339             : 
    1340       42749 : Node* EffectControlLinearizer::LowerCheckedInt32Add(Node* node,
    1341             :                                                     Node* frame_state) {
    1342             :   Node* lhs = node->InputAt(0);
    1343             :   Node* rhs = node->InputAt(1);
    1344             : 
    1345       42749 :   Node* value = __ Int32AddWithOverflow(lhs, rhs);
    1346       42749 :   Node* check = __ Projection(1, value);
    1347       42748 :   __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state);
    1348       42746 :   return __ Projection(0, value);
    1349             : }
    1350             : 
    1351       18699 : Node* EffectControlLinearizer::LowerCheckedInt32Sub(Node* node,
    1352             :                                                     Node* frame_state) {
    1353             :   Node* lhs = node->InputAt(0);
    1354             :   Node* rhs = node->InputAt(1);
    1355             : 
    1356       18699 :   Node* value = __ Int32SubWithOverflow(lhs, rhs);
    1357       18699 :   Node* check = __ Projection(1, value);
    1358       18699 :   __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state);
    1359       18699 :   return __ Projection(0, value);
    1360             : }
    1361             : 
    1362         228 : Node* EffectControlLinearizer::LowerCheckedInt32Div(Node* node,
    1363             :                                                     Node* frame_state) {
    1364             :   Node* lhs = node->InputAt(0);
    1365             :   Node* rhs = node->InputAt(1);
    1366             : 
    1367         228 :   auto if_not_positive = __ MakeDeferredLabel<1>();
    1368         228 :   auto if_is_minint = __ MakeDeferredLabel<1>();
    1369         228 :   auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
    1370         228 :   auto minint_check_done = __ MakeLabel<2>();
    1371             : 
    1372         228 :   Node* zero = __ Int32Constant(0);
    1373             : 
    1374             :   // Check if {rhs} is positive (and not zero).
    1375         228 :   Node* check0 = __ Int32LessThan(zero, rhs);
    1376         228 :   __ GotoUnless(check0, &if_not_positive);
    1377             : 
    1378             :   // Fast case, no additional checking required.
    1379         228 :   __ Goto(&done, __ Int32Div(lhs, rhs));
    1380             : 
    1381             :   {
    1382             :     __ Bind(&if_not_positive);
    1383             : 
    1384             :     // Check if {rhs} is zero.
    1385         228 :     Node* check = __ Word32Equal(rhs, zero);
    1386         228 :     __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state);
    1387             : 
    1388             :     // Check if {lhs} is zero, as that would produce minus zero.
    1389         228 :     check = __ Word32Equal(lhs, zero);
    1390         228 :     __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check, frame_state);
    1391             : 
    1392             :     // Check if {lhs} is kMinInt and {rhs} is -1, in which case we'd have
    1393             :     // to return -kMinInt, which is not representable.
    1394         228 :     Node* minint = __ Int32Constant(std::numeric_limits<int32_t>::min());
    1395         228 :     Node* check1 = graph()->NewNode(machine()->Word32Equal(), lhs, minint);
    1396         228 :     __ GotoIf(check1, &if_is_minint);
    1397             :     __ Goto(&minint_check_done);
    1398             : 
    1399             :     __ Bind(&if_is_minint);
    1400             :     // Check if {rhs} is -1.
    1401         228 :     Node* minusone = __ Int32Constant(-1);
    1402         228 :     Node* is_minus_one = __ Word32Equal(rhs, minusone);
    1403         228 :     __ DeoptimizeIf(DeoptimizeReason::kOverflow, is_minus_one, frame_state);
    1404             :     __ Goto(&minint_check_done);
    1405             : 
    1406         228 :     __ Bind(&minint_check_done);
    1407             :     // Perform the actual integer division.
    1408         228 :     __ Goto(&done, __ Int32Div(lhs, rhs));
    1409             :   }
    1410             : 
    1411         228 :   __ Bind(&done);
    1412             :   Node* value = done.PhiAt(0);
    1413             : 
    1414             :   // Check if the remainder is non-zero.
    1415         228 :   Node* check = __ Word32Equal(lhs, __ Int32Mul(rhs, value));
    1416         228 :   __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, check, frame_state);
    1417             : 
    1418         228 :   return value;
    1419             : }
    1420             : 
    1421        1017 : Node* EffectControlLinearizer::LowerCheckedInt32Mod(Node* node,
    1422             :                                                     Node* frame_state) {
    1423             :   // General case for signed integer modulus, with optimization for (unknown)
    1424             :   // power of 2 right hand side.
    1425             :   //
    1426             :   //   if rhs <= 0 then
    1427             :   //     rhs = -rhs
    1428             :   //     deopt if rhs == 0
    1429             :   //   if lhs < 0 then
    1430             :   //     let res = lhs % rhs in
    1431             :   //     deopt if res == 0
    1432             :   //     res
    1433             :   //   else
    1434             :   //     let msk = rhs - 1 in
    1435             :   //     if rhs & msk == 0 then
    1436             :   //       lhs & msk
    1437             :   //     else
    1438             :   //       lhs % rhs
    1439             :   //
    1440             :   Node* lhs = node->InputAt(0);
    1441             :   Node* rhs = node->InputAt(1);
    1442             : 
    1443        1017 :   auto if_rhs_not_positive = __ MakeDeferredLabel<1>();
    1444        1017 :   auto if_lhs_negative = __ MakeDeferredLabel<1>();
    1445        1017 :   auto if_power_of_two = __ MakeLabel<1>();
    1446        1017 :   auto rhs_checked = __ MakeLabel<2>(MachineRepresentation::kWord32);
    1447        1017 :   auto done = __ MakeLabel<3>(MachineRepresentation::kWord32);
    1448             : 
    1449        1017 :   Node* zero = __ Int32Constant(0);
    1450             : 
    1451             :   // Check if {rhs} is not strictly positive.
    1452        1017 :   Node* check0 = __ Int32LessThanOrEqual(rhs, zero);
    1453        1017 :   __ GotoIf(check0, &if_rhs_not_positive);
    1454             :   __ Goto(&rhs_checked, rhs);
    1455             : 
    1456             :   __ Bind(&if_rhs_not_positive);
    1457             :   {
    1458             :     // Negate {rhs}, might still produce a negative result in case of
    1459             :     // -2^31, but that is handled safely below.
    1460        1017 :     Node* vtrue0 = __ Int32Sub(zero, rhs);
    1461             : 
    1462             :     // Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
    1463        1017 :     Node* check = __ Word32Equal(vtrue0, zero);
    1464        1017 :     __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state);
    1465             :     __ Goto(&rhs_checked, vtrue0);
    1466             :   }
    1467             : 
    1468        1017 :   __ Bind(&rhs_checked);
    1469             :   rhs = rhs_checked.PhiAt(0);
    1470             : 
    1471             :   // Check if {lhs} is negative.
    1472        1017 :   Node* check1 = __ Int32LessThan(lhs, zero);
    1473        1017 :   __ GotoIf(check1, &if_lhs_negative);
    1474             : 
    1475             :   // {lhs} non-negative.
    1476             :   {
    1477        1017 :     Node* one = __ Int32Constant(1);
    1478        1017 :     Node* msk = __ Int32Sub(rhs, one);
    1479             : 
    1480             :     // Check if {rhs} minus one is a valid mask.
    1481        1017 :     Node* check2 = __ Word32Equal(__ Word32And(rhs, msk), zero);
    1482        1017 :     __ GotoIf(check2, &if_power_of_two);
    1483             :     // Compute the remainder using the generic {lhs % rhs}.
    1484        1017 :     __ Goto(&done, __ Int32Mod(lhs, rhs));
    1485             : 
    1486             :     __ Bind(&if_power_of_two);
    1487             :     // Compute the remainder using {lhs & msk}.
    1488        1017 :     __ Goto(&done, __ Word32And(lhs, msk));
    1489             :   }
    1490             : 
    1491             :   __ Bind(&if_lhs_negative);
    1492             :   {
    1493             :     // Compute the remainder using {lhs % msk}.
    1494        1017 :     Node* vtrue1 = __ Int32Mod(lhs, rhs);
    1495             : 
    1496             :     // Check if we would have to return -0.
    1497        1017 :     Node* check = __ Word32Equal(vtrue1, zero);
    1498        1017 :     __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check, frame_state);
    1499             :     __ Goto(&done, vtrue1);
    1500             :   }
    1501             : 
    1502        1017 :   __ Bind(&done);
    1503        1017 :   return done.PhiAt(0);
    1504             : }
    1505             : 
    1506         100 : Node* EffectControlLinearizer::LowerCheckedUint32Div(Node* node,
    1507             :                                                      Node* frame_state) {
    1508             :   Node* lhs = node->InputAt(0);
    1509             :   Node* rhs = node->InputAt(1);
    1510             : 
    1511         100 :   Node* zero = __ Int32Constant(0);
    1512             : 
    1513             :   // Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
    1514         100 :   Node* check = __ Word32Equal(rhs, zero);
    1515         100 :   __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state);
    1516             : 
    1517             :   // Perform the actual unsigned integer division.
    1518         100 :   Node* value = __ Uint32Div(lhs, rhs);
    1519             : 
    1520             :   // Check if the remainder is non-zero.
    1521         100 :   check = __ Word32Equal(lhs, __ Int32Mul(rhs, value));
    1522         100 :   __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, check, frame_state);
    1523         100 :   return value;
    1524             : }
    1525             : 
    1526          69 : Node* EffectControlLinearizer::LowerCheckedUint32Mod(Node* node,
    1527             :                                                      Node* frame_state) {
    1528             :   Node* lhs = node->InputAt(0);
    1529             :   Node* rhs = node->InputAt(1);
    1530             : 
    1531          69 :   Node* zero = __ Int32Constant(0);
    1532             : 
    1533             :   // Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
    1534          69 :   Node* check = __ Word32Equal(rhs, zero);
    1535          69 :   __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state);
    1536             : 
    1537             :   // Perform the actual unsigned integer modulus.
    1538          69 :   return __ Uint32Mod(lhs, rhs);
    1539             : }
    1540             : 
    1541        6747 : Node* EffectControlLinearizer::LowerCheckedInt32Mul(Node* node,
    1542             :                                                     Node* frame_state) {
    1543        6747 :   CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
    1544             :   Node* lhs = node->InputAt(0);
    1545             :   Node* rhs = node->InputAt(1);
    1546             : 
    1547        6747 :   Node* projection = __ Int32MulWithOverflow(lhs, rhs);
    1548        6747 :   Node* check = __ Projection(1, projection);
    1549        6747 :   __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state);
    1550             : 
    1551        6747 :   Node* value = __ Projection(0, projection);
    1552             : 
    1553        6747 :   if (mode == CheckForMinusZeroMode::kCheckForMinusZero) {
    1554        4216 :     auto if_zero = __ MakeDeferredLabel<1>();
    1555        4216 :     auto check_done = __ MakeLabel<2>();
    1556        4216 :     Node* zero = __ Int32Constant(0);
    1557        4216 :     Node* check_zero = __ Word32Equal(value, zero);
    1558        4216 :     __ GotoIf(check_zero, &if_zero);
    1559             :     __ Goto(&check_done);
    1560             : 
    1561             :     __ Bind(&if_zero);
    1562             :     // We may need to return negative zero.
    1563        4216 :     Node* check_or = __ Int32LessThan(__ Word32Or(lhs, rhs), zero);
    1564        4216 :     __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check_or, frame_state);
    1565             :     __ Goto(&check_done);
    1566             : 
    1567        4216 :     __ Bind(&check_done);
    1568             :   }
    1569             : 
    1570        6747 :   return value;
    1571             : }
    1572             : 
    1573           0 : Node* EffectControlLinearizer::LowerCheckedInt32ToTaggedSigned(
    1574             :     Node* node, Node* frame_state) {
    1575             :   DCHECK(SmiValuesAre31Bits());
    1576             :   Node* value = node->InputAt(0);
    1577             : 
    1578           0 :   Node* add = __ Int32AddWithOverflow(value, value);
    1579           0 :   Node* check = __ Projection(1, add);
    1580           0 :   __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state);
    1581           0 :   return __ Projection(0, add);
    1582             : }
    1583             : 
    1584         219 : Node* EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node,
    1585             :                                                          Node* frame_state) {
    1586             :   Node* value = node->InputAt(0);
    1587         219 :   Node* unsafe = __ Int32LessThan(value, __ Int32Constant(0));
    1588         219 :   __ DeoptimizeIf(DeoptimizeReason::kLostPrecision, unsafe, frame_state);
    1589         219 :   return value;
    1590             : }
    1591             : 
    1592          24 : Node* EffectControlLinearizer::LowerCheckedUint32ToTaggedSigned(
    1593             :     Node* node, Node* frame_state) {
    1594             :   Node* value = node->InputAt(0);
    1595          24 :   Node* check = __ Uint32LessThanOrEqual(value, SmiMaxValueConstant());
    1596          24 :   __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, check, frame_state);
    1597          24 :   return ChangeUint32ToSmi(value);
    1598             : }
    1599             : 
    1600        8683 : Node* EffectControlLinearizer::BuildCheckedFloat64ToInt32(
    1601             :     CheckForMinusZeroMode mode, Node* value, Node* frame_state) {
    1602        8683 :   Node* value32 = __ RoundFloat64ToInt32(value);
    1603        8683 :   Node* check_same = __ Float64Equal(value, __ ChangeInt32ToFloat64(value32));
    1604             :   __ DeoptimizeUnless(DeoptimizeReason::kLostPrecisionOrNaN, check_same,
    1605        8683 :                       frame_state);
    1606             : 
    1607        8683 :   if (mode == CheckForMinusZeroMode::kCheckForMinusZero) {
    1608             :     // Check if {value} is -0.
    1609        2277 :     auto if_zero = __ MakeDeferredLabel<1>();
    1610        2277 :     auto check_done = __ MakeLabel<2>();
    1611             : 
    1612        2277 :     Node* check_zero = __ Word32Equal(value32, __ Int32Constant(0));
    1613        2277 :     __ GotoIf(check_zero, &if_zero);
    1614             :     __ Goto(&check_done);
    1615             : 
    1616             :     __ Bind(&if_zero);
    1617             :     // In case of 0, we need to check the high bits for the IEEE -0 pattern.
    1618             :     Node* check_negative = __ Int32LessThan(__ Float64ExtractHighWord32(value),
    1619        2277 :                                             __ Int32Constant(0));
    1620        2277 :     __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check_negative, frame_state);
    1621             :     __ Goto(&check_done);
    1622             : 
    1623        2277 :     __ Bind(&check_done);
    1624             :   }
    1625        8683 :   return value32;
    1626             : }
    1627             : 
    1628        6193 : Node* EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node,
    1629             :                                                           Node* frame_state) {
    1630        6193 :   CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
    1631             :   Node* value = node->InputAt(0);
    1632        6193 :   return BuildCheckedFloat64ToInt32(mode, value, frame_state);
    1633             : }
    1634             : 
    1635       27194 : Node* EffectControlLinearizer::LowerCheckedTaggedSignedToInt32(
    1636             :     Node* node, Node* frame_state) {
    1637             :   Node* value = node->InputAt(0);
    1638       27194 :   Node* check = ObjectIsSmi(value);
    1639       27194 :   __ DeoptimizeUnless(DeoptimizeReason::kNotASmi, check, frame_state);
    1640       27194 :   return ChangeSmiToInt32(value);
    1641             : }
    1642             : 
    1643        2490 : Node* EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node,
    1644             :                                                          Node* frame_state) {
    1645        2490 :   CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
    1646             :   Node* value = node->InputAt(0);
    1647             : 
    1648        2490 :   auto if_not_smi = __ MakeDeferredLabel<1>();
    1649        2490 :   auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
    1650             : 
    1651        2490 :   Node* check = ObjectIsSmi(value);
    1652        2490 :   __ GotoUnless(check, &if_not_smi);
    1653             :   // In the Smi case, just convert to int32.
    1654        2490 :   __ Goto(&done, ChangeSmiToInt32(value));
    1655             : 
    1656             :   // In the non-Smi case, check the heap numberness, load the number and convert
    1657             :   // to int32.
    1658             :   __ Bind(&if_not_smi);
    1659        2490 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1660        2490 :   Node* check_map = __ WordEqual(value_map, __ HeapNumberMapConstant());
    1661             :   __ DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber, check_map,
    1662        2490 :                       frame_state);
    1663        2490 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1664        2490 :   vfalse = BuildCheckedFloat64ToInt32(mode, vfalse, frame_state);
    1665             :   __ Goto(&done, vfalse);
    1666             : 
    1667        2490 :   __ Bind(&done);
    1668        2490 :   return done.PhiAt(0);
    1669             : }
    1670             : 
    1671       22842 : Node* EffectControlLinearizer::BuildCheckedHeapNumberOrOddballToFloat64(
    1672             :     CheckTaggedInputMode mode, Node* value, Node* frame_state) {
    1673       22842 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1674       22843 :   Node* check_number = __ WordEqual(value_map, __ HeapNumberMapConstant());
    1675       22843 :   switch (mode) {
    1676             :     case CheckTaggedInputMode::kNumber: {
    1677             :       __ DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber, check_number,
    1678        1473 :                           frame_state);
    1679        1473 :       break;
    1680             :     }
    1681             :     case CheckTaggedInputMode::kNumberOrOddball: {
    1682       21370 :       auto check_done = __ MakeLabel<2>();
    1683             : 
    1684       21370 :       __ GotoIf(check_number, &check_done);
    1685             :       // For oddballs also contain the numeric value, let us just check that
    1686             :       // we have an oddball here.
    1687             :       Node* instance_type =
    1688       21370 :           __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1689             :       Node* check_oddball =
    1690       21370 :           __ Word32Equal(instance_type, __ Int32Constant(ODDBALL_TYPE));
    1691             :       __ DeoptimizeUnless(DeoptimizeReason::kNotANumberOrOddball, check_oddball,
    1692       21369 :                           frame_state);
    1693             :       STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    1694             :       __ Goto(&check_done);
    1695             : 
    1696       21370 :       __ Bind(&check_done);
    1697             :       break;
    1698             :     }
    1699             :   }
    1700       22843 :   return __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1701             : }
    1702             : 
    1703       20767 : Node* EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node,
    1704             :                                                            Node* frame_state) {
    1705       20767 :   CheckTaggedInputMode mode = CheckTaggedInputModeOf(node->op());
    1706             :   Node* value = node->InputAt(0);
    1707             : 
    1708       20767 :   auto if_smi = __ MakeLabel<1>();
    1709       20767 :   auto done = __ MakeLabel<2>(MachineRepresentation::kFloat64);
    1710             : 
    1711       20767 :   Node* check = ObjectIsSmi(value);
    1712       20767 :   __ GotoIf(check, &if_smi);
    1713             : 
    1714             :   // In the Smi case, just convert to int32 and then float64.
    1715             :   // Otherwise, check heap numberness and load the number.
    1716             :   Node* number =
    1717       20767 :       BuildCheckedHeapNumberOrOddballToFloat64(mode, value, frame_state);
    1718             :   __ Goto(&done, number);
    1719             : 
    1720             :   __ Bind(&if_smi);
    1721       20767 :   Node* from_smi = ChangeSmiToInt32(value);
    1722       20767 :   from_smi = __ ChangeInt32ToFloat64(from_smi);
    1723             :   __ Goto(&done, from_smi);
    1724             : 
    1725       20767 :   __ Bind(&done);
    1726       20767 :   return done.PhiAt(0);
    1727             : }
    1728             : 
    1729       23022 : Node* EffectControlLinearizer::LowerCheckedTaggedToTaggedSigned(
    1730             :     Node* node, Node* frame_state) {
    1731             :   Node* value = node->InputAt(0);
    1732             : 
    1733       23022 :   Node* check = ObjectIsSmi(value);
    1734       23022 :   __ DeoptimizeUnless(DeoptimizeReason::kNotASmi, check, frame_state);
    1735             : 
    1736       23022 :   return value;
    1737             : }
    1738             : 
    1739       19690 : Node* EffectControlLinearizer::LowerCheckedTaggedToTaggedPointer(
    1740             :     Node* node, Node* frame_state) {
    1741             :   Node* value = node->InputAt(0);
    1742             : 
    1743       19690 :   Node* check = ObjectIsSmi(value);
    1744       19690 :   __ DeoptimizeIf(DeoptimizeReason::kSmi, check, frame_state);
    1745       19690 :   return value;
    1746             : }
    1747             : 
    1748        1155 : Node* EffectControlLinearizer::LowerTruncateTaggedToWord32(Node* node) {
    1749             :   Node* value = node->InputAt(0);
    1750             : 
    1751        1155 :   auto if_not_smi = __ MakeDeferredLabel<1>();
    1752        1155 :   auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
    1753             : 
    1754        1155 :   Node* check = ObjectIsSmi(value);
    1755        1155 :   __ GotoUnless(check, &if_not_smi);
    1756        1155 :   __ Goto(&done, ChangeSmiToInt32(value));
    1757             : 
    1758             :   __ Bind(&if_not_smi);
    1759             :   STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
    1760        1155 :   Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1761        1155 :   vfalse = __ TruncateFloat64ToWord32(vfalse);
    1762             :   __ Goto(&done, vfalse);
    1763             : 
    1764        1155 :   __ Bind(&done);
    1765        1155 :   return done.PhiAt(0);
    1766             : }
    1767             : 
    1768        2076 : Node* EffectControlLinearizer::LowerCheckedTruncateTaggedToWord32(
    1769             :     Node* node, Node* frame_state) {
    1770             :   Node* value = node->InputAt(0);
    1771             : 
    1772        2076 :   auto if_not_smi = __ MakeLabel<1>();
    1773        2076 :   auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
    1774             : 
    1775        2076 :   Node* check = ObjectIsSmi(value);
    1776        2076 :   __ GotoUnless(check, &if_not_smi);
    1777             :   // In the Smi case, just convert to int32.
    1778        2076 :   __ Goto(&done, ChangeSmiToInt32(value));
    1779             : 
    1780             :   // Otherwise, check that it's a heap number or oddball and truncate the value
    1781             :   // to int32.
    1782             :   __ Bind(&if_not_smi);
    1783             :   Node* number = BuildCheckedHeapNumberOrOddballToFloat64(
    1784        2076 :       CheckTaggedInputMode::kNumberOrOddball, value, frame_state);
    1785        2076 :   number = __ TruncateFloat64ToWord32(number);
    1786             :   __ Goto(&done, number);
    1787             : 
    1788        2076 :   __ Bind(&done);
    1789        2076 :   return done.PhiAt(0);
    1790             : }
    1791             : 
    1792       17020 : Node* EffectControlLinearizer::LowerObjectIsDetectableCallable(Node* node) {
    1793             :   Node* value = node->InputAt(0);
    1794             : 
    1795       17020 :   auto if_smi = __ MakeDeferredLabel<1>();
    1796       17020 :   auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
    1797             : 
    1798       17020 :   Node* check = ObjectIsSmi(value);
    1799       17020 :   __ GotoIf(check, &if_smi);
    1800             : 
    1801       17020 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1802             :   Node* value_bit_field =
    1803       17020 :       __ LoadField(AccessBuilder::ForMapBitField(), value_map);
    1804             :   Node* vfalse = __ Word32Equal(
    1805             :       __ Int32Constant(1 << Map::kIsCallable),
    1806             :       __ Word32And(value_bit_field,
    1807             :                    __ Int32Constant((1 << Map::kIsCallable) |
    1808       17020 :                                     (1 << Map::kIsUndetectable))));
    1809             :   __ Goto(&done, vfalse);
    1810             : 
    1811             :   __ Bind(&if_smi);
    1812       17020 :   __ Goto(&done, __ Int32Constant(0));
    1813             : 
    1814       17020 :   __ Bind(&done);
    1815       17020 :   return done.PhiAt(0);
    1816             : }
    1817             : 
    1818        2976 : Node* EffectControlLinearizer::LowerObjectIsNaN(Node* node) {
    1819             :   Node* value = node->InputAt(0);
    1820        2976 :   Node* zero = __ Int32Constant(0);
    1821             : 
    1822        2976 :   auto done = __ MakeLabel<3>(MachineRepresentation::kBit);
    1823             : 
    1824             :   // Check if {value} is a Smi.
    1825        2976 :   __ GotoIf(ObjectIsSmi(value), &done, zero);
    1826             : 
    1827             :   // Check if {value} is a HeapNumber.
    1828        2976 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1829             :   __ GotoUnless(__ WordEqual(value_map, __ HeapNumberMapConstant()), &done,
    1830        2976 :                 zero);
    1831             : 
    1832             :   // Check if {value} contains a NaN.
    1833        2976 :   Node* value_value = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
    1834             :   __ Goto(&done,
    1835        2976 :           __ Word32Equal(__ Float64Equal(value_value, value_value), zero));
    1836             : 
    1837        2976 :   __ Bind(&done);
    1838        2976 :   return done.PhiAt(0);
    1839             : }
    1840             : 
    1841        8189 : Node* EffectControlLinearizer::LowerObjectIsNonCallable(Node* node) {
    1842             :   Node* value = node->InputAt(0);
    1843             : 
    1844        8189 :   auto if_primitive = __ MakeDeferredLabel<2>();
    1845        8189 :   auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
    1846             : 
    1847        8189 :   Node* check0 = ObjectIsSmi(value);
    1848        8189 :   __ GotoIf(check0, &if_primitive);
    1849             : 
    1850        8189 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1851             :   Node* value_instance_type =
    1852        8189 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1853             :   STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
    1854             :   Node* check1 = __ Uint32LessThanOrEqual(
    1855        8189 :       __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type);
    1856        8189 :   __ GotoUnless(check1, &if_primitive);
    1857             : 
    1858             :   Node* value_bit_field =
    1859        8189 :       __ LoadField(AccessBuilder::ForMapBitField(), value_map);
    1860             :   Node* check2 = __ Word32Equal(
    1861             :       __ Int32Constant(0),
    1862        8189 :       __ Word32And(value_bit_field, __ Int32Constant(1 << Map::kIsCallable)));
    1863             :   __ Goto(&done, check2);
    1864             : 
    1865        8189 :   __ Bind(&if_primitive);
    1866        8189 :   __ Goto(&done, __ Int32Constant(0));
    1867             : 
    1868        8189 :   __ Bind(&done);
    1869        8189 :   return done.PhiAt(0);
    1870             : }
    1871             : 
    1872       11024 : Node* EffectControlLinearizer::LowerObjectIsNumber(Node* node) {
    1873             :   Node* value = node->InputAt(0);
    1874             : 
    1875       11024 :   auto if_smi = __ MakeLabel<1>();
    1876       11024 :   auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
    1877             : 
    1878       11024 :   __ GotoIf(ObjectIsSmi(value), &if_smi);
    1879       11024 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1880       11024 :   __ Goto(&done, __ WordEqual(value_map, __ HeapNumberMapConstant()));
    1881             : 
    1882             :   __ Bind(&if_smi);
    1883       11024 :   __ Goto(&done, __ Int32Constant(1));
    1884             : 
    1885       11024 :   __ Bind(&done);
    1886       11024 :   return done.PhiAt(0);
    1887             : }
    1888             : 
    1889       21909 : Node* EffectControlLinearizer::LowerObjectIsReceiver(Node* node) {
    1890             :   Node* value = node->InputAt(0);
    1891             : 
    1892       21909 :   auto if_smi = __ MakeDeferredLabel<1>();
    1893       21909 :   auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
    1894             : 
    1895       21909 :   __ GotoIf(ObjectIsSmi(value), &if_smi);
    1896             : 
    1897             :   STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
    1898       21909 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1899             :   Node* value_instance_type =
    1900       21909 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1901             :   Node* result = __ Uint32LessThanOrEqual(
    1902       21909 :       __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type);
    1903             :   __ Goto(&done, result);
    1904             : 
    1905             :   __ Bind(&if_smi);
    1906       21909 :   __ Goto(&done, __ Int32Constant(0));
    1907             : 
    1908       21909 :   __ Bind(&done);
    1909       21909 :   return done.PhiAt(0);
    1910             : }
    1911             : 
    1912        8556 : Node* EffectControlLinearizer::LowerObjectIsSmi(Node* node) {
    1913             :   Node* value = node->InputAt(0);
    1914        8556 :   return ObjectIsSmi(value);
    1915             : }
    1916             : 
    1917        4846 : Node* EffectControlLinearizer::LowerObjectIsString(Node* node) {
    1918             :   Node* value = node->InputAt(0);
    1919             : 
    1920        4846 :   auto if_smi = __ MakeDeferredLabel<1>();
    1921        4846 :   auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
    1922             : 
    1923        4846 :   Node* check = ObjectIsSmi(value);
    1924        4846 :   __ GotoIf(check, &if_smi);
    1925        4846 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1926             :   Node* value_instance_type =
    1927        4846 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1928             :   Node* vfalse = __ Uint32LessThan(value_instance_type,
    1929        4846 :                                    __ Uint32Constant(FIRST_NONSTRING_TYPE));
    1930             :   __ Goto(&done, vfalse);
    1931             : 
    1932             :   __ Bind(&if_smi);
    1933        4846 :   __ Goto(&done, __ Int32Constant(0));
    1934             : 
    1935        4846 :   __ Bind(&done);
    1936        4846 :   return done.PhiAt(0);
    1937             : }
    1938             : 
    1939         665 : Node* EffectControlLinearizer::LowerObjectIsSymbol(Node* node) {
    1940             :   Node* value = node->InputAt(0);
    1941             : 
    1942         665 :   auto if_smi = __ MakeDeferredLabel<1>();
    1943         665 :   auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
    1944             : 
    1945         665 :   Node* check = ObjectIsSmi(value);
    1946         665 :   __ GotoIf(check, &if_smi);
    1947         665 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1948             :   Node* value_instance_type =
    1949         665 :       __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
    1950             :   Node* vfalse =
    1951         665 :       __ Word32Equal(value_instance_type, __ Uint32Constant(SYMBOL_TYPE));
    1952             :   __ Goto(&done, vfalse);
    1953             : 
    1954             :   __ Bind(&if_smi);
    1955         665 :   __ Goto(&done, __ Int32Constant(0));
    1956             : 
    1957         665 :   __ Bind(&done);
    1958         665 :   return done.PhiAt(0);
    1959             : }
    1960             : 
    1961        8923 : Node* EffectControlLinearizer::LowerObjectIsUndetectable(Node* node) {
    1962             :   Node* value = node->InputAt(0);
    1963             : 
    1964        8923 :   auto if_smi = __ MakeDeferredLabel<1>();
    1965        8923 :   auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
    1966             : 
    1967        8923 :   Node* check = ObjectIsSmi(value);
    1968        8923 :   __ GotoIf(check, &if_smi);
    1969             : 
    1970        8923 :   Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
    1971             :   Node* value_bit_field =
    1972        8923 :       __ LoadField(AccessBuilder::ForMapBitField(), value_map);
    1973             :   Node* vfalse = __ Word32Equal(
    1974             :       __ Word32Equal(__ Int32Constant(0),
    1975             :                      __ Word32And(value_bit_field,
    1976             :                                   __ Int32Constant(1 << Map::kIsUndetectable))),
    1977        8923 :       __ Int32Constant(0));
    1978             :   __ Goto(&done, vfalse);
    1979             : 
    1980             :   __ Bind(&if_smi);
    1981        8923 :   __ Goto(&done, __ Int32Constant(0));
    1982             : 
    1983        8923 :   __ Bind(&done);
    1984        8923 :   return done.PhiAt(0);
    1985             : }
    1986             : 
    1987       11994 : Node* EffectControlLinearizer::LowerArgumentsLength(Node* node) {
    1988        3998 :   Node* arguments_frame = NodeProperties::GetValueInput(node, 0);
    1989        3998 :   int formal_parameter_count = FormalParameterCountOf(node->op());
    1990        3998 :   bool is_rest_length = IsRestLengthOf(node->op());
    1991             :   DCHECK(formal_parameter_count >= 0);
    1992             : 
    1993        3998 :   if (is_rest_length) {
    1994             :     // The ArgumentsLength node is computing the number of rest parameters,
    1995             :     // which is max(0, actual_parameter_count - formal_parameter_count).
    1996             :     // We have to distinguish the case, when there is an arguments adaptor frame
    1997             :     // (i.e., arguments_frame != LoadFramePointer()).
    1998         551 :     auto if_adaptor_frame = __ MakeLabel<1>();
    1999         551 :     auto done = __ MakeLabel<3>(MachineRepresentation::kTaggedSigned);
    2000             : 
    2001         551 :     Node* frame = __ LoadFramePointer();
    2002         551 :     __ GotoIf(__ WordEqual(arguments_frame, frame), &done, __ SmiConstant(0));
    2003             :     __ Goto(&if_adaptor_frame);
    2004             : 
    2005             :     __ Bind(&if_adaptor_frame);
    2006             :     Node* arguments_length = __ Load(
    2007             :         MachineType::TaggedSigned(), arguments_frame,
    2008         551 :         __ IntPtrConstant(ArgumentsAdaptorFrameConstants::kLengthOffset));
    2009             : 
    2010             :     Node* rest_length =
    2011         551 :         __ IntSub(arguments_length, __ SmiConstant(formal_parameter_count));
    2012             :     __ GotoIf(__ IntLessThan(rest_length, __ SmiConstant(0)), &done,
    2013         551 :               __ SmiConstant(0));
    2014             :     __ Goto(&done, rest_length);
    2015             : 
    2016         551 :     __ Bind(&done);
    2017             :     return done.PhiAt(0);
    2018             :   } else {
    2019             :     // The ArgumentsLength node is computing the actual number of arguments.
    2020             :     // We have to distinguish the case when there is an arguments adaptor frame
    2021             :     // (i.e., arguments_frame != LoadFramePointer()).
    2022        3447 :     auto if_adaptor_frame = __ MakeLabel<1>();
    2023        3447 :     auto done = __ MakeLabel<2>(MachineRepresentation::kTaggedSigned);
    2024             : 
    2025        3447 :     Node* frame = __ LoadFramePointer();
    2026             :     __ GotoIf(__ WordEqual(arguments_frame, frame), &done,
    2027        3447 :               __ SmiConstant(formal_parameter_count));
    2028             :     __ Goto(&if_adaptor_frame);
    2029             : 
    2030             :     __ Bind(&if_adaptor_frame);
    2031             :     Node* arguments_length = __ Load(
    2032             :         MachineType::TaggedSigned(), arguments_frame,
    2033        3447 :         __ IntPtrConstant(ArgumentsAdaptorFrameConstants::kLengthOffset));
    2034             :     __ Goto(&done, arguments_length);
    2035             : 
    2036        3447 :     __ Bind(&done);
    2037             :     return done.PhiAt(0);
    2038             :   }
    2039             : }
    2040             : 
    2041        3951 : Node* EffectControlLinearizer::LowerArgumentsFrame(Node* node) {
    2042        3951 :   auto done = __ MakeLabel<2>(MachineType::PointerRepresentation());
    2043             : 
    2044        3951 :   Node* frame = __ LoadFramePointer();
    2045             :   Node* parent_frame =
    2046             :       __ Load(MachineType::AnyTagged(), frame,
    2047        3951 :               __ IntPtrConstant(StandardFrameConstants::kCallerFPOffset));
    2048             :   Node* parent_frame_type = __ Load(
    2049             :       MachineType::AnyTagged(), parent_frame,
    2050        3951 :       __ IntPtrConstant(CommonFrameConstants::kContextOrFrameTypeOffset));
    2051             :   __ GotoIf(__ WordEqual(parent_frame_type,
    2052             :                          __ IntPtrConstant(StackFrame::TypeToMarker(
    2053             :                              StackFrame::ARGUMENTS_ADAPTOR))),
    2054        3951 :             &done, parent_frame);
    2055             :   __ Goto(&done, frame);
    2056             : 
    2057        3951 :   __ Bind(&done);
    2058        3951 :   return done.PhiAt(0);
    2059             : }
    2060             : 
    2061        7596 : Node* EffectControlLinearizer::LowerNewUnmappedArgumentsElements(Node* node) {
    2062        3798 :   Node* frame = NodeProperties::GetValueInput(node, 0);
    2063        3798 :   Node* length = NodeProperties::GetValueInput(node, 1);
    2064             : 
    2065             :   Callable const callable =
    2066        3798 :       CodeFactory::NewUnmappedArgumentsElements(isolate());
    2067        3798 :   Operator::Properties const properties = node->op()->properties();
    2068             :   CallDescriptor::Flags const flags = CallDescriptor::kNoFlags;
    2069             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    2070       11394 :       isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
    2071             :   return __ Call(desc, __ HeapConstant(callable.code()), frame, length,
    2072        7596 :                  __ NoContextConstant());
    2073             : }
    2074             : 
    2075         325 : Node* EffectControlLinearizer::LowerArrayBufferWasNeutered(Node* node) {
    2076             :   Node* value = node->InputAt(0);
    2077             : 
    2078             :   Node* value_bit_field =
    2079         325 :       __ LoadField(AccessBuilder::ForJSArrayBufferBitField(), value);
    2080             :   return __ Word32Equal(
    2081             :       __ Word32Equal(
    2082             :           __ Word32And(value_bit_field,
    2083             :                        __ Int32Constant(JSArrayBuffer::WasNeutered::kMask)),
    2084             :           __ Int32Constant(0)),
    2085         325 :       __ Int32Constant(0));
    2086             : }
    2087             : 
    2088         287 : Node* EffectControlLinearizer::LowerStringCharAt(Node* node) {
    2089             :   Node* receiver = node->InputAt(0);
    2090             :   Node* position = node->InputAt(1);
    2091             : 
    2092         287 :   Callable const callable = CodeFactory::StringCharAt(isolate());
    2093         287 :   Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite;
    2094             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    2095             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    2096         861 :       isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
    2097             :   return __ Call(desc, __ HeapConstant(callable.code()), receiver, position,
    2098         574 :                  __ NoContextConstant());
    2099             : }
    2100             : 
    2101         379 : Node* EffectControlLinearizer::LowerStringCharCodeAt(Node* node) {
    2102             :   Node* receiver = node->InputAt(0);
    2103             :   Node* position = node->InputAt(1);
    2104             : 
    2105         379 :   Callable const callable = CodeFactory::StringCharCodeAt(isolate());
    2106         379 :   Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite;
    2107             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    2108             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    2109             :       isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties,
    2110        1137 :       MachineType::TaggedSigned());
    2111             :   return __ Call(desc, __ HeapConstant(callable.code()), receiver, position,
    2112         758 :                  __ NoContextConstant());
    2113             : }
    2114             : 
    2115         752 : Node* EffectControlLinearizer::LowerStringFromCharCode(Node* node) {
    2116             :   Node* value = node->InputAt(0);
    2117             : 
    2118         752 :   auto runtime_call = __ MakeDeferredLabel<2>();
    2119             :   auto if_undefined = __ MakeDeferredLabel<1>();
    2120         752 :   auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
    2121             : 
    2122             :   // Compute the character code.
    2123         752 :   Node* code = __ Word32And(value, __ Int32Constant(String::kMaxUtf16CodeUnit));
    2124             : 
    2125             :   // Check if the {code} is a one-byte char code.
    2126             :   Node* check0 = __ Int32LessThanOrEqual(
    2127         752 :       code, __ Int32Constant(String::kMaxOneByteCharCode));
    2128         752 :   __ GotoUnless(check0, &runtime_call);
    2129             : 
    2130             :   // Load the isolate wide single character string cache.
    2131         752 :   Node* cache = __ HeapConstant(factory()->single_character_string_cache());
    2132             : 
    2133             :   // Compute the {cache} index for {code}.
    2134         752 :   Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code);
    2135             : 
    2136             :   // Check if we have an entry for the {code} in the single character string
    2137             :   // cache already.
    2138             :   Node* entry =
    2139         752 :       __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index);
    2140             : 
    2141         752 :   Node* check1 = __ WordEqual(entry, __ UndefinedConstant());
    2142         752 :   __ GotoIf(check1, &runtime_call);
    2143             :   __ Goto(&done, entry);
    2144             : 
    2145             :   // Let %StringFromCharCode handle this case.
    2146             :   // TODO(turbofan): At some point we may consider adding a stub for this
    2147             :   // deferred case, so that we don't need to call to C++ here.
    2148         752 :   __ Bind(&runtime_call);
    2149             :   {
    2150         752 :     Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
    2151             :     Runtime::FunctionId id = Runtime::kStringCharFromCode;
    2152             :     CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
    2153         752 :         graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags);
    2154             :     Node* vtrue1 =
    2155             :         __ Call(desc, __ CEntryStubConstant(1), ChangeInt32ToSmi(code),
    2156             :                 __ ExternalConstant(ExternalReference(id, isolate())),
    2157        1504 :                 __ Int32Constant(1), __ NoContextConstant());
    2158             :     __ Goto(&done, vtrue1);
    2159             :   }
    2160         752 :   __ Bind(&done);
    2161         752 :   return done.PhiAt(0);
    2162             : }
    2163             : 
    2164         114 : Node* EffectControlLinearizer::LowerStringFromCodePoint(Node* node) {
    2165             :   Node* value = node->InputAt(0);
    2166             :   Node* code = value;
    2167             : 
    2168          57 :   auto if_not_single_code = __ MakeDeferredLabel<1>();
    2169          57 :   auto if_not_one_byte = __ MakeDeferredLabel<1>();
    2170          57 :   auto cache_miss = __ MakeDeferredLabel<1>();
    2171          57 :   auto done = __ MakeLabel<4>(MachineRepresentation::kTagged);
    2172             : 
    2173             :   // Check if the {code} is a single code unit
    2174          57 :   Node* check0 = __ Uint32LessThanOrEqual(code, __ Uint32Constant(0xFFFF));
    2175          57 :   __ GotoUnless(check0, &if_not_single_code);
    2176             : 
    2177             :   {
    2178             :     // Check if the {code} is a one byte character
    2179             :     Node* check1 = __ Uint32LessThanOrEqual(
    2180          57 :         code, __ Uint32Constant(String::kMaxOneByteCharCode));
    2181          57 :     __ GotoUnless(check1, &if_not_one_byte);
    2182             :     {
    2183             :       // Load the isolate wide single character string cache.
    2184          57 :       Node* cache = __ HeapConstant(factory()->single_character_string_cache());
    2185             : 
    2186             :       // Compute the {cache} index for {code}.
    2187          57 :       Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code);
    2188             : 
    2189             :       // Check if we have an entry for the {code} in the single character string
    2190             :       // cache already.
    2191             :       Node* entry =
    2192          57 :           __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index);
    2193             : 
    2194          57 :       Node* check2 = __ WordEqual(entry, __ UndefinedConstant());
    2195          57 :       __ GotoIf(check2, &cache_miss);
    2196             : 
    2197             :       // Use the {entry} from the {cache}.
    2198             :       __ Goto(&done, entry);
    2199             : 
    2200             :       __ Bind(&cache_miss);
    2201             :       {
    2202             :         // Allocate a new SeqOneByteString for {code}.
    2203             :         Node* vtrue2 = __ Allocate(
    2204          57 :             NOT_TENURED, __ Int32Constant(SeqOneByteString::SizeFor(1)));
    2205             :         __ StoreField(AccessBuilder::ForMap(), vtrue2,
    2206          57 :                       __ HeapConstant(factory()->one_byte_string_map()));
    2207             :         __ StoreField(AccessBuilder::ForNameHashField(), vtrue2,
    2208          57 :                       __ IntPtrConstant(Name::kEmptyHashField));
    2209             :         __ StoreField(AccessBuilder::ForStringLength(), vtrue2,
    2210          57 :                       __ SmiConstant(1));
    2211             :         __ Store(
    2212             :             StoreRepresentation(MachineRepresentation::kWord8, kNoWriteBarrier),
    2213             :             vtrue2,
    2214             :             __ IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag),
    2215         114 :             code);
    2216             : 
    2217             :         // Remember it in the {cache}.
    2218             :         __ StoreElement(AccessBuilder::ForFixedArrayElement(), cache, index,
    2219          57 :                         vtrue2);
    2220             :         __ Goto(&done, vtrue2);
    2221             :       }
    2222             :     }
    2223             : 
    2224             :     __ Bind(&if_not_one_byte);
    2225             :     {
    2226             :       // Allocate a new SeqTwoByteString for {code}.
    2227             :       Node* vfalse1 = __ Allocate(
    2228          57 :           NOT_TENURED, __ Int32Constant(SeqTwoByteString::SizeFor(1)));
    2229             :       __ StoreField(AccessBuilder::ForMap(), vfalse1,
    2230          57 :                     __ HeapConstant(factory()->string_map()));
    2231             :       __ StoreField(AccessBuilder::ForNameHashField(), vfalse1,
    2232          57 :                     __ IntPtrConstant(Name::kEmptyHashField));
    2233             :       __ StoreField(AccessBuilder::ForStringLength(), vfalse1,
    2234          57 :                     __ SmiConstant(1));
    2235             :       __ Store(
    2236             :           StoreRepresentation(MachineRepresentation::kWord16, kNoWriteBarrier),
    2237             :           vfalse1,
    2238             :           __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag),
    2239         114 :           code);
    2240             :       __ Goto(&done, vfalse1);
    2241             :     }
    2242             :   }
    2243             : 
    2244             :   __ Bind(&if_not_single_code);
    2245             :   // Generate surrogate pair string
    2246             :   {
    2247          57 :     switch (UnicodeEncodingOf(node->op())) {
    2248             :       case UnicodeEncoding::UTF16:
    2249             :         break;
    2250             : 
    2251             :       case UnicodeEncoding::UTF32: {
    2252             :         // Convert UTF32 to UTF16 code units, and store as a 32 bit word.
    2253           0 :         Node* lead_offset = __ Int32Constant(0xD800 - (0x10000 >> 10));
    2254             : 
    2255             :         // lead = (codepoint >> 10) + LEAD_OFFSET
    2256             :         Node* lead =
    2257           0 :             __ Int32Add(__ Word32Shr(code, __ Int32Constant(10)), lead_offset);
    2258             : 
    2259             :         // trail = (codepoint & 0x3FF) + 0xDC00;
    2260             :         Node* trail = __ Int32Add(__ Word32And(code, __ Int32Constant(0x3FF)),
    2261           0 :                                   __ Int32Constant(0xDC00));
    2262             : 
    2263             :         // codpoint = (trail << 16) | lead;
    2264           0 :         code = __ Word32Or(__ Word32Shl(trail, __ Int32Constant(16)), lead);
    2265           0 :         break;
    2266             :       }
    2267             :     }
    2268             : 
    2269             :     // Allocate a new SeqTwoByteString for {code}.
    2270             :     Node* vfalse0 = __ Allocate(NOT_TENURED,
    2271          57 :                                 __ Int32Constant(SeqTwoByteString::SizeFor(2)));
    2272             :     __ StoreField(AccessBuilder::ForMap(), vfalse0,
    2273          57 :                   __ HeapConstant(factory()->string_map()));
    2274             :     __ StoreField(AccessBuilder::ForNameHashField(), vfalse0,
    2275          57 :                   __ IntPtrConstant(Name::kEmptyHashField));
    2276          57 :     __ StoreField(AccessBuilder::ForStringLength(), vfalse0, __ SmiConstant(2));
    2277             :     __ Store(
    2278             :         StoreRepresentation(MachineRepresentation::kWord32, kNoWriteBarrier),
    2279             :         vfalse0,
    2280             :         __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag),
    2281         114 :         code);
    2282             :     __ Goto(&done, vfalse0);
    2283             :   }
    2284             : 
    2285          57 :   __ Bind(&done);
    2286          57 :   return done.PhiAt(0);
    2287             : }
    2288             : 
    2289         168 : Node* EffectControlLinearizer::LowerStringIndexOf(Node* node) {
    2290             :   Node* subject = node->InputAt(0);
    2291             :   Node* search_string = node->InputAt(1);
    2292             :   Node* position = node->InputAt(2);
    2293             : 
    2294         168 :   Callable callable = CodeFactory::StringIndexOf(isolate());
    2295             :   Operator::Properties properties = Operator::kEliminatable;
    2296             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    2297             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    2298         504 :       isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
    2299             :   return __ Call(desc, __ HeapConstant(callable.code()), subject, search_string,
    2300         336 :                  position, __ NoContextConstant());
    2301             : }
    2302             : 
    2303        2689 : Node* EffectControlLinearizer::LowerStringComparison(Callable const& callable,
    2304             :                                                      Node* node) {
    2305             :   Node* lhs = node->InputAt(0);
    2306             :   Node* rhs = node->InputAt(1);
    2307             : 
    2308             :   Operator::Properties properties = Operator::kEliminatable;
    2309             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    2310             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    2311        8067 :       isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
    2312             :   return __ Call(desc, __ HeapConstant(callable.code()), lhs, rhs,
    2313        5378 :                  __ NoContextConstant());
    2314             : }
    2315             : 
    2316        2205 : Node* EffectControlLinearizer::LowerStringEqual(Node* node) {
    2317        2205 :   return LowerStringComparison(CodeFactory::StringEqual(isolate()), node);
    2318             : }
    2319             : 
    2320         379 : Node* EffectControlLinearizer::LowerStringLessThan(Node* node) {
    2321         379 :   return LowerStringComparison(CodeFactory::StringLessThan(isolate()), node);
    2322             : }
    2323             : 
    2324         105 : Node* EffectControlLinearizer::LowerStringLessThanOrEqual(Node* node) {
    2325             :   return LowerStringComparison(CodeFactory::StringLessThanOrEqual(isolate()),
    2326         105 :                                node);
    2327             : }
    2328             : 
    2329         651 : Node* EffectControlLinearizer::LowerCheckFloat64Hole(Node* node,
    2330             :                                                      Node* frame_state) {
    2331             :   // If we reach this point w/o eliminating the {node} that's marked
    2332             :   // with allow-return-hole, we cannot do anything, so just deoptimize
    2333             :   // in case of the hole NaN (similar to Crankshaft).
    2334             :   Node* value = node->InputAt(0);
    2335             :   Node* check = __ Word32Equal(__ Float64ExtractHighWord32(value),
    2336         651 :                                __ Int32Constant(kHoleNanUpper32));
    2337         651 :   __ DeoptimizeIf(DeoptimizeReason::kHole, check, frame_state);
    2338         651 :   return value;
    2339             : }
    2340             : 
    2341         917 : Node* EffectControlLinearizer::LowerCheckTaggedHole(Node* node,
    2342             :                                                     Node* frame_state) {
    2343             :   Node* value = node->InputAt(0);
    2344         917 :   Node* check = __ WordEqual(value, __ TheHoleConstant());
    2345         917 :   __ DeoptimizeIf(DeoptimizeReason::kHole, check, frame_state);
    2346         917 :   return value;
    2347             : }
    2348             : 
    2349        1529 : Node* EffectControlLinearizer::LowerConvertTaggedHoleToUndefined(Node* node) {
    2350             :   Node* value = node->InputAt(0);
    2351             : 
    2352        1529 :   auto if_is_hole = __ MakeDeferredLabel<1>();
    2353        1529 :   auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
    2354             : 
    2355        1529 :   Node* check = __ WordEqual(value, __ TheHoleConstant());
    2356        1529 :   __ GotoIf(check, &if_is_hole);
    2357             :   __ Goto(&done, value);
    2358             : 
    2359             :   __ Bind(&if_is_hole);
    2360        1529 :   __ Goto(&done, __ UndefinedConstant());
    2361             : 
    2362        1529 :   __ Bind(&done);
    2363        1529 :   return done.PhiAt(0);
    2364             : }
    2365             : 
    2366       47288 : Node* EffectControlLinearizer::AllocateHeapNumberWithValue(Node* value) {
    2367       47288 :   Node* result = __ Allocate(NOT_TENURED, __ Int32Constant(HeapNumber::kSize));
    2368       47289 :   __ StoreField(AccessBuilder::ForMap(), result, __ HeapNumberMapConstant());
    2369       47289 :   __ StoreField(AccessBuilder::ForHeapNumberValue(), result, value);
    2370       47289 :   return result;
    2371             : }
    2372             : 
    2373      102269 : Node* EffectControlLinearizer::ChangeInt32ToSmi(Node* value) {
    2374      102269 :   if (machine()->Is64()) {
    2375      102269 :     value = __ ChangeInt32ToInt64(value);
    2376             :   }
    2377      102270 :   return __ WordShl(value, SmiShiftBitsConstant());
    2378             : }
    2379             : 
    2380         708 : Node* EffectControlLinearizer::ChangeUint32ToSmi(Node* value) {
    2381         708 :   if (machine()->Is64()) {
    2382         708 :     value = __ ChangeUint32ToUint64(value);
    2383             :   }
    2384         708 :   return __ WordShl(value, SmiShiftBitsConstant());
    2385             : }
    2386             : 
    2387      170228 : Node* EffectControlLinearizer::ChangeSmiToInt32(Node* value) {
    2388      170229 :   value = __ WordSar(value, SmiShiftBitsConstant());
    2389      170229 :   if (machine()->Is64()) {
    2390      170229 :     value = __ TruncateInt64ToInt32(value);
    2391             :   }
    2392      170228 :   return value;
    2393             : }
    2394             : 
    2395      317335 : Node* EffectControlLinearizer::ObjectIsSmi(Node* value) {
    2396             :   return __ WordEqual(__ WordAnd(value, __ IntPtrConstant(kSmiTagMask)),
    2397      317335 :                       __ IntPtrConstant(kSmiTag));
    2398             : }
    2399             : 
    2400           0 : Node* EffectControlLinearizer::SmiMaxValueConstant() {
    2401         708 :   return __ Int32Constant(Smi::kMaxValue);
    2402             : }
    2403             : 
    2404           0 : Node* EffectControlLinearizer::SmiShiftBitsConstant() {
    2405      273206 :   return __ IntPtrConstant(kSmiShiftSize + kSmiTagSize);
    2406             : }
    2407             : 
    2408          16 : Node* EffectControlLinearizer::LowerPlainPrimitiveToNumber(Node* node) {
    2409             :   Node* value = node->InputAt(0);
    2410          16 :   return __ ToNumber(value);
    2411             : }
    2412             : 
    2413        6372 : Node* EffectControlLinearizer::LowerPlainPrimitiveToWord32(Node* node) {
    2414             :   Node* value = node->InputAt(0);
    2415             : 
    2416        6372 :   auto if_not_smi = __ MakeDeferredLabel<1>();
    2417        6372 :   auto if_to_number_smi = __ MakeLabel<1>();
    2418        6372 :   auto done = __ MakeLabel<3>(MachineRepresentation::kWord32);
    2419             : 
    2420        6372 :   Node* check0 = ObjectIsSmi(value);
    2421        6372 :   __ GotoUnless(check0, &if_not_smi);
    2422        6372 :   __ Goto(&done, ChangeSmiToInt32(value));
    2423             : 
    2424             :   __ Bind(&if_not_smi);
    2425        6371 :   Node* to_number = __ ToNumber(value);
    2426             : 
    2427        6372 :   Node* check1 = ObjectIsSmi(to_number);
    2428        6372 :   __ GotoIf(check1, &if_to_number_smi);
    2429        6372 :   Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), to_number);
    2430        6372 :   __ Goto(&done, __ TruncateFloat64ToWord32(number));
    2431             : 
    2432             :   __ Bind(&if_to_number_smi);
    2433        6372 :   __ Goto(&done, ChangeSmiToInt32(to_number));
    2434             : 
    2435        6372 :   __ Bind(&done);
    2436        6370 :   return done.PhiAt(0);
    2437             : }
    2438             : 
    2439        1891 : Node* EffectControlLinearizer::LowerPlainPrimitiveToFloat64(Node* node) {
    2440             :   Node* value = node->InputAt(0);
    2441             : 
    2442        1891 :   auto if_not_smi = __ MakeDeferredLabel<1>();
    2443        1891 :   auto if_to_number_smi = __ MakeLabel<1>();
    2444        1891 :   auto done = __ MakeLabel<3>(MachineRepresentation::kFloat64);
    2445             : 
    2446        1891 :   Node* check0 = ObjectIsSmi(value);
    2447        1891 :   __ GotoUnless(check0, &if_not_smi);
    2448        1891 :   Node* from_smi = ChangeSmiToInt32(value);
    2449        1891 :   __ Goto(&done, __ ChangeInt32ToFloat64(from_smi));
    2450             : 
    2451             :   __ Bind(&if_not_smi);
    2452        1891 :   Node* to_number = __ ToNumber(value);
    2453        1891 :   Node* check1 = ObjectIsSmi(to_number);
    2454        1891 :   __ GotoIf(check1, &if_to_number_smi);
    2455             : 
    2456        1891 :   Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), to_number);
    2457             :   __ Goto(&done, number);
    2458             : 
    2459             :   __ Bind(&if_to_number_smi);
    2460        1891 :   Node* number_from_smi = ChangeSmiToInt32(to_number);
    2461        1891 :   number_from_smi = __ ChangeInt32ToFloat64(number_from_smi);
    2462             :   __ Goto(&done, number_from_smi);
    2463             : 
    2464        1891 :   __ Bind(&done);
    2465        1891 :   return done.PhiAt(0);
    2466             : }
    2467             : 
    2468         181 : Node* EffectControlLinearizer::LowerEnsureWritableFastElements(Node* node) {
    2469             :   Node* object = node->InputAt(0);
    2470             :   Node* elements = node->InputAt(1);
    2471             : 
    2472         181 :   auto if_not_fixed_array = __ MakeDeferredLabel<1>();
    2473         181 :   auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
    2474             : 
    2475             :   // Load the current map of {elements}.
    2476         181 :   Node* elements_map = __ LoadField(AccessBuilder::ForMap(), elements);
    2477             : 
    2478             :   // Check if {elements} is not a copy-on-write FixedArray.
    2479         181 :   Node* check = __ WordEqual(elements_map, __ FixedArrayMapConstant());
    2480         181 :   __ GotoUnless(check, &if_not_fixed_array);
    2481             :   // Nothing to do if the {elements} are not copy-on-write.
    2482             :   __ Goto(&done, elements);
    2483             : 
    2484             :   __ Bind(&if_not_fixed_array);
    2485             :   // We need to take a copy of the {elements} and set them up for {object}.
    2486             :   Operator::Properties properties = Operator::kEliminatable;
    2487         181 :   Callable callable = CodeFactory::CopyFastSmiOrObjectElements(isolate());
    2488             :   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    2489             :   CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
    2490         543 :       isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
    2491             :   Node* result = __ Call(desc, __ HeapConstant(callable.code()), object,
    2492         362 :                          __ NoContextConstant());
    2493             :   __ Goto(&done, result);
    2494             : 
    2495         181 :   __ Bind(&done);
    2496         181 :   return done.PhiAt(0);
    2497             : }
    2498             : 
    2499        2054 : Node* EffectControlLinearizer::LowerMaybeGrowFastElements(Node* node,
    2500             :                                                           Node* frame_state) {
    2501        2054 :   GrowFastElementsFlags flags = GrowFastElementsFlagsOf(node->op());
    2502             :   Node* object = node->InputAt(0);
    2503             :   Node* elements = node->InputAt(1);
    2504             :   Node* index = node->InputAt(2);
    2505             :   Node* length = node->InputAt(3);
    2506             : 
    2507        2054 :   auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
    2508        2054 :   auto done_grow = __ MakeLabel<2>(MachineRepresentation::kTagged);
    2509        2054 :   auto if_grow = __ MakeDeferredLabel<1>();
    2510        2054 :   auto if_not_grow = __ MakeLabel<1>();
    2511             : 
    2512             :   Node* check0 = (flags & GrowFastElementsFlag::kHoleyElements)
    2513         190 :                      ? __ Uint32LessThanOrEqual(length, index)
    2514        2244 :                      : __ Word32Equal(length, index);
    2515        2054 :   __ GotoUnless(check0, &if_not_grow);
    2516             :   {
    2517             :     // Load the length of the {elements} backing store.
    2518             :     Node* elements_length =
    2519        2054 :         __ LoadField(AccessBuilder::ForFixedArrayLength(), elements);
    2520        2054 :     elements_length = ChangeSmiToInt32(elements_length);
    2521             : 
    2522             :     // Check if we need to grow the {elements} backing store.
    2523        2054 :     Node* check1 = __ Uint32LessThan(index, elements_length);
    2524        2054 :     __ GotoUnless(check1, &if_grow);
    2525             :     __ Goto(&done_grow, elements);
    2526             : 
    2527             :     __ Bind(&if_grow);
    2528             :     // We need to grow the {elements} for {object}.
    2529             :     Operator::Properties properties = Operator::kEliminatable;
    2530             :     Callable callable =
    2531             :         (flags & GrowFastElementsFlag::kDoubleElements)
    2532             :             ? CodeFactory::GrowFastDoubleElements(isolate())
    2533        4108 :             : CodeFactory::GrowFastSmiOrObjectElements(isolate());
    2534             :     CallDescriptor::Flags call_flags = CallDescriptor::kNoFlags;
    2535             :     CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
    2536             :         isolate(), graph()->zone(), callable.descriptor(), 0, call_flags,
    2537        6162 :         properties);
    2538             :     Node* new_object = __ Call(desc, __ HeapConstant(callable.code()), object,
    2539        4108 :                                ChangeInt32ToSmi(index), __ NoContextConstant());
    2540             : 
    2541             :     // Ensure that we were able to grow the {elements}.
    2542             :     // TODO(turbofan): We use kSmi as reason here similar to Crankshaft,
    2543             :     // but maybe we should just introduce a reason that makes sense.
    2544             :     __ DeoptimizeIf(DeoptimizeReason::kSmi, ObjectIsSmi(new_object),
    2545        2054 :                     frame_state);
    2546             :     __ Goto(&done_grow, new_object);
    2547             : 
    2548        2054 :     __ Bind(&done_grow);
    2549             : 
    2550             :     // For JSArray {object}s we also need to update the "length".
    2551        2054 :     if (flags & GrowFastElementsFlag::kArrayObject) {
    2552             :       // Compute the new {length}.
    2553             :       Node* object_length =
    2554        2041 :           ChangeInt32ToSmi(__ Int32Add(index, __ Int32Constant(1)));
    2555             : 
    2556             :       // Update the "length" property of the {object}.
    2557             :       __ StoreField(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS), object,
    2558        2041 :                     object_length);
    2559             :     }
    2560             :     __ Goto(&done, done_grow.PhiAt(0));
    2561             :   }
    2562             : 
    2563             :   __ Bind(&if_not_grow);
    2564             :   {
    2565             :     // In case of non-holey {elements}, we need to verify that the {index} is
    2566             :     // in-bounds, otherwise for holey {elements}, the check above already
    2567             :     // guards the index (and the operator forces {index} to be unsigned).
    2568        2054 :     if (!(flags & GrowFastElementsFlag::kHoleyElements)) {
    2569        1864 :       Node* check1 = __ Uint32LessThan(index, length);
    2570        1864 :       __ DeoptimizeUnless(DeoptimizeReason::kOutOfBounds, check1, frame_state);
    2571             :     }
    2572             :     __ Goto(&done, elements);
    2573             :   }
    2574        2054 :   __ Bind(&done);
    2575        2054 :   return done.PhiAt(0);
    2576             : }
    2577             : 
    2578         462 : void EffectControlLinearizer::LowerTransitionElementsKind(Node* node) {
    2579         462 :   ElementsTransition const transition = ElementsTransitionOf(node->op());
    2580             :   Node* object = node->InputAt(0);
    2581             : 
    2582         462 :   auto if_map_same = __ MakeDeferredLabel<1>();
    2583         462 :   auto done = __ MakeLabel<2>();
    2584             : 
    2585         462 :   Node* source_map = __ HeapConstant(transition.source());
    2586         462 :   Node* target_map = __ HeapConstant(transition.target());
    2587             : 
    2588             :   // Load the current map of {object}.
    2589         462 :   Node* object_map = __ LoadField(AccessBuilder::ForMap(), object);
    2590             : 
    2591             :   // Check if {object_map} is the same as {source_map}.
    2592         462 :   Node* check = __ WordEqual(object_map, source_map);
    2593         462 :   __ GotoIf(check, &if_map_same);
    2594             :   __ Goto(&done);
    2595             : 
    2596             :   __ Bind(&if_map_same);
    2597         462 :   switch (transition.mode()) {
    2598             :     case ElementsTransition::kFastTransition:
    2599             :       // In-place migration of {object}, just store the {target_map}.
    2600         202 :       __ StoreField(AccessBuilder::ForMap(), object, target_map);
    2601         202 :       break;
    2602             :     case ElementsTransition::kSlowTransition: {
    2603             :       // Instance migration, call out to the runtime for {object}.
    2604         260 :       Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
    2605             :       Runtime::FunctionId id = Runtime::kTransitionElementsKind;
    2606             :       CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
    2607         260 :           graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags);
    2608             :       __ Call(desc, __ CEntryStubConstant(1), object, target_map,
    2609             :               __ ExternalConstant(ExternalReference(id, isolate())),
    2610         520 :               __ Int32Constant(2), __ NoContextConstant());
    2611             :       break;
    2612             :     }
    2613             :   }
    2614             :   __ Goto(&done);
    2615             : 
    2616         462 :   __ Bind(&done);
    2617         462 : }
    2618             : 
    2619        3452 : Node* EffectControlLinearizer::LowerLoadTypedElement(Node* node) {
    2620        3452 :   ExternalArrayType array_type = ExternalArrayTypeOf(node->op());
    2621             :   Node* buffer = node->InputAt(0);
    2622             :   Node* base = node->InputAt(1);
    2623             :   Node* external = node->InputAt(2);
    2624             :   Node* index = node->InputAt(3);
    2625             : 
    2626             :   // We need to keep the {buffer} alive so that the GC will not release the
    2627             :   // ArrayBuffer (if there's any) as long as we are still operating on it.
    2628        3452 :   __ Retain(buffer);
    2629             : 
    2630             :   // Compute the effective storage pointer, handling the case where the
    2631             :   // {external} pointer is the effective storage pointer (i.e. the {base}
    2632             :   // is Smi zero).
    2633             :   Node* storage = NumberMatcher(base).Is(0) ? external : __ UnsafePointerAdd(
    2634        3452 :                                                              base, external);
    2635             : 
    2636             :   // Perform the actual typed element access.
    2637             :   return __ LoadElement(AccessBuilder::ForTypedArrayElement(array_type, true),
    2638        3452 :                         storage, index);
    2639             : }
    2640             : 
    2641        3062 : void EffectControlLinearizer::LowerStoreTypedElement(Node* node) {
    2642        3062 :   ExternalArrayType array_type = ExternalArrayTypeOf(node->op());
    2643             :   Node* buffer = node->InputAt(0);
    2644             :   Node* base = node->InputAt(1);
    2645             :   Node* external = node->InputAt(2);
    2646             :   Node* index = node->InputAt(3);
    2647             :   Node* value = node->InputAt(4);
    2648             : 
    2649             :   // We need to keep the {buffer} alive so that the GC will not release the
    2650             :   // ArrayBuffer (if there's any) as long as we are still operating on it.
    2651        3062 :   __ Retain(buffer);
    2652             : 
    2653             :   // Compute the effective storage pointer, handling the case where the
    2654             :   // {external} pointer is the effective storage pointer (i.e. the {base}
    2655             :   // is Smi zero).
    2656             :   Node* storage = NumberMatcher(base).Is(0) ? external : __ UnsafePointerAdd(
    2657        3062 :                                                              base, external);
    2658             : 
    2659             :   // Perform the actual typed element access.
    2660             :   __ StoreElement(AccessBuilder::ForTypedArrayElement(array_type, true),
    2661        3062 :                   storage, index, value);
    2662        3062 : }
    2663             : 
    2664        5772 : Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundUp(Node* node) {
    2665             :   // Nothing to be done if a fast hardware instruction is available.
    2666        5772 :   if (machine()->Float64RoundUp().IsSupported()) {
    2667             :     return Nothing<Node*>();
    2668             :   }
    2669             : 
    2670             :   Node* const input = node->InputAt(0);
    2671             : 
    2672             :   // General case for ceil.
    2673             :   //
    2674             :   //   if 0.0 < input then
    2675             :   //     if 2^52 <= input then
    2676             :   //       input
    2677             :   //     else
    2678             :   //       let temp1 = (2^52 + input) - 2^52 in
    2679             :   //       if temp1 < input then
    2680             :   //         temp1 + 1
    2681             :   //       else
    2682             :   //         temp1
    2683             :   //   else
    2684             :   //     if input == 0 then
    2685             :   //       input
    2686             :   //     else
    2687             :   //       if input <= -2^52 then
    2688             :   //         input
    2689             :   //       else
    2690             :   //         let temp1 = -0 - input in
    2691             :   //         let temp2 = (2^52 + temp1) - 2^52 in
    2692             :   //         let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
    2693             :   //         -0 - temp3
    2694             : 
    2695           0 :   auto if_not_positive = __ MakeDeferredLabel<1>();
    2696           0 :   auto if_greater_than_two_52 = __ MakeDeferredLabel<1>();
    2697           0 :   auto if_less_than_minus_two_52 = __ MakeDeferredLabel<1>();
    2698           0 :   auto if_zero = __ MakeDeferredLabel<1>();
    2699           0 :   auto done_temp3 = __ MakeLabel<2>(MachineRepresentation::kFloat64);
    2700           0 :   auto done = __ MakeLabel<6>(MachineRepresentation::kFloat64);
    2701             : 
    2702           0 :   Node* const zero = __ Float64Constant(0.0);
    2703           0 :   Node* const two_52 = __ Float64Constant(4503599627370496.0E0);
    2704           0 :   Node* const one = __ Float64Constant(1.0);
    2705             : 
    2706           0 :   Node* check0 = __ Float64LessThan(zero, input);
    2707           0 :   __ GotoUnless(check0, &if_not_positive);
    2708             :   {
    2709           0 :     Node* check1 = __ Float64LessThanOrEqual(two_52, input);
    2710           0 :     __ GotoIf(check1, &if_greater_than_two_52);
    2711             :     {
    2712           0 :       Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52);
    2713           0 :       __ GotoUnless(__ Float64LessThan(temp1, input), &done, temp1);
    2714           0 :       __ Goto(&done, __ Float64Add(temp1, one));
    2715             :     }
    2716             : 
    2717             :     __ Bind(&if_greater_than_two_52);
    2718             :     __ Goto(&done, input);
    2719             :   }
    2720             : 
    2721             :   __ Bind(&if_not_positive);
    2722             :   {
    2723           0 :     Node* check1 = __ Float64Equal(input, zero);
    2724           0 :     __ GotoIf(check1, &if_zero);
    2725             : 
    2726           0 :     Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0);
    2727           0 :     Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52);
    2728           0 :     __ GotoIf(check2, &if_less_than_minus_two_52);
    2729             : 
    2730             :     {
    2731           0 :       Node* const minus_zero = __ Float64Constant(-0.0);
    2732           0 :       Node* temp1 = __ Float64Sub(minus_zero, input);
    2733           0 :       Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52);
    2734           0 :       Node* check3 = __ Float64LessThan(temp1, temp2);
    2735           0 :       __ GotoUnless(check3, &done_temp3, temp2);
    2736           0 :       __ Goto(&done_temp3, __ Float64Sub(temp2, one));
    2737             : 
    2738           0 :       __ Bind(&done_temp3);
    2739             :       Node* temp3 = done_temp3.PhiAt(0);
    2740           0 :       __ Goto(&done, __ Float64Sub(minus_zero, temp3));
    2741             :     }
    2742             :     __ Bind(&if_less_than_minus_two_52);
    2743             :     __ Goto(&done, input);
    2744             : 
    2745             :     __ Bind(&if_zero);
    2746             :     __ Goto(&done, input);
    2747             :   }
    2748           0 :   __ Bind(&done);
    2749             :   return Just(done.PhiAt(0));
    2750             : }
    2751             : 
    2752           0 : Node* EffectControlLinearizer::BuildFloat64RoundDown(Node* value) {
    2753           0 :   Node* round_down = __ Float64RoundDown(value);
    2754           0 :   if (round_down != nullptr) {
    2755             :     return round_down;
    2756             :   }
    2757             : 
    2758             :   Node* const input = value;
    2759             : 
    2760             :   // General case for floor.
    2761             :   //
    2762             :   //   if 0.0 < input then
    2763             :   //     if 2^52 <= input then
    2764             :   //       input
    2765             :   //     else
    2766             :   //       let temp1 = (2^52 + input) - 2^52 in
    2767             :   //       if input < temp1 then
    2768             :   //         temp1 - 1
    2769             :   //       else
    2770             :   //         temp1
    2771             :   //   else
    2772             :   //     if input == 0 then
    2773             :   //       input
    2774             :   //     else
    2775             :   //       if input <= -2^52 then
    2776             :   //         input
    2777             :   //       else
    2778             :   //         let temp1 = -0 - input in
    2779             :   //         let temp2 = (2^52 + temp1) - 2^52 in
    2780             :   //         if temp2 < temp1 then
    2781             :   //           -1 - temp2
    2782             :   //         else
    2783             :   //           -0 - temp2
    2784             : 
    2785           0 :   auto if_not_positive = __ MakeDeferredLabel<1>();
    2786           0 :   auto if_greater_than_two_52 = __ MakeDeferredLabel<1>();
    2787           0 :   auto if_less_than_minus_two_52 = __ MakeDeferredLabel<1>();
    2788           0 :   auto if_temp2_lt_temp1 = __ MakeLabel<1>();
    2789           0 :   auto if_zero = __ MakeDeferredLabel<1>();
    2790           0 :   auto done = __ MakeLabel<7>(MachineRepresentation::kFloat64);
    2791             : 
    2792           0 :   Node* const zero = __ Float64Constant(0.0);
    2793           0 :   Node* const two_52 = __ Float64Constant(4503599627370496.0E0);
    2794             : 
    2795           0 :   Node* check0 = __ Float64LessThan(zero, input);
    2796           0 :   __ GotoUnless(check0, &if_not_positive);
    2797             :   {
    2798           0 :     Node* check1 = __ Float64LessThanOrEqual(two_52, input);
    2799           0 :     __ GotoIf(check1, &if_greater_than_two_52);
    2800             :     {
    2801           0 :       Node* const one = __ Float64Constant(1.0);
    2802           0 :       Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52);
    2803           0 :       __ GotoUnless(__ Float64LessThan(input, temp1), &done, temp1);
    2804           0 :       __ Goto(&done, __ Float64Sub(temp1, one));
    2805             :     }
    2806             : 
    2807             :     __ Bind(&if_greater_than_two_52);
    2808             :     __ Goto(&done, input);
    2809             :   }
    2810             : 
    2811             :   __ Bind(&if_not_positive);
    2812             :   {
    2813           0 :     Node* check1 = __ Float64Equal(input, zero);
    2814           0 :     __ GotoIf(check1, &if_zero);
    2815             : 
    2816           0 :     Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0);
    2817           0 :     Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52);
    2818           0 :     __ GotoIf(check2, &if_less_than_minus_two_52);
    2819             : 
    2820             :     {
    2821           0 :       Node* const minus_zero = __ Float64Constant(-0.0);
    2822           0 :       Node* temp1 = __ Float64Sub(minus_zero, input);
    2823           0 :       Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52);
    2824           0 :       Node* check3 = __ Float64LessThan(temp2, temp1);
    2825           0 :       __ GotoIf(check3, &if_temp2_lt_temp1);
    2826           0 :       __ Goto(&done, __ Float64Sub(minus_zero, temp2));
    2827             : 
    2828             :       __ Bind(&if_temp2_lt_temp1);
    2829           0 :       __ Goto(&done, __ Float64Sub(__ Float64Constant(-1.0), temp2));
    2830             :     }
    2831             :     __ Bind(&if_less_than_minus_two_52);
    2832             :     __ Goto(&done, input);
    2833             : 
    2834             :     __ Bind(&if_zero);
    2835             :     __ Goto(&done, input);
    2836             :   }
    2837           0 :   __ Bind(&done);
    2838             :   return done.PhiAt(0);
    2839             : }
    2840             : 
    2841        8875 : Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundDown(Node* node) {
    2842             :   // Nothing to be done if a fast hardware instruction is available.
    2843        8875 :   if (machine()->Float64RoundDown().IsSupported()) {
    2844             :     return Nothing<Node*>();
    2845             :   }
    2846             : 
    2847             :   Node* const input = node->InputAt(0);
    2848           0 :   return Just(BuildFloat64RoundDown(input));
    2849             : }
    2850             : 
    2851         300 : Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundTiesEven(Node* node) {
    2852             :   // Nothing to be done if a fast hardware instruction is available.
    2853         300 :   if (machine()->Float64RoundTiesEven().IsSupported()) {
    2854             :     return Nothing<Node*>();
    2855             :   }
    2856             : 
    2857             :   Node* const input = node->InputAt(0);
    2858             : 
    2859             :   // Generate case for round ties to even:
    2860             :   //
    2861             :   //   let value = floor(input) in
    2862             :   //   let temp1 = input - value in
    2863             :   //   if temp1 < 0.5 then
    2864             :   //     value
    2865             :   //   else if 0.5 < temp1 then
    2866             :   //     value + 1.0
    2867             :   //   else
    2868             :   //     let temp2 = value % 2.0 in
    2869             :   //     if temp2 == 0.0 then
    2870             :   //       value
    2871             :   //     else
    2872             :   //       value + 1.0
    2873             : 
    2874           0 :   auto if_is_half = __ MakeLabel<1>();
    2875           0 :   auto done = __ MakeLabel<4>(MachineRepresentation::kFloat64);
    2876             : 
    2877           0 :   Node* value = BuildFloat64RoundDown(input);
    2878           0 :   Node* temp1 = __ Float64Sub(input, value);
    2879             : 
    2880           0 :   Node* const half = __ Float64Constant(0.5);
    2881           0 :   Node* check0 = __ Float64LessThan(temp1, half);
    2882           0 :   __ GotoIf(check0, &done, value);
    2883             : 
    2884           0 :   Node* const one = __ Float64Constant(1.0);
    2885           0 :   Node* check1 = __ Float64LessThan(half, temp1);
    2886           0 :   __ GotoUnless(check1, &if_is_half);
    2887           0 :   __ Goto(&done, __ Float64Add(value, one));
    2888             : 
    2889             :   __ Bind(&if_is_half);
    2890           0 :   Node* temp2 = __ Float64Mod(value, __ Float64Constant(2.0));
    2891           0 :   Node* check2 = __ Float64Equal(temp2, __ Float64Constant(0.0));
    2892           0 :   __ GotoIf(check2, &done, value);
    2893           0 :   __ Goto(&done, __ Float64Add(value, one));
    2894             : 
    2895           0 :   __ Bind(&done);
    2896             :   return Just(done.PhiAt(0));
    2897             : }
    2898             : 
    2899        1389 : Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundTruncate(Node* node) {
    2900             :   // Nothing to be done if a fast hardware instruction is available.
    2901        1389 :   if (machine()->Float64RoundTruncate().IsSupported()) {
    2902             :     return Nothing<Node*>();
    2903             :   }
    2904             : 
    2905             :   Node* const input = node->InputAt(0);
    2906             : 
    2907             :   // General case for trunc.
    2908             :   //
    2909             :   //   if 0.0 < input then
    2910             :   //     if 2^52 <= input then
    2911             :   //       input
    2912             :   //     else
    2913             :   //       let temp1 = (2^52 + input) - 2^52 in
    2914             :   //       if input < temp1 then
    2915             :   //         temp1 - 1
    2916             :   //       else
    2917             :   //         temp1
    2918             :   //   else
    2919             :   //     if input == 0 then
    2920             :   //       input
    2921             :   //     else
    2922             :   //       if input <= -2^52 then
    2923             :   //         input
    2924             :   //       else
    2925             :   //         let temp1 = -0 - input in
    2926             :   //         let temp2 = (2^52 + temp1) - 2^52 in
    2927             :   //         let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
    2928             :   //         -0 - temp3
    2929             :   //
    2930             :   // Note: We do not use the Diamond helper class here, because it really hurts
    2931             :   // readability with nested diamonds.
    2932             : 
    2933           0 :   auto if_not_positive = __ MakeDeferredLabel<1>();
    2934           0 :   auto if_greater_than_two_52 = __ MakeDeferredLabel<1>();
    2935           0 :   auto if_less_than_minus_two_52 = __ MakeDeferredLabel<1>();
    2936           0 :   auto if_zero = __ MakeDeferredLabel<1>();
    2937           0 :   auto done_temp3 = __ MakeLabel<2>(MachineRepresentation::kFloat64);
    2938           0 :   auto done = __ MakeLabel<6>(MachineRepresentation::kFloat64);
    2939             : 
    2940           0 :   Node* const zero = __ Float64Constant(0.0);
    2941           0 :   Node* const two_52 = __ Float64Constant(4503599627370496.0E0);
    2942           0 :   Node* const one = __ Float64Constant(1.0);
    2943             : 
    2944           0 :   Node* check0 = __ Float64LessThan(zero, input);
    2945           0 :   __ GotoUnless(check0, &if_not_positive);
    2946             :   {
    2947           0 :     Node* check1 = __ Float64LessThanOrEqual(two_52, input);
    2948           0 :     __ GotoIf(check1, &if_greater_than_two_52);
    2949             :     {
    2950           0 :       Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52);
    2951           0 :       __ GotoUnless(__ Float64LessThan(input, temp1), &done, temp1);
    2952           0 :       __ Goto(&done, __ Float64Sub(temp1, one));
    2953             :     }
    2954             : 
    2955             :     __ Bind(&if_greater_than_two_52);
    2956             :     __ Goto(&done, input);
    2957             :   }
    2958             : 
    2959             :   __ Bind(&if_not_positive);
    2960             :   {
    2961           0 :     Node* check1 = __ Float64Equal(input, zero);
    2962           0 :     __ GotoIf(check1, &if_zero);
    2963             : 
    2964           0 :     Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0);
    2965           0 :     Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52);
    2966           0 :     __ GotoIf(check2, &if_less_than_minus_two_52);
    2967             : 
    2968             :     {
    2969           0 :       Node* const minus_zero = __ Float64Constant(-0.0);
    2970           0 :       Node* temp1 = __ Float64Sub(minus_zero, input);
    2971           0 :       Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52);
    2972           0 :       Node* check3 = __ Float64LessThan(temp1, temp2);
    2973           0 :       __ GotoUnless(check3, &done_temp3, temp2);
    2974           0 :       __ Goto(&done_temp3, __ Float64Sub(temp2, one));
    2975             : 
    2976           0 :       __ Bind(&done_temp3);
    2977             :       Node* temp3 = done_temp3.PhiAt(0);
    2978           0 :       __ Goto(&done, __ Float64Sub(minus_zero, temp3));
    2979             :     }
    2980             :     __ Bind(&if_less_than_minus_two_52);
    2981             :     __ Goto(&done, input);
    2982             : 
    2983             :     __ Bind(&if_zero);
    2984             :     __ Goto(&done, input);
    2985             :   }
    2986           0 :   __ Bind(&done);
    2987             :   return Just(done.PhiAt(0));
    2988             : }
    2989             : 
    2990             : #undef __
    2991             : 
    2992           0 : Factory* EffectControlLinearizer::factory() const {
    2993           0 :   return isolate()->factory();
    2994             : }
    2995             : 
    2996       12245 : Isolate* EffectControlLinearizer::isolate() const {
    2997       21801 :   return jsgraph()->isolate();
    2998             : }
    2999             : 
    3000             : }  // namespace compiler
    3001             : }  // namespace internal
    3002             : }  // namespace v8

Generated by: LCOV version 1.10