1bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// Copyright 2015 the V8 project authors. All rights reserved. 2bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// found in the LICENSE file. 4bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 5bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/compiler/effect-control-linearizer.h" 6bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 7bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/code-factory.h" 8bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/compiler/access-builder.h" 9c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch#include "src/compiler/compiler-source-position-table.h" 10bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/compiler/js-graph.h" 11bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/compiler/linkage.h" 12f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/compiler/node-matchers.h" 13bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/compiler/node-properties.h" 14bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/compiler/node.h" 15bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/compiler/schedule.h" 1662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h" 17bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 18bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace v8 { 19bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace internal { 20bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace compiler { 21bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 22c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochEffectControlLinearizer::EffectControlLinearizer( 23c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch JSGraph* js_graph, Schedule* schedule, Zone* temp_zone, 24c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SourcePositionTable* source_positions) 25c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch : js_graph_(js_graph), 26c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch schedule_(schedule), 27c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch temp_zone_(temp_zone), 2862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch source_positions_(source_positions), 2962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch graph_assembler_(js_graph, nullptr, nullptr, temp_zone) {} 30bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 31bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochGraph* EffectControlLinearizer::graph() const { return js_graph_->graph(); } 32bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochCommonOperatorBuilder* EffectControlLinearizer::common() const { 33bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return js_graph_->common(); 34bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 35bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochSimplifiedOperatorBuilder* EffectControlLinearizer::simplified() const { 36bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return js_graph_->simplified(); 37bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 38bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochMachineOperatorBuilder* EffectControlLinearizer::machine() const { 39bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return js_graph_->machine(); 40bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 41bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 42bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace { 43bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 44bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochstruct BlockEffectControlData { 45f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* current_effect = nullptr; // New effect. 46f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* current_control = nullptr; // New control. 4713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* current_frame_state = nullptr; // New frame state. 48bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}; 49bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 50f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochclass BlockEffectControlMap { 51f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch public: 52f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch explicit BlockEffectControlMap(Zone* temp_zone) : map_(temp_zone) {} 53f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 54f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BlockEffectControlData& For(BasicBlock* from, BasicBlock* to) { 55f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return map_[std::make_pair(from->rpo_number(), to->rpo_number())]; 56f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 57f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 58f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch const BlockEffectControlData& For(BasicBlock* from, BasicBlock* to) const { 59f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return map_.at(std::make_pair(from->rpo_number(), to->rpo_number())); 60f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 61f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 62f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch private: 63f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch typedef std::pair<int32_t, int32_t> Key; 64f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch typedef ZoneMap<Key, BlockEffectControlData> Map; 65f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 66f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Map map_; 67f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}; 68f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 69bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// Effect phis that need to be updated after the first pass. 70bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochstruct PendingEffectPhi { 71bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* effect_phi; 72bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BasicBlock* block; 73bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 74bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PendingEffectPhi(Node* effect_phi, BasicBlock* block) 75bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch : effect_phi(effect_phi), block(block) {} 76bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}; 77bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 78bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid UpdateEffectPhi(Node* node, BasicBlock* block, 79f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BlockEffectControlMap* block_effects) { 80bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Update all inputs to an effect phi with the effects from the given 81bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // block->effect map. 82bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode()); 83c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK_EQ(static_cast<size_t>(node->op()->EffectInputCount()), 84c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch block->PredecessorCount()); 85bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch for (int i = 0; i < node->op()->EffectInputCount(); i++) { 86bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* input = node->InputAt(i); 87bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i)); 88f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch const BlockEffectControlData& block_effect = 89f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch block_effects->For(predecessor, block); 90f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (input != block_effect.current_effect) { 91f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch node->ReplaceInput(i, block_effect.current_effect); 92bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 93bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 94bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 95bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 96bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid UpdateBlockControl(BasicBlock* block, 97f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BlockEffectControlMap* block_effects) { 98bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* control = block->NodeAt(0); 99bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(NodeProperties::IsControl(control)); 100bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 101bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Do not rewire the end node. 102bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (control->opcode() == IrOpcode::kEnd) return; 103bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 104bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Update all inputs to the given control node with the correct control. 105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(control->opcode() == IrOpcode::kMerge || 106c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch static_cast<size_t>(control->op()->ControlInputCount()) == 107c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch block->PredecessorCount()); 108c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (static_cast<size_t>(control->op()->ControlInputCount()) != 109c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch block->PredecessorCount()) { 110f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return; // We already re-wired the control inputs of this node. 111f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 112bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch for (int i = 0; i < control->op()->ControlInputCount(); i++) { 113bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* input = NodeProperties::GetControlInput(control, i); 114bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i)); 115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch const BlockEffectControlData& block_effect = 116f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch block_effects->For(predecessor, block); 117f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (input != block_effect.current_control) { 118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch NodeProperties::ReplaceControlInput(control, block_effect.current_control, 119f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch i); 120bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 121bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 122bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 123bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 124bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochbool HasIncomingBackEdges(BasicBlock* block) { 125bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch for (BasicBlock* pred : block->predecessors()) { 126bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (pred->rpo_number() >= block->rpo_number()) { 127bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return true; 128bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 129bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 130bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return false; 131bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 132bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 133bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid RemoveRegionNode(Node* node) { 134bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(IrOpcode::kFinishRegion == node->opcode() || 135bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch IrOpcode::kBeginRegion == node->opcode()); 136bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Update the value/context uses to the value input of the finish node and 137bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // the effect uses to the effect input. 138bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch for (Edge edge : node->use_edges()) { 139bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(!edge.from()->IsDead()); 140bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (NodeProperties::IsEffectEdge(edge)) { 141bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch edge.UpdateTo(NodeProperties::GetEffectInput(node)); 142bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 143bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(!NodeProperties::IsControlEdge(edge)); 144bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(!NodeProperties::IsFrameStateEdge(edge)); 145bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch edge.UpdateTo(node->InputAt(0)); 146bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 147bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 148bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch node->Kill(); 149bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 150bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 151f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid TryCloneBranch(Node* node, BasicBlock* block, Graph* graph, 152f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CommonOperatorBuilder* common, 153c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch BlockEffectControlMap* block_effects, 154c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SourcePositionTable* source_positions) { 155f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK_EQ(IrOpcode::kBranch, node->opcode()); 156f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 157f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // This optimization is a special case of (super)block cloning. It takes an 158f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // input graph as shown below and clones the Branch node for every predecessor 159f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // to the Merge, essentially removing the Merge completely. This avoids 160f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // materializing the bit for the Phi and may offer potential for further 161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // branch folding optimizations (i.e. because one or more inputs to the Phi is 162f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // a constant). Note that there may be more Phi nodes hanging off the Merge, 163f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // but we can only a certain subset of them currently (actually only Phi and 164f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // EffectPhi nodes whose uses have either the IfTrue or IfFalse as control 165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // input). 166f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 167f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Control1 ... ControlN 168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ^ ^ 169f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // | | Cond1 ... CondN 170f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // +----+ +----+ ^ ^ 171f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // | | | | 172f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // | | +----+ | 173f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Merge<--+ | +------------+ 174f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ^ \|/ 175f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // | Phi 176f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // | | 177f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Branch----+ 178f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ^ 179f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // | 180f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // +-----+-----+ 181f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // | | 182f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // IfTrue IfFalse 183f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ^ ^ 184f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // | | 185f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 186f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // The resulting graph (modulo the Phi and EffectPhi nodes) looks like this: 187f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 188f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Control1 Cond1 ... ControlN CondN 189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ^ ^ ^ ^ 190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // \ / \ / 191f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Branch ... Branch 192f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ^ ^ 193f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // | | 194f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // +---+---+ +---+----+ 195f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // | | | | 196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // IfTrue IfFalse ... IfTrue IfFalse 197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ^ ^ ^ ^ 198f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // | | | | 199f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // +--+ +-------------+ | 200f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // | | +--------------+ +--+ 201f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // | | | | 202f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Merge Merge 203f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ^ ^ 204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // | | 205f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 206c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SourcePositionTable::Scope scope(source_positions, 207c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch source_positions->GetSourcePosition(node)); 208f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* branch = node; 209f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* cond = NodeProperties::GetValueInput(branch, 0); 210f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!cond->OwnedBy(branch) || cond->opcode() != IrOpcode::kPhi) return; 211f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* merge = NodeProperties::GetControlInput(branch); 212f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (merge->opcode() != IrOpcode::kMerge || 213f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch NodeProperties::GetControlInput(cond) != merge) { 214f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return; 215f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 216f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Grab the IfTrue/IfFalse projections of the Branch. 217f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BranchMatcher matcher(branch); 218f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check/collect other Phi/EffectPhi nodes hanging off the Merge. 219f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch NodeVector phis(graph->zone()); 220f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (Node* const use : merge->uses()) { 221f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (use == branch || use == cond) continue; 222f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // We cannot currently deal with non-Phi/EffectPhi nodes hanging off the 223f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Merge. Ideally, we would just clone the nodes (and everything that 224f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // depends on it to some distant join point), but that requires knowledge 225f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // about dominance/post-dominance. 226f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!NodeProperties::IsPhi(use)) return; 227f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (Edge edge : use->use_edges()) { 228f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Right now we can only handle Phi/EffectPhi nodes whose uses are 229f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // directly control-dependend on either the IfTrue or the IfFalse 230f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // successor, because we know exactly how to update those uses. 231f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (edge.from()->op()->ControlInputCount() != 1) return; 232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* control = NodeProperties::GetControlInput(edge.from()); 233f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (NodeProperties::IsPhi(edge.from())) { 234f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch control = NodeProperties::GetControlInput(control, edge.index()); 235f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 236f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (control != matcher.IfTrue() && control != matcher.IfFalse()) return; 237f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 238f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch phis.push_back(use); 239f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 240f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BranchHint const hint = BranchHintOf(branch->op()); 241f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int const input_count = merge->op()->ControlInputCount(); 242f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK_LE(1, input_count); 243f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node** const inputs = graph->zone()->NewArray<Node*>(2 * input_count); 244f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node** const merge_true_inputs = &inputs[0]; 245f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node** const merge_false_inputs = &inputs[input_count]; 246f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int index = 0; index < input_count; ++index) { 247f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* cond1 = NodeProperties::GetValueInput(cond, index); 248f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* control1 = NodeProperties::GetControlInput(merge, index); 249f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* branch1 = graph->NewNode(common->Branch(hint), cond1, control1); 250f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch merge_true_inputs[index] = graph->NewNode(common->IfTrue(), branch1); 251f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch merge_false_inputs[index] = graph->NewNode(common->IfFalse(), branch1); 252f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 253f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* const merge_true = matcher.IfTrue(); 254f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* const merge_false = matcher.IfFalse(); 255f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch merge_true->TrimInputCount(0); 256f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch merge_false->TrimInputCount(0); 257f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int i = 0; i < input_count; ++i) { 258f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch merge_true->AppendInput(graph->zone(), merge_true_inputs[i]); 259f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch merge_false->AppendInput(graph->zone(), merge_false_inputs[i]); 260f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 261c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK_EQ(2u, block->SuccessorCount()); 262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch NodeProperties::ChangeOp(matcher.IfTrue(), common->Merge(input_count)); 263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch NodeProperties::ChangeOp(matcher.IfFalse(), common->Merge(input_count)); 264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int const true_index = 265f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch block->SuccessorAt(0)->NodeAt(0) == matcher.IfTrue() ? 0 : 1; 266f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BlockEffectControlData* true_block_data = 267f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch &block_effects->For(block, block->SuccessorAt(true_index)); 268f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BlockEffectControlData* false_block_data = 269f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch &block_effects->For(block, block->SuccessorAt(true_index ^ 1)); 270f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (Node* const phi : phis) { 271f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int index = 0; index < input_count; ++index) { 272f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch inputs[index] = phi->InputAt(index); 273f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 274f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch inputs[input_count] = merge_true; 275f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* phi_true = graph->NewNode(phi->op(), input_count + 1, inputs); 276f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch inputs[input_count] = merge_false; 277f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* phi_false = graph->NewNode(phi->op(), input_count + 1, inputs); 278f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (phi->UseCount() == 0) { 279f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK_EQ(phi->opcode(), IrOpcode::kEffectPhi); 280f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 281f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (Edge edge : phi->use_edges()) { 282f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* control = NodeProperties::GetControlInput(edge.from()); 283f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (NodeProperties::IsPhi(edge.from())) { 284f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch control = NodeProperties::GetControlInput(control, edge.index()); 285f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 286f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(control == matcher.IfTrue() || control == matcher.IfFalse()); 287f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch edge.UpdateTo((control == matcher.IfTrue()) ? phi_true : phi_false); 288f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 289f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 290f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (phi->opcode() == IrOpcode::kEffectPhi) { 291f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch true_block_data->current_effect = phi_true; 292f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch false_block_data->current_effect = phi_false; 293f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 294f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch phi->Kill(); 295f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 296f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Fix up IfTrue and IfFalse and kill all dead nodes. 297f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (branch == block->control_input()) { 298f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch true_block_data->current_control = merge_true; 299f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch false_block_data->current_control = merge_false; 300f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 301f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch branch->Kill(); 302f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch cond->Kill(); 303f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch merge->Kill(); 304f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 305bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} // namespace 306bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 307bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid EffectControlLinearizer::Run() { 308f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BlockEffectControlMap block_effects(temp_zone()); 309bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch ZoneVector<PendingEffectPhi> pending_effect_phis(temp_zone()); 310bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch ZoneVector<BasicBlock*> pending_block_controls(temp_zone()); 311bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NodeVector inputs_buffer(temp_zone()); 312bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 313bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch for (BasicBlock* block : *(schedule()->rpo_order())) { 314bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch size_t instr = 0; 315bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 316bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // The control node should be the first. 317bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* control = block->NodeAt(instr); 318bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(NodeProperties::IsControl(control)); 319bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Update the control inputs. 320bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (HasIncomingBackEdges(block)) { 321bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // If there are back edges, we need to update later because we have not 322bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // computed the control yet. This should only happen for loops. 323bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK_EQ(IrOpcode::kLoop, control->opcode()); 324bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch pending_block_controls.push_back(block); 325bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 326bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // If there are no back edges, we can update now. 327bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch UpdateBlockControl(block, &block_effects); 328bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 329bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch instr++; 330bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 331bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Iterate over the phis and update the effect phis. 332bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* effect = nullptr; 333bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* terminate = nullptr; 334bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch for (; instr < block->NodeCount(); instr++) { 335bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* node = block->NodeAt(instr); 336bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Only go through the phis and effect phis. 337bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (node->opcode() == IrOpcode::kEffectPhi) { 338bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // There should be at most one effect phi in a block. 339bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK_NULL(effect); 340bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // IfException blocks should not have effect phis. 341bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK_NE(IrOpcode::kIfException, control->opcode()); 342bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch effect = node; 343bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 344bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Make sure we update the inputs to the incoming blocks' effects. 345bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (HasIncomingBackEdges(block)) { 346bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // In case of loops, we do not update the effect phi immediately 347bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // because the back predecessor has not been handled yet. We just 348bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // record the effect phi for later processing. 349bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch pending_effect_phis.push_back(PendingEffectPhi(node, block)); 350bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 351bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch UpdateEffectPhi(node, block, &block_effects); 352bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 353bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else if (node->opcode() == IrOpcode::kPhi) { 354bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Just skip phis. 355bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else if (node->opcode() == IrOpcode::kTerminate) { 356bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(terminate == nullptr); 357bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch terminate = node; 358bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 359bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 360bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 361bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 362bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 363bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (effect == nullptr) { 364bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // There was no effect phi. 365bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(!HasIncomingBackEdges(block)); 366bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (block == schedule()->start()) { 367bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Start block => effect is start. 368bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK_EQ(graph()->start(), control); 369bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch effect = graph()->start(); 370bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else if (control->opcode() == IrOpcode::kEnd) { 371bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // End block is just a dummy, no effect needed. 372bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK_EQ(BasicBlock::kNone, block->control()); 373bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK_EQ(1u, block->size()); 374bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch effect = nullptr; 375bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 376f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // If all the predecessors have the same effect, we can use it as our 377f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // current effect. 378f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch effect = 379f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch block_effects.For(block->PredecessorAt(0), block).current_effect; 380f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (size_t i = 1; i < block->PredecessorCount(); ++i) { 381f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (block_effects.For(block->PredecessorAt(i), block) 382f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch .current_effect != effect) { 383bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch effect = nullptr; 384bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 385bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 386bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 387bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (effect == nullptr) { 388bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK_NE(IrOpcode::kIfException, control->opcode()); 389bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // The input blocks do not have the same effect. We have 390bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // to create an effect phi node. 391bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch inputs_buffer.clear(); 392f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch inputs_buffer.resize(block->PredecessorCount(), jsgraph()->Dead()); 393bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch inputs_buffer.push_back(control); 394bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch effect = graph()->NewNode( 395bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch common()->EffectPhi(static_cast<int>(block->PredecessorCount())), 396bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch static_cast<int>(inputs_buffer.size()), &(inputs_buffer.front())); 397f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // For loops, we update the effect phi node later to break cycles. 398f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (control->opcode() == IrOpcode::kLoop) { 399f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch pending_effect_phis.push_back(PendingEffectPhi(effect, block)); 400f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 401f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UpdateEffectPhi(effect, block, &block_effects); 402f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 403bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else if (control->opcode() == IrOpcode::kIfException) { 404bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // The IfException is connected into the effect chain, so we need 405bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // to update the effect here. 406bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NodeProperties::ReplaceEffectInput(control, effect); 407bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch effect = control; 408bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 409bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 410bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 411bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 412bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Fixup the Terminate node. 413bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (terminate != nullptr) { 414bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NodeProperties::ReplaceEffectInput(terminate, effect); 415bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 416bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 41713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // The frame state at block entry is determined by the frame states leaving 41813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // all predecessors. In case there is no frame state dominating this block, 41913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // we can rely on a checkpoint being present before the next deoptimization. 42013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // TODO(mstarzinger): Eventually we will need to go hunt for a frame state 42113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // once deoptimizing nodes roam freely through the schedule. 42213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* frame_state = nullptr; 42313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (block != schedule()->start()) { 42413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // If all the predecessors have the same effect, we can use it 42513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // as our current effect. 426f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch frame_state = 427f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch block_effects.For(block->PredecessorAt(0), block).current_frame_state; 42813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (size_t i = 1; i < block->PredecessorCount(); i++) { 429f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (block_effects.For(block->PredecessorAt(i), block) 430f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch .current_frame_state != frame_state) { 43113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch frame_state = nullptr; 43213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 43313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 43413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 43513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 43613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 437bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Process the ordinary instructions. 438bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch for (; instr < block->NodeCount(); instr++) { 439bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* node = block->NodeAt(instr); 44013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ProcessNode(node, &frame_state, &effect, &control); 441bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 442bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 443bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch switch (block->control()) { 444bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case BasicBlock::kGoto: 445bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case BasicBlock::kNone: 446bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 447bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 448bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case BasicBlock::kCall: 449bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case BasicBlock::kTailCall: 450bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case BasicBlock::kSwitch: 451bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case BasicBlock::kReturn: 452bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case BasicBlock::kDeoptimize: 453bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case BasicBlock::kThrow: 45413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ProcessNode(block->control_input(), &frame_state, &effect, &control); 455bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 456f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 457f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case BasicBlock::kBranch: 458f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ProcessNode(block->control_input(), &frame_state, &effect, &control); 459f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TryCloneBranch(block->control_input(), block, graph(), common(), 460c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch &block_effects, source_positions_); 461f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 462bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 463bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 464f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Store the effect, control and frame state for later use. 465f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (BasicBlock* successor : block->successors()) { 466f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BlockEffectControlData* data = &block_effects.For(block, successor); 467f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (data->current_effect == nullptr) { 468f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch data->current_effect = effect; 469f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 470f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (data->current_control == nullptr) { 471f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch data->current_control = control; 472f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 473f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch data->current_frame_state = frame_state; 474f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 475bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 476bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 477bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Update the incoming edges of the effect phis that could not be processed 478bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // during the first pass (because they could have incoming back edges). 479bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch for (const PendingEffectPhi& pending_effect_phi : pending_effect_phis) { 480bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch UpdateEffectPhi(pending_effect_phi.effect_phi, pending_effect_phi.block, 481bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch &block_effects); 482bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 483bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch for (BasicBlock* pending_block_control : pending_block_controls) { 484bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch UpdateBlockControl(pending_block_control, &block_effects); 485bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 486bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 487bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 488bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace { 489bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 490bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid TryScheduleCallIfSuccess(Node* node, Node** control) { 491bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Schedule the call's IfSuccess node if there is no exception use. 492bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (!NodeProperties::IsExceptionalCall(node)) { 493bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch for (Edge edge : node->use_edges()) { 494bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (NodeProperties::IsControlEdge(edge) && 495bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch edge.from()->opcode() == IrOpcode::kIfSuccess) { 496bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch *control = edge.from(); 497bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 498bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 499bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 500bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 501bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 502bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} // namespace 503bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 50413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid EffectControlLinearizer::ProcessNode(Node* node, Node** frame_state, 50513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node** effect, Node** control) { 506c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SourcePositionTable::Scope scope(source_positions_, 507c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch source_positions_->GetSourcePosition(node)); 508c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 509bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // If the node needs to be wired into the effect/control chain, do this 51013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // here. Pass current frame state for lowering to eager deoptimization. 51113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (TryWireInStateEffect(node, *frame_state, effect, control)) { 512bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return; 513bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 514bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 51513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // If the node has a visible effect, then there must be a checkpoint in the 51613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // effect chain before we are allowed to place another eager deoptimization 51713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // point. We zap the frame state to ensure this invariant is maintained. 51813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (region_observability_ == RegionObservability::kObservable && 51913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch !node->op()->HasProperty(Operator::kNoWrite)) { 52013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *frame_state = nullptr; 52113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 52213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 523bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Remove the end markers of 'atomic' allocation region because the 524bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // region should be wired-in now. 52513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (node->opcode() == IrOpcode::kFinishRegion) { 52613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Reset the current region observability. 52713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch region_observability_ = RegionObservability::kObservable; 52813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Update the value uses to the value input of the finish node and 52913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // the effect uses to the effect input. 53013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return RemoveRegionNode(node); 53113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 53213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (node->opcode() == IrOpcode::kBeginRegion) { 53313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Determine the observability for this region and use that for all 53413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // nodes inside the region (i.e. ignore the absence of kNoWrite on 53513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // StoreField and other operators). 53613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK_NE(RegionObservability::kNotObservable, region_observability_); 53713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch region_observability_ = RegionObservabilityOf(node->op()); 538bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Update the value uses to the value input of the finish node and 539bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // the effect uses to the effect input. 540bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return RemoveRegionNode(node); 541bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 542bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 54313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Special treatment for checkpoint nodes. 54413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (node->opcode() == IrOpcode::kCheckpoint) { 545bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Unlink the check point; effect uses will be updated to the incoming 54613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // effect that is passed. The frame state is preserved for lowering. 54713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK_EQ(RegionObservability::kObservable, region_observability_); 548f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *frame_state = NodeProperties::GetFrameStateInput(node); 549bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return; 550bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 551bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 552bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (node->opcode() == IrOpcode::kIfSuccess) { 553bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // We always schedule IfSuccess with its call, so skip it here. 554bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK_EQ(IrOpcode::kCall, node->InputAt(0)->opcode()); 555bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // The IfSuccess node should not belong to an exceptional call node 556bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // because such IfSuccess nodes should only start a basic block (and 557bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // basic block start nodes are not handled in the ProcessNode method). 558bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(!NodeProperties::IsExceptionalCall(node->InputAt(0))); 559bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return; 560bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 561bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 562bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // If the node takes an effect, replace with the current one. 563bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (node->op()->EffectInputCount() > 0) { 564bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK_EQ(1, node->op()->EffectInputCount()); 565bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* input_effect = NodeProperties::GetEffectInput(node); 566bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 567bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (input_effect != *effect) { 568bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NodeProperties::ReplaceEffectInput(node, *effect); 569bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 570bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 571bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // If the node produces an effect, update our current effect. (However, 572bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ignore new effect chains started with ValueEffect.) 573bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (node->op()->EffectOutputCount() > 0) { 574bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK_EQ(1, node->op()->EffectOutputCount()); 575bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch *effect = node; 576bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 577bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } else { 578bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // New effect chain is only started with a Start or ValueEffect node. 579bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(node->op()->EffectOutputCount() == 0 || 580bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch node->opcode() == IrOpcode::kStart); 581bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 582bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 583bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Rewire control inputs. 584bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch for (int i = 0; i < node->op()->ControlInputCount(); i++) { 585bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NodeProperties::ReplaceControlInput(node, *control, i); 586bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 587bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Update the current control and wire IfSuccess right after calls. 588bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (node->op()->ControlOutputCount() > 0) { 589bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch *control = node; 590bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (node->opcode() == IrOpcode::kCall) { 591bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Schedule the call's IfSuccess node (if there is no exception use). 592bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch TryScheduleCallIfSuccess(node, control); 593bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 594bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 595bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 596bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 59713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochbool EffectControlLinearizer::TryWireInStateEffect(Node* node, 59813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* frame_state, 59913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node** effect, 600bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node** control) { 60162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch gasm()->Reset(*effect, *control); 60262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* result = nullptr; 603bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch switch (node->opcode()) { 604bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case IrOpcode::kChangeBitToTagged: 60562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerChangeBitToTagged(node); 606bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 607bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case IrOpcode::kChangeInt31ToTaggedSigned: 60862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerChangeInt31ToTaggedSigned(node); 609bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 610bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case IrOpcode::kChangeInt32ToTagged: 61162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerChangeInt32ToTagged(node); 612bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 613bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case IrOpcode::kChangeUint32ToTagged: 61462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerChangeUint32ToTagged(node); 615bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 616bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case IrOpcode::kChangeFloat64ToTagged: 61762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerChangeFloat64ToTagged(node); 618bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 619c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case IrOpcode::kChangeFloat64ToTaggedPointer: 62062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerChangeFloat64ToTaggedPointer(node); 621c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 622bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case IrOpcode::kChangeTaggedSignedToInt32: 62362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerChangeTaggedSignedToInt32(node); 624bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 625bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case IrOpcode::kChangeTaggedToBit: 62662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerChangeTaggedToBit(node); 627bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 628bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case IrOpcode::kChangeTaggedToInt32: 62962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerChangeTaggedToInt32(node); 630bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 631bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case IrOpcode::kChangeTaggedToUint32: 63262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerChangeTaggedToUint32(node); 633bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 634bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case IrOpcode::kChangeTaggedToFloat64: 63562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerChangeTaggedToFloat64(node); 63662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 63762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case IrOpcode::kChangeTaggedToTaggedSigned: 63862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerChangeTaggedToTaggedSigned(node); 639bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 640f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case IrOpcode::kTruncateTaggedToBit: 64162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerTruncateTaggedToBit(node); 642f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch break; 64313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case IrOpcode::kTruncateTaggedToFloat64: 64462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerTruncateTaggedToFloat64(node); 64513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 64613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case IrOpcode::kCheckBounds: 64762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckBounds(node, frame_state); 64813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 649f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kCheckMaps: 65062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckMaps(node, frame_state); 651f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 652f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kCheckNumber: 65362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckNumber(node, frame_state); 65462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 65562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case IrOpcode::kCheckReceiver: 65662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckReceiver(node, frame_state); 657f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 658f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kCheckString: 65962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckString(node, frame_state); 66062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 66162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case IrOpcode::kCheckInternalizedString: 66262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckInternalizedString(node, frame_state); 663f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 664f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kCheckIf: 66562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckIf(node, frame_state); 666f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 66713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case IrOpcode::kCheckedInt32Add: 66862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckedInt32Add(node, frame_state); 66913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 67013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case IrOpcode::kCheckedInt32Sub: 67162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckedInt32Sub(node, frame_state); 67213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 673f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kCheckedInt32Div: 67462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckedInt32Div(node, frame_state); 675f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 676f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kCheckedInt32Mod: 67762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckedInt32Mod(node, frame_state); 678f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 679f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kCheckedUint32Div: 68062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckedUint32Div(node, frame_state); 681f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 682f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kCheckedUint32Mod: 68362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckedUint32Mod(node, frame_state); 684f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 685f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kCheckedInt32Mul: 68662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckedInt32Mul(node, frame_state); 687f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 688f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case IrOpcode::kCheckedInt32ToTaggedSigned: 68962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckedInt32ToTaggedSigned(node, frame_state); 690f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch break; 69113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case IrOpcode::kCheckedUint32ToInt32: 69262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckedUint32ToInt32(node, frame_state); 69313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 694f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case IrOpcode::kCheckedUint32ToTaggedSigned: 69562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckedUint32ToTaggedSigned(node, frame_state); 696f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch break; 69713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case IrOpcode::kCheckedFloat64ToInt32: 69862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckedFloat64ToInt32(node, frame_state); 69913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 700f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kCheckedTaggedSignedToInt32: 70162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckedTaggedSignedToInt32(node, frame_state); 702f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 70313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case IrOpcode::kCheckedTaggedToInt32: 70462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckedTaggedToInt32(node, frame_state); 70513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 70613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case IrOpcode::kCheckedTaggedToFloat64: 70762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckedTaggedToFloat64(node, frame_state); 70813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 709f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case IrOpcode::kCheckedTaggedToTaggedSigned: 71062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckedTaggedToTaggedSigned(node, frame_state); 711f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch break; 712c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case IrOpcode::kCheckedTaggedToTaggedPointer: 71362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckedTaggedToTaggedPointer(node, frame_state); 714c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 715bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case IrOpcode::kTruncateTaggedToWord32: 71662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerTruncateTaggedToWord32(node); 717bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 718f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kCheckedTruncateTaggedToWord32: 71962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckedTruncateTaggedToWord32(node, frame_state); 72062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 72162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case IrOpcode::kObjectIsDetectableCallable: 72262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerObjectIsDetectableCallable(node); 723f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 72462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case IrOpcode::kObjectIsNonCallable: 72562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerObjectIsNonCallable(node); 726bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 727bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case IrOpcode::kObjectIsNumber: 72862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerObjectIsNumber(node); 729bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 730bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case IrOpcode::kObjectIsReceiver: 73162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerObjectIsReceiver(node); 732bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 733bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case IrOpcode::kObjectIsSmi: 73462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerObjectIsSmi(node); 735bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 736bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case IrOpcode::kObjectIsString: 73762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerObjectIsString(node); 738bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 739bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch case IrOpcode::kObjectIsUndetectable: 74062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerObjectIsUndetectable(node); 74162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 74262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case IrOpcode::kNewRestParameterElements: 74362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerNewRestParameterElements(node); 74462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 74562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case IrOpcode::kNewUnmappedArgumentsElements: 74662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerNewUnmappedArgumentsElements(node); 747bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch break; 748f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case IrOpcode::kArrayBufferWasNeutered: 74962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerArrayBufferWasNeutered(node); 750f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch break; 75113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case IrOpcode::kStringFromCharCode: 75262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerStringFromCharCode(node); 75313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 754f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case IrOpcode::kStringFromCodePoint: 75562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerStringFromCodePoint(node); 75662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 75762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case IrOpcode::kStringIndexOf: 75862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerStringIndexOf(node); 75962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 76062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case IrOpcode::kStringCharAt: 76162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerStringCharAt(node); 762f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch break; 763f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kStringCharCodeAt: 76462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerStringCharCodeAt(node); 765f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 766f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case IrOpcode::kStringEqual: 76762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerStringEqual(node); 768f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch break; 769f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case IrOpcode::kStringLessThan: 77062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerStringLessThan(node); 771f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch break; 772f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case IrOpcode::kStringLessThanOrEqual: 77362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerStringLessThanOrEqual(node); 774f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch break; 77513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case IrOpcode::kCheckFloat64Hole: 77662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckFloat64Hole(node, frame_state); 77713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 77813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case IrOpcode::kCheckTaggedHole: 77962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerCheckTaggedHole(node, frame_state); 78013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 781f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kConvertTaggedHoleToUndefined: 78262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerConvertTaggedHoleToUndefined(node); 783f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 78413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case IrOpcode::kPlainPrimitiveToNumber: 78562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerPlainPrimitiveToNumber(node); 78613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 78713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case IrOpcode::kPlainPrimitiveToWord32: 78862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerPlainPrimitiveToWord32(node); 78913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 79013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch case IrOpcode::kPlainPrimitiveToFloat64: 79162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerPlainPrimitiveToFloat64(node); 79213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch break; 793f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kEnsureWritableFastElements: 79462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerEnsureWritableFastElements(node); 795f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 796f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kMaybeGrowFastElements: 79762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerMaybeGrowFastElements(node, frame_state); 798f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 799f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kTransitionElementsKind: 80062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LowerTransitionElementsKind(node); 801f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 802f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kLoadTypedElement: 80362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result = LowerLoadTypedElement(node); 804f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 805f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kStoreTypedElement: 80662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LowerStoreTypedElement(node); 807f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 808f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kFloat64RoundUp: 80962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!LowerFloat64RoundUp(node).To(&result)) { 81062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return false; 81162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 812f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 813f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kFloat64RoundDown: 81462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!LowerFloat64RoundDown(node).To(&result)) { 81562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return false; 81662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 817f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 818f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case IrOpcode::kFloat64RoundTruncate: 81962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!LowerFloat64RoundTruncate(node).To(&result)) { 82062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return false; 82162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 822f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 823c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case IrOpcode::kFloat64RoundTiesEven: 82462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!LowerFloat64RoundTiesEven(node).To(&result)) { 82562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return false; 82662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 827c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch break; 828bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch default: 829bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return false; 830bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 83162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch *effect = gasm()->ExtractCurrentEffect(); 83262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch *control = gasm()->ExtractCurrentControl(); 83362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch NodeProperties::ReplaceUses(node, result, *effect, *control); 834bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return true; 835bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 836bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 83762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define __ gasm()-> 83862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 83962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node) { 840bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value = node->InputAt(0); 84162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return AllocateHeapNumberWithValue(value); 842bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 843bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 84462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeFloat64ToTaggedPointer(Node* node) { 845c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* value = node->InputAt(0); 84662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return AllocateHeapNumberWithValue(value); 847c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 848c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 84962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeBitToTagged(Node* node) { 850bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value = node->InputAt(0); 851bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 85262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_true = __ MakeLabel<1>(); 85362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); 854bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 85562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(value, &if_true); 85662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ FalseConstant()); 857bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 85862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_true); 85962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ TrueConstant()); 860bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 86162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 86262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 863bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 864bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 86562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeInt31ToTaggedSigned(Node* node) { 866bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value = node->InputAt(0); 86762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return ChangeInt32ToSmi(value); 868bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 869bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 87062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeInt32ToTagged(Node* node) { 871bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value = node->InputAt(0); 872bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 873bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (machine()->Is64()) { 87462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return ChangeInt32ToSmi(value); 875bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 876bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 87762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_overflow = __ MakeDeferredLabel<1>(); 87862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); 879bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 88062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* add = __ Int32AddWithOverflow(value, value); 88162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* ovf = __ Projection(1, add); 88262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(ovf, &if_overflow); 88362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Projection(0, add)); 884bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 88562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_overflow); 88662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* number = AllocateHeapNumberWithValue(__ ChangeInt32ToFloat64(value)); 88762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, number); 888bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 88962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 89062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 891bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 892bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 89362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeUint32ToTagged(Node* node) { 894bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value = node->InputAt(0); 895bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 89662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_in_smi_range = __ MakeDeferredLabel<1>(); 89762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); 898bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 89962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ Uint32LessThanOrEqual(value, SmiMaxValueConstant()); 90062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check, &if_not_in_smi_range); 90162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, ChangeUint32ToSmi(value)); 902bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 90362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_in_smi_range); 90462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* number = AllocateHeapNumberWithValue(__ ChangeUint32ToFloat64(value)); 905bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 90662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, number); 90762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 908bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 90962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 910bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 911bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 91262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeTaggedSignedToInt32(Node* node) { 913bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value = node->InputAt(0); 91462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return ChangeSmiToInt32(value); 915bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 916bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 91762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeTaggedToBit(Node* node) { 918bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value = node->InputAt(0); 91962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ WordEqual(value, __ TrueConstant()); 920bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 921bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 92262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerTruncateTaggedToBit(Node* node) { 923f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* value = node->InputAt(0); 924f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 92562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_smi = __ MakeDeferredLabel<1>(); 92662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_heapnumber = __ MakeDeferredLabel<1>(); 92762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<6>(MachineRepresentation::kBit); 92862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 92962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* zero = __ Int32Constant(0); 93062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* fzero = __ Float64Constant(0.0); 93162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 93262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check if {value} is false. 93362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(__ WordEqual(value, __ FalseConstant()), &done, zero); 934f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 935f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check if {value} is a Smi. 936f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* check_smi = ObjectIsSmi(value); 93762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check_smi, &if_smi); 938f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 93962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check if {value} is the empty string. 94062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(__ WordEqual(value, __ EmptyStringConstant()), &done, zero); 94162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 94262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Load the map of {value}. 94362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 94462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 94562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check if the {value} is undetectable and immediately return false. 94662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map_bitfield = 94762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadField(AccessBuilder::ForMapBitField(), value_map); 94862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless( 94962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Word32Equal(__ Word32And(value_map_bitfield, 95062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant(1 << Map::kIsUndetectable)), 95162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch zero), 95262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &done, zero); 953f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 954f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check if {value} is a HeapNumber. 95562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(__ WordEqual(value_map, __ HeapNumberMapConstant()), 95662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &if_heapnumber); 95762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 95862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // All other values that reach here are true. 95962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Int32Constant(1)); 96062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 96162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_heapnumber); 962f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 96362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // For HeapNumber {value}, just check that its value is not 0.0, -0.0 or 96462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // NaN. 96562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_value = 96662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 96762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Float64LessThan(fzero, __ Float64Abs(value_value))); 968f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 969f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 97062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_smi); 971f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 97262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // If {value} is a Smi, then we only need to check that it's not zero. 97362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, 97462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Word32Equal(__ WordEqual(value, __ IntPtrConstant(0)), zero)); 975f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 976f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 97762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 97862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 979f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 980f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 98162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeTaggedToInt32(Node* node) { 982bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value = node->InputAt(0); 983bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 98462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_smi = __ MakeDeferredLabel<1>(); 98562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kWord32); 986bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 98762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = ObjectIsSmi(value); 98862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check, &if_not_smi); 98962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, ChangeSmiToInt32(value)); 990bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 99162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_smi); 99262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); 99362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 99462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch vfalse = __ ChangeFloat64ToInt32(vfalse); 99562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, vfalse); 996bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 99762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 99862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 999bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1000bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 100162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeTaggedToUint32(Node* node) { 1002bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value = node->InputAt(0); 1003bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 100462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_smi = __ MakeDeferredLabel<1>(); 100562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kWord32); 1006bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 100762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = ObjectIsSmi(value); 100862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check, &if_not_smi); 100962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, ChangeSmiToInt32(value)); 1010bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 101162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_smi); 101262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); 101362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 101462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch vfalse = __ ChangeFloat64ToUint32(vfalse); 101562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, vfalse); 1016bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 101762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 101862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 1019bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1020bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 102162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeTaggedToFloat64(Node* node) { 102262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return LowerTruncateTaggedToFloat64(node); 102313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 102413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 102562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeTaggedToTaggedSigned(Node* node) { 1026bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value = node->InputAt(0); 1027bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 102862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_smi = __ MakeDeferredLabel<1>(); 102962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kWord32); 103062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 1031bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* check = ObjectIsSmi(value); 103262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check, &if_not_smi); 103362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, value); 1034bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 103562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_smi); 103662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); 103762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 103862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch vfalse = __ ChangeFloat64ToInt32(vfalse); 103962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch vfalse = ChangeInt32ToSmi(vfalse); 104062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, vfalse); 1041bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 104262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 104362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 104462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 104562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 104662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerTruncateTaggedToFloat64(Node* node) { 104762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value = node->InputAt(0); 1048bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 104962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_smi = __ MakeDeferredLabel<1>(); 105062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kFloat64); 1051bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 105262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = ObjectIsSmi(value); 105362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check, &if_not_smi); 105462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* vtrue = ChangeSmiToInt32(value); 105562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch vtrue = __ ChangeInt32ToFloat64(vtrue); 105662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, vtrue); 105762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 105862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_smi); 105962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); 106062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 106162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, vfalse); 106262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 106362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 106462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 1065bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1066bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 106762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckBounds(Node* node, Node* frame_state) { 106813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* index = node->InputAt(0); 106913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* limit = node->InputAt(1); 107013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 107162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ Uint32LessThan(index, limit); 107262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeReason::kOutOfBounds, check, frame_state); 107362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return index; 107413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 107513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 107662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) { 107762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CheckMapsParameters const& p = CheckMapsParametersOf(node->op()); 1078f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* value = node->InputAt(0); 1079f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 108062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ZoneHandleSet<Map> const& maps = p.maps(); 108162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch size_t const map_count = maps.size(); 1082f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 108362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (p.flags() & CheckMapsFlag::kTryMigrateInstance) { 108462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = 108562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, map_count * 2); 108662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto migrate = __ MakeDeferredLabel<1>(); 1087f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 108862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Load the current map of the {value}. 108962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 1090f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 109162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Perform the map checks. 109262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch for (size_t i = 0; i < map_count; ++i) { 109362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* map = __ HeapConstant(maps[i]); 109462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ WordEqual(value_map, map); 109562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (i == map_count - 1) { 109662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check, &migrate); 109762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done); 109862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 109962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check, &done); 110062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 1101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1102f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 110362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Perform the (deferred) instance migration. 110462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&migrate); 110562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 110662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // If map is not deprecated the migration attempt does not make sense. 110762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* bitfield3 = 110862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadField(AccessBuilder::ForMapBitField3(), value_map); 110962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* if_not_deprecated = __ WordEqual( 111062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Word32And(bitfield3, __ Int32Constant(Map::Deprecated::kMask)), 111162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant(0)); 111262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kWrongMap, if_not_deprecated, 111362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch frame_state); 111462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 111562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; 111662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Runtime::FunctionId id = Runtime::kTryMigrateInstance; 111762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor( 111862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags); 111962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* result = 112062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Call(desc, __ CEntryStubConstant(1), value, 112162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ ExternalConstant(ExternalReference(id, isolate())), 112262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant(1), __ NoContextConstant()); 112362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = ObjectIsSmi(result); 112462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kInstanceMigrationFailed, check, 112562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch frame_state); 112662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 1127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 112862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Reload the current map of the {value}. 112962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch value_map = __ LoadField(AccessBuilder::ForMap(), value); 1130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 113162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Perform the map checks again. 113262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch for (size_t i = 0; i < map_count; ++i) { 113362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* map = __ HeapConstant(maps[i]); 113462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ WordEqual(value_map, map); 113562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (i == map_count - 1) { 113662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeReason::kWrongMap, check, frame_state); 113762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 113862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check, &done); 113962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 114062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 1141f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 114262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done); 114362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 114462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 114562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = 114662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, map_count); 1147f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 114862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Load the current map of the {value}. 114962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 1150f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 115162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch for (size_t i = 0; i < map_count; ++i) { 115262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* map = __ HeapConstant(maps[i]); 115362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ WordEqual(value_map, map); 115462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (i == map_count - 1) { 115562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeReason::kWrongMap, check, frame_state); 115662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 115762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check, &done); 115862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 115962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 116062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done); 116162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 1162f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 116362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return value; 1164f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 116662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckNumber(Node* node, Node* frame_state) { 1167f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* value = node->InputAt(0); 1168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 116962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_smi = __ MakeDeferredLabel<1>(); 117062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(); 117162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 1172f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* check0 = ObjectIsSmi(value); 117362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check0, &if_not_smi); 117462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done); 117562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 117662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_smi); 117762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 117862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check1 = __ WordEqual(value_map, __ HeapNumberMapConstant()); 117962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber, check1, frame_state); 118062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done); 1181f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 118262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 118362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return value; 118462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 118562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 118662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckReceiver(Node* node, 118762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* frame_state) { 118862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value = node->InputAt(0); 1189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 119062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 119162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_instance_type = 119262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 1193f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 119462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 119562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ Uint32LessThanOrEqual( 119662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type); 119762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeReason::kNotAJavaScriptObject, check, 119862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch frame_state); 119962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return value; 1200f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1201f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 120262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckString(Node* node, Node* frame_state) { 1203f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* value = node->InputAt(0); 1204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 120562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 120662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_instance_type = 120762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 1208f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 120962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ Uint32LessThan(value_instance_type, 121062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Uint32Constant(FIRST_NONSTRING_TYPE)); 121162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeReason::kWrongInstanceType, check, frame_state); 121262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return value; 1213f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1214f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 121562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckInternalizedString(Node* node, 121662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* frame_state) { 121762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value = node->InputAt(0); 121813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 121962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 122062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_instance_type = 122162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 122213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 122362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ Word32Equal( 122462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Word32And(value_instance_type, 122562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant(kIsNotStringMask | kIsNotInternalizedMask)), 122662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant(kInternalizedTag)); 122762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeReason::kWrongInstanceType, check, frame_state); 122813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 122962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return value; 123062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 123113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 123262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckIf(Node* node, Node* frame_state) { 123362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value = node->InputAt(0); 123462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeKind::kEager, DeoptimizeReason::kNoReason, 123562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch value, frame_state); 123662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return value; 123713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 123813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 123962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedInt32Add(Node* node, 124062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* frame_state) { 124113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* lhs = node->InputAt(0); 124213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* rhs = node->InputAt(1); 124313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 124462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value = __ Int32AddWithOverflow(lhs, rhs); 124562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ Projection(1, value); 124662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state); 124762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ Projection(0, value); 124862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 124913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 125062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedInt32Sub(Node* node, 125162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* frame_state) { 125262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* lhs = node->InputAt(0); 125362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* rhs = node->InputAt(1); 125413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 125562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value = __ Int32SubWithOverflow(lhs, rhs); 125662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ Projection(1, value); 125762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state); 125862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ Projection(0, value); 125913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 126013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 126162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedInt32Div(Node* node, 126262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* frame_state) { 1263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* lhs = node->InputAt(0); 1264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* rhs = node->InputAt(1); 126513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 126662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_positive = __ MakeDeferredLabel<1>(); 126762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_is_minint = __ MakeDeferredLabel<1>(); 126862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kWord32); 126962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto minint_check_done = __ MakeLabel<2>(); 127062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 127162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* zero = __ Int32Constant(0); 127262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 1273f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if {rhs} is positive (and not zero). 127462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check0 = __ Int32LessThan(zero, rhs); 127562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check0, &if_not_positive); 127613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 127762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Fast case, no additional checking required. 127862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Int32Div(lhs, rhs)); 1279f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1280f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 128162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_positive); 128262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 1283f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if {rhs} is zero. 128462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ Word32Equal(rhs, zero); 128562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state); 1286f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1287f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if {lhs} is zero, as that would produce minus zero. 128862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch check = __ Word32Equal(lhs, zero); 128962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check, frame_state); 1290f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1291f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if {lhs} is kMinInt and {rhs} is -1, in which case we'd have 1292f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // to return -kMinInt, which is not representable. 129362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* minint = __ Int32Constant(std::numeric_limits<int32_t>::min()); 1294f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* check1 = graph()->NewNode(machine()->Word32Equal(), lhs, minint); 129562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check1, &if_is_minint); 129662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&minint_check_done); 129713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 129862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_is_minint); 129962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check if {rhs} is -1. 130062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* minusone = __ Int32Constant(-1); 130162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* is_minus_one = __ Word32Equal(rhs, minusone); 130262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kOverflow, is_minus_one, frame_state); 130362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&minint_check_done); 130413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 130562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&minint_check_done); 1306f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Perform the actual integer division. 130762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Int32Div(lhs, rhs)); 1308f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 130913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 131062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 131162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value = done.PhiAt(0); 131213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 1313f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if the remainder is non-zero. 131462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ Word32Equal(lhs, __ Int32Mul(rhs, value)); 131562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, check, frame_state); 131613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 131762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return value; 131813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 131913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 132062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedInt32Mod(Node* node, 132162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* frame_state) { 1322f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // General case for signed integer modulus, with optimization for (unknown) 1323f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // power of 2 right hand side. 1324f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 1325f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // if rhs <= 0 then 1326f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // rhs = -rhs 1327f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // deopt if rhs == 0 1328f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // if lhs < 0 then 1329f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // let res = lhs % rhs in 1330f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // deopt if res == 0 1331f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // res 1332f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // else 1333f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // let msk = rhs - 1 in 1334f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // if rhs & msk == 0 then 1335f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // lhs & msk 1336f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // else 1337f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // lhs % rhs 1338f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 1339f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* lhs = node->InputAt(0); 1340f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* rhs = node->InputAt(1); 134113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 134262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_rhs_not_positive = __ MakeDeferredLabel<1>(); 134362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_lhs_negative = __ MakeDeferredLabel<1>(); 134462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_power_of_two = __ MakeLabel<1>(); 134562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto rhs_checked = __ MakeLabel<2>(MachineRepresentation::kWord32); 134662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<3>(MachineRepresentation::kWord32); 134762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 134862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* zero = __ Int32Constant(0); 134962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 1350f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if {rhs} is not strictly positive. 135162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check0 = __ Int32LessThanOrEqual(rhs, zero); 135262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check0, &if_rhs_not_positive); 135362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&rhs_checked, rhs); 135413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 135562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_rhs_not_positive); 1356f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 1357f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Negate {rhs}, might still produce a negative result in case of 1358f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -2^31, but that is handled safely below. 135962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* vtrue0 = __ Int32Sub(zero, rhs); 1360f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1361f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Ensure that {rhs} is not zero, otherwise we'd have to return NaN. 136262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ Word32Equal(vtrue0, zero); 136362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state); 136462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&rhs_checked, vtrue0); 1365f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 136613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 136762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&rhs_checked); 136862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch rhs = rhs_checked.PhiAt(0); 136913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 1370f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if {lhs} is negative. 137162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check1 = __ Int32LessThan(lhs, zero); 137262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check1, &if_lhs_negative); 137313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 137462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // {lhs} non-negative. 1375f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 137662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* one = __ Int32Constant(1); 137762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* msk = __ Int32Sub(rhs, one); 1378f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1379f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if {rhs} minus one is a valid mask. 138062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check2 = __ Word32Equal(__ Word32And(rhs, msk), zero); 138162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check2, &if_power_of_two); 138262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Compute the remainder using the generic {lhs % rhs}. 138362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Int32Mod(lhs, rhs)); 1384f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 138562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_power_of_two); 1386f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Compute the remainder using {lhs & msk}. 138762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Word32And(lhs, msk)); 138862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 1389f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 139062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_lhs_negative); 139162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 139262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Compute the remainder using {lhs % msk}. 139362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* vtrue1 = __ Int32Mod(lhs, rhs); 139413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 139562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check if we would have to return -0. 139662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ Word32Equal(vtrue1, zero); 139762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check, frame_state); 139862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, vtrue1); 1399f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1400f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 140162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 140262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 140313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 140413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 140562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedUint32Div(Node* node, 140662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* frame_state) { 1407f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* lhs = node->InputAt(0); 1408f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* rhs = node->InputAt(1); 140913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 141062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* zero = __ Int32Constant(0); 141162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 1412f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Ensure that {rhs} is not zero, otherwise we'd have to return NaN. 141362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ Word32Equal(rhs, zero); 141462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state); 141513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 1416f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Perform the actual unsigned integer division. 141762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value = __ Uint32Div(lhs, rhs); 1418f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1419f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if the remainder is non-zero. 142062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch check = __ Word32Equal(lhs, __ Int32Mul(rhs, value)); 142162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, check, frame_state); 142262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return value; 1423f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1424f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 142562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedUint32Mod(Node* node, 142662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* frame_state) { 1427f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* lhs = node->InputAt(0); 1428f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* rhs = node->InputAt(1); 1429f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 143062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* zero = __ Int32Constant(0); 143162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 1432f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Ensure that {rhs} is not zero, otherwise we'd have to return NaN. 143362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ Word32Equal(rhs, zero); 143462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state); 1435f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1436f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Perform the actual unsigned integer modulus. 143762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ Uint32Mod(lhs, rhs); 1438f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1439f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 144062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedInt32Mul(Node* node, 144162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* frame_state) { 1442f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op()); 1443f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* lhs = node->InputAt(0); 1444f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* rhs = node->InputAt(1); 1445f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 144662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* projection = __ Int32MulWithOverflow(lhs, rhs); 144762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ Projection(1, projection); 144862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state); 1449f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 145062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value = __ Projection(0, projection); 1451f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1452f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (mode == CheckForMinusZeroMode::kCheckForMinusZero) { 145362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_zero = __ MakeDeferredLabel<1>(); 145462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto check_done = __ MakeLabel<2>(); 145562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* zero = __ Int32Constant(0); 145662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check_zero = __ Word32Equal(value, zero); 145762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check_zero, &if_zero); 145862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&check_done); 1459f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 146062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_zero); 146162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // We may need to return negative zero. 146262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check_or = __ Int32LessThan(__ Word32Or(lhs, rhs), zero); 146362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check_or, frame_state); 146462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&check_done); 1465f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 146662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&check_done); 1467f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1468f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 146962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return value; 1470f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1471f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 147262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedInt32ToTaggedSigned( 147362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* node, Node* frame_state) { 1474f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK(SmiValuesAre31Bits()); 1475f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* value = node->InputAt(0); 1476f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 147762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* add = __ Int32AddWithOverflow(value, value); 147862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ Projection(1, add); 147962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state); 148062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ Projection(0, add); 1481f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 1482f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 148362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node, 148462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* frame_state) { 1485f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* value = node->InputAt(0); 148662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* max_int = __ Int32Constant(std::numeric_limits<int32_t>::max()); 148762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* is_safe = __ Uint32LessThanOrEqual(value, max_int); 148862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, is_safe, frame_state); 148962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return value; 1490f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1491f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 149262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedUint32ToTaggedSigned( 149362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* node, Node* frame_state) { 1494f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* value = node->InputAt(0); 149562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ Uint32LessThanOrEqual(value, SmiMaxValueConstant()); 149662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, check, frame_state); 149762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return ChangeUint32ToSmi(value); 149862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 149962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 150062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::BuildCheckedFloat64ToInt32( 150162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CheckForMinusZeroMode mode, Node* value, Node* frame_state) { 150262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value32 = __ RoundFloat64ToInt32(value); 150362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check_same = __ Float64Equal(value, __ ChangeInt32ToFloat64(value32)); 150462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeReason::kLostPrecisionOrNaN, check_same, 150562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch frame_state); 1506f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1507f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (mode == CheckForMinusZeroMode::kCheckForMinusZero) { 1508f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if {value} is -0. 150962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_zero = __ MakeDeferredLabel<1>(); 151062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto check_done = __ MakeLabel<2>(); 1511f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 151262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check_zero = __ Word32Equal(value32, __ Int32Constant(0)); 151362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check_zero, &if_zero); 151462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&check_done); 1515f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 151662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_zero); 1517f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // In case of 0, we need to check the high bits for the IEEE -0 pattern. 151862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check_negative = __ Int32LessThan(__ Float64ExtractHighWord32(value), 151962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant(0)); 152062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check_negative, frame_state); 152162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&check_done); 1522f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 152362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&check_done); 152462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 152562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return value32; 1526f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1527f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 152862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node, 152962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* frame_state) { 1530f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op()); 1531f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* value = node->InputAt(0); 153262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return BuildCheckedFloat64ToInt32(mode, value, frame_state); 1533f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1534f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 153562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedTaggedSignedToInt32( 153662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* node, Node* frame_state) { 1537f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* value = node->InputAt(0); 1538f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* check = ObjectIsSmi(value); 153962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeReason::kNotASmi, check, frame_state); 154062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return ChangeSmiToInt32(value); 1541f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1542f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 154362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node, 154462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* frame_state) { 1545f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op()); 1546f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* value = node->InputAt(0); 1547f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 154862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_smi = __ MakeDeferredLabel<1>(); 154962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kWord32); 1550f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 155162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = ObjectIsSmi(value); 155262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check, &if_not_smi); 1553f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // In the Smi case, just convert to int32. 155462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, ChangeSmiToInt32(value)); 1555f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1556f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // In the non-Smi case, check the heap numberness, load the number and convert 1557f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // to int32. 155862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_smi); 155962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 156062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check_map = __ WordEqual(value_map, __ HeapNumberMapConstant()); 156162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber, check_map, 156262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch frame_state); 156362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 156462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch vfalse = BuildCheckedFloat64ToInt32(mode, vfalse, frame_state); 156562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, vfalse); 156662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 156762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 156862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 156962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 157062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 157162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::BuildCheckedHeapNumberOrOddballToFloat64( 157262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CheckTaggedInputMode mode, Node* value, Node* frame_state) { 157362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 157462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check_number = __ WordEqual(value_map, __ HeapNumberMapConstant()); 1575f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch switch (mode) { 1576f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case CheckTaggedInputMode::kNumber: { 157762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber, check_number, 157862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch frame_state); 1579f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1580f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1581f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case CheckTaggedInputMode::kNumberOrOddball: { 158262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto check_done = __ MakeLabel<2>(); 1583f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 158462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check_number, &check_done); 1585f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // For oddballs also contain the numeric value, let us just check that 1586f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // we have an oddball here. 158762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* instance_type = 158862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 1589f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* check_oddball = 159062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Word32Equal(instance_type, __ Int32Constant(ODDBALL_TYPE)); 159162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeReason::kNotANumberOrOddball, check_oddball, 159262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch frame_state); 1593f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); 159462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&check_done); 1595f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 159662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&check_done); 1597f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1598f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1599f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 160062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 160113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 160213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 160362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node, 160462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* frame_state) { 1605f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CheckTaggedInputMode mode = CheckTaggedInputModeOf(node->op()); 160613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* value = node->InputAt(0); 160713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 160862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_smi = __ MakeLabel<1>(); 160962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kFloat64); 161062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 161113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* check = ObjectIsSmi(value); 161262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check, &if_smi); 161313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 161413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // In the Smi case, just convert to int32 and then float64. 161513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Otherwise, check heap numberness and load the number. 161662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* number = 161762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch BuildCheckedHeapNumberOrOddballToFloat64(mode, value, frame_state); 161862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, number); 1619f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 162062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_smi); 162162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* from_smi = ChangeSmiToInt32(value); 162262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch from_smi = __ ChangeInt32ToFloat64(from_smi); 162362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, from_smi); 1624f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 162562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 162662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 1627f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 1628f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 162962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedTaggedToTaggedSigned( 163062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* node, Node* frame_state) { 1631c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* value = node->InputAt(0); 1632c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1633c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* check = ObjectIsSmi(value); 163462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeReason::kNotASmi, check, frame_state); 1635c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 163662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return value; 1637c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1638c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 163962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedTaggedToTaggedPointer( 164062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* node, Node* frame_state) { 1641bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value = node->InputAt(0); 1642bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1643bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* check = ObjectIsSmi(value); 164462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kSmi, check, frame_state); 164562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return value; 164662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 1647bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 164862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerTruncateTaggedToWord32(Node* node) { 164962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value = node->InputAt(0); 1650bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 165162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_smi = __ MakeDeferredLabel<1>(); 165262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kWord32); 165362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 165462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = ObjectIsSmi(value); 165562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check, &if_not_smi); 165662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, ChangeSmiToInt32(value)); 1657bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 165862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_smi); 165962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); 166062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 166162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch vfalse = __ TruncateFloat64ToWord32(vfalse); 166262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, vfalse); 1663bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 166462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 166562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 1666bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1667bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 166862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedTruncateTaggedToWord32( 166962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* node, Node* frame_state) { 1670f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* value = node->InputAt(0); 1671f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 167262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_smi = __ MakeLabel<1>(); 167362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kWord32); 1674f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 167562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = ObjectIsSmi(value); 167662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check, &if_not_smi); 1677f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // In the Smi case, just convert to int32. 167862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, ChangeSmiToInt32(value)); 1679f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1680f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Otherwise, check that it's a heap number or oddball and truncate the value 1681f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // to int32. 168262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_smi); 168362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* number = BuildCheckedHeapNumberOrOddballToFloat64( 168462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CheckTaggedInputMode::kNumberOrOddball, value, frame_state); 168562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch number = __ TruncateFloat64ToWord32(number); 168662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, number); 168762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 168862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 168962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 169062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 169162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 169262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerObjectIsDetectableCallable(Node* node) { 1693bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value = node->InputAt(0); 1694bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 169562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_smi = __ MakeDeferredLabel<1>(); 169662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kBit); 169762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 1698bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* check = ObjectIsSmi(value); 169962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check, &if_smi); 1700bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 170162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 170262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_bit_field = 170362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadField(AccessBuilder::ForMapBitField(), value_map); 170462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* vfalse = __ Word32Equal( 170562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant(1 << Map::kIsCallable), 170662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Word32And(value_bit_field, 170762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant((1 << Map::kIsCallable) | 170862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch (1 << Map::kIsUndetectable)))); 170962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, vfalse); 1710bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 171162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_smi); 171262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Int32Constant(0)); 1713bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 171462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 171562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 1716bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1717bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 171862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerObjectIsNonCallable(Node* node) { 1719bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value = node->InputAt(0); 1720bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 172162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_primitive = __ MakeDeferredLabel<2>(); 172262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kBit); 172362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 172462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check0 = ObjectIsSmi(value); 172562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check0, &if_primitive); 1726bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 172762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 172862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_instance_type = 172962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 173062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 173162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check1 = __ Uint32LessThanOrEqual( 173262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type); 173362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check1, &if_primitive); 1734bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 173562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_bit_field = 173662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadField(AccessBuilder::ForMapBitField(), value_map); 173762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check2 = __ Word32Equal( 173862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant(0), 173962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Word32And(value_bit_field, __ Int32Constant(1 << Map::kIsCallable))); 174062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, check2); 1741bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 174262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_primitive); 174362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Int32Constant(0)); 1744bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 174562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 174662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 1747bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1748bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 174962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerObjectIsNumber(Node* node) { 1750bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value = node->InputAt(0); 1751bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 175262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_smi = __ MakeLabel<1>(); 175362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kBit); 1754bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 175562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(ObjectIsSmi(value), &if_smi); 175662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 175762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ WordEqual(value_map, __ HeapNumberMapConstant())); 1758bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 175962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_smi); 176062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Int32Constant(1)); 1761bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 176262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 176362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 1764bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1765bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 176662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerObjectIsReceiver(Node* node) { 1767bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value = node->InputAt(0); 1768bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 176962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_smi = __ MakeDeferredLabel<1>(); 177062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kBit); 1771bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 177262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(ObjectIsSmi(value), &if_smi); 1773bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 177462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 177562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 177662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_instance_type = 177762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 177862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* result = __ Uint32LessThanOrEqual( 177962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type); 178062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, result); 1781bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 178262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_smi); 178362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Int32Constant(0)); 1784bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 178562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 178662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 1787bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1788bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 178962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerObjectIsSmi(Node* node) { 1790bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Node* value = node->InputAt(0); 179162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return ObjectIsSmi(value); 179262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 1793bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 179462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerObjectIsString(Node* node) { 179562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value = node->InputAt(0); 1796bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 179762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_smi = __ MakeDeferredLabel<1>(); 179862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kBit); 1799bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 180062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = ObjectIsSmi(value); 180162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check, &if_smi); 180262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 180362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_instance_type = 180462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 180562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* vfalse = __ Uint32LessThan(value_instance_type, 180662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Uint32Constant(FIRST_NONSTRING_TYPE)); 180762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, vfalse); 1808bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 180962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_smi); 181062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Int32Constant(0)); 1811bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 181262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 181362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 1814bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1815bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 181662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerObjectIsUndetectable(Node* node) { 1817f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* value = node->InputAt(0); 1818f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 181962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_smi = __ MakeDeferredLabel<1>(); 182062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kBit); 1821f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 182262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = ObjectIsSmi(value); 182362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check, &if_smi); 1824f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 182562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 182662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_bit_field = 182762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadField(AccessBuilder::ForMapBitField(), value_map); 182862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* vfalse = __ Word32Equal( 182962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Word32Equal(__ Int32Constant(0), 183062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Word32And(value_bit_field, 183162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant(1 << Map::kIsUndetectable))), 183262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant(0)); 183362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, vfalse); 1834f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 183562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_smi); 183662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Int32Constant(0)); 1837f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 183862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 183962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 184062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 1841f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 184262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerNewRestParameterElements(Node* node) { 184362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int const formal_parameter_count = ParameterCountOf(node->op()); 1844f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 184562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Callable const callable = CodeFactory::NewRestParameterElements(isolate()); 184662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Operator::Properties const properties = node->op()->properties(); 184762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallDescriptor::Flags const flags = CallDescriptor::kNoFlags; 184862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallDescriptor* desc = Linkage::GetStubCallDescriptor( 184962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); 185062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ Call(desc, __ HeapConstant(callable.code()), 185162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ IntPtrConstant(formal_parameter_count), 185262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ NoContextConstant()); 185362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 1854f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 185562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerNewUnmappedArgumentsElements(Node* node) { 185662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int const formal_parameter_count = ParameterCountOf(node->op()); 1857f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 185862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Callable const callable = 185962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CodeFactory::NewUnmappedArgumentsElements(isolate()); 186062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Operator::Properties const properties = node->op()->properties(); 186162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallDescriptor::Flags const flags = CallDescriptor::kNoFlags; 186262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallDescriptor* desc = Linkage::GetStubCallDescriptor( 186362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); 186462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ Call(desc, __ HeapConstant(callable.code()), 186562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ IntPtrConstant(formal_parameter_count), 186662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ NoContextConstant()); 186762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 1868f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 186962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerArrayBufferWasNeutered(Node* node) { 187062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value = node->InputAt(0); 1871f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 187262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value_bit_field = 187362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadField(AccessBuilder::ForJSArrayBufferBitField(), value); 187462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ Word32Equal( 187562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Word32Equal( 187662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Word32And(value_bit_field, 187762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant(JSArrayBuffer::WasNeutered::kMask)), 187862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant(0)), 187962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant(0)); 188062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 1881f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 188262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerStringCharAt(Node* node) { 188362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* receiver = node->InputAt(0); 188462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* position = node->InputAt(1); 1885f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 188662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Callable const callable = CodeFactory::StringCharAt(isolate()); 188762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite; 188862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 188962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallDescriptor* desc = Linkage::GetStubCallDescriptor( 189062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); 189162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ Call(desc, __ HeapConstant(callable.code()), receiver, position, 189262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ NoContextConstant()); 1893f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1894f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 189562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerStringCharCodeAt(Node* node) { 189662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* receiver = node->InputAt(0); 189762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* position = node->InputAt(1); 189862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 189962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Callable const callable = CodeFactory::StringCharCodeAt(isolate()); 190062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite; 190162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 190262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallDescriptor* desc = Linkage::GetStubCallDescriptor( 190362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties, 190462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MachineType::TaggedSigned()); 190562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ Call(desc, __ HeapConstant(callable.code()), receiver, position, 190662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ NoContextConstant()); 190762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 190862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 190962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerStringFromCharCode(Node* node) { 191013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* value = node->InputAt(0); 191113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 191262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto runtime_call = __ MakeDeferredLabel<2>(); 191362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_undefined = __ MakeDeferredLabel<1>(); 191462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); 191562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 191613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Compute the character code. 191762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* code = __ Word32And(value, __ Int32Constant(String::kMaxUtf16CodeUnit)); 191813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 191913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Check if the {code} is a one-byte char code. 192062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check0 = __ Int32LessThanOrEqual( 192162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch code, __ Int32Constant(String::kMaxOneByteCharCode)); 192262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check0, &runtime_call); 192313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 1924c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load the isolate wide single character string cache. 192562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* cache = __ HeapConstant(factory()->single_character_string_cache()); 192613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 1927c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Compute the {cache} index for {code}. 192862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code); 192913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 1930c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Check if we have an entry for the {code} in the single character string 1931c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // cache already. 193262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* entry = 193362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index); 1934c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 193562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check1 = __ WordEqual(entry, __ UndefinedConstant()); 193662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check1, &runtime_call); 193762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, entry); 1938c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1939c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Let %StringFromCharCode handle this case. 1940c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // TODO(turbofan): At some point we may consider adding a stub for this 1941c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // deferred case, so that we don't need to call to C++ here. 194262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&runtime_call); 194313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 1944c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; 1945c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Runtime::FunctionId id = Runtime::kStringCharFromCode; 1946c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor( 1947c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags); 194862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* vtrue1 = 194962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Call(desc, __ CEntryStubConstant(1), ChangeInt32ToSmi(code), 195062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ ExternalConstant(ExternalReference(id, isolate())), 195162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant(1), __ NoContextConstant()); 195262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, vtrue1); 195313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 195462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 195562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 195613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 195713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 195862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerStringFromCodePoint(Node* node) { 1959f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* value = node->InputAt(0); 1960f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* code = value; 1961f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 196262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_single_code = __ MakeDeferredLabel<1>(); 196362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_one_byte = __ MakeDeferredLabel<1>(); 196462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto cache_miss = __ MakeDeferredLabel<1>(); 196562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<4>(MachineRepresentation::kTagged); 1966f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1967f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check if the {code} is a single code unit 196862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check0 = __ Uint32LessThanOrEqual(code, __ Uint32Constant(0xFFFF)); 196962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check0, &if_not_single_code); 1970f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1971f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 1972f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check if the {code} is a one byte character 197362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check1 = __ Uint32LessThanOrEqual( 197462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch code, __ Uint32Constant(String::kMaxOneByteCharCode)); 197562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check1, &if_not_one_byte); 1976f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 1977f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Load the isolate wide single character string cache. 197862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* cache = __ HeapConstant(factory()->single_character_string_cache()); 1979f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1980f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Compute the {cache} index for {code}. 198162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code); 1982f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1983f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check if we have an entry for the {code} in the single character string 1984f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // cache already. 198562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* entry = 198662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index); 198762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 198862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check2 = __ WordEqual(entry, __ UndefinedConstant()); 198962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check2, &cache_miss); 199062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 199162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Use the {entry} from the {cache}. 199262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, entry); 199362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 199462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&cache_miss); 1995f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 1996f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Allocate a new SeqOneByteString for {code}. 199762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* vtrue2 = __ Allocate( 199862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch NOT_TENURED, __ Int32Constant(SeqOneByteString::SizeFor(1))); 199962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ StoreField(AccessBuilder::ForMap(), vtrue2, 200062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ HeapConstant(factory()->one_byte_string_map())); 200162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ StoreField(AccessBuilder::ForNameHashField(), vtrue2, 200262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ IntPtrConstant(Name::kEmptyHashField)); 200362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ StoreField(AccessBuilder::ForStringLength(), vtrue2, 200462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ SmiConstant(1)); 200562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Store( 200662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreRepresentation(MachineRepresentation::kWord8, kNoWriteBarrier), 200762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch vtrue2, 200862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag), 200962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch code); 2010f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2011f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Remember it in the {cache}. 201262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ StoreElement(AccessBuilder::ForFixedArrayElement(), cache, index, 201362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch vtrue2); 201462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, vtrue2); 2015f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2016f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2017f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 201862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_one_byte); 2019f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 2020f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Allocate a new SeqTwoByteString for {code}. 202162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* vfalse1 = __ Allocate( 202262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch NOT_TENURED, __ Int32Constant(SeqTwoByteString::SizeFor(1))); 202362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ StoreField(AccessBuilder::ForMap(), vfalse1, 202462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ HeapConstant(factory()->string_map())); 202562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ StoreField(AccessBuilder::ForNameHashField(), vfalse1, 202662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ IntPtrConstant(Name::kEmptyHashField)); 202762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ StoreField(AccessBuilder::ForStringLength(), vfalse1, 202862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ SmiConstant(1)); 202962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Store( 203062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreRepresentation(MachineRepresentation::kWord16, kNoWriteBarrier), 203162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch vfalse1, 203262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag), 203362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch code); 203462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, vfalse1); 2035f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2036f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2037f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 203862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_single_code); 2039f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Generate surrogate pair string 2040f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 2041f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch switch (UnicodeEncodingOf(node->op())) { 2042f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case UnicodeEncoding::UTF16: 2043f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch break; 2044f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2045f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case UnicodeEncoding::UTF32: { 2046f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Convert UTF32 to UTF16 code units, and store as a 32 bit word. 204762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* lead_offset = __ Int32Constant(0xD800 - (0x10000 >> 10)); 2048f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2049f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // lead = (codepoint >> 10) + LEAD_OFFSET 2050f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Node* lead = 205162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Add(__ Word32Shr(code, __ Int32Constant(10)), lead_offset); 2052f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2053f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // trail = (codepoint & 0x3FF) + 0xDC00; 205462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* trail = __ Int32Add(__ Word32And(code, __ Int32Constant(0x3FF)), 205562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant(0xDC00)); 2056f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2057f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // codpoint = (trail << 16) | lead; 205862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch code = __ Word32Or(__ Word32Shl(trail, __ Int32Constant(16)), lead); 2059f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch break; 2060f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2061f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2062f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2063f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Allocate a new SeqTwoByteString for {code}. 206462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* vfalse0 = __ Allocate(NOT_TENURED, 206562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant(SeqTwoByteString::SizeFor(2))); 206662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ StoreField(AccessBuilder::ForMap(), vfalse0, 206762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ HeapConstant(factory()->string_map())); 206862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ StoreField(AccessBuilder::ForNameHashField(), vfalse0, 206962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ IntPtrConstant(Name::kEmptyHashField)); 207062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ StoreField(AccessBuilder::ForStringLength(), vfalse0, __ SmiConstant(2)); 207162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Store( 207262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreRepresentation(MachineRepresentation::kWord32, kNoWriteBarrier), 207362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch vfalse0, 207462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag), 207562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch code); 207662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, vfalse0); 207762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 207862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 207962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 208062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 208162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 208262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 208362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerStringIndexOf(Node* node) { 208462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* subject = node->InputAt(0); 208562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* search_string = node->InputAt(1); 208662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* position = node->InputAt(2); 2087f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 208862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Callable callable = CodeFactory::StringIndexOf(isolate()); 208962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Operator::Properties properties = Operator::kEliminatable; 209062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 209162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallDescriptor* desc = Linkage::GetStubCallDescriptor( 209262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); 209362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ Call(desc, __ HeapConstant(callable.code()), subject, search_string, 209462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch position, __ NoContextConstant()); 2095f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 2096f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 209762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerStringComparison(Callable const& callable, 209862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* node) { 209962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* lhs = node->InputAt(0); 210062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* rhs = node->InputAt(1); 210162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 2102f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Operator::Properties properties = Operator::kEliminatable; 2103f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 2104f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallDescriptor* desc = Linkage::GetStubCallDescriptor( 2105f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); 210662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ Call(desc, __ HeapConstant(callable.code()), lhs, rhs, 210762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ NoContextConstant()); 2108f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 2109f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 211062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerStringEqual(Node* node) { 211162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return LowerStringComparison(CodeFactory::StringEqual(isolate()), node); 2112f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 2113f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 211462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerStringLessThan(Node* node) { 211562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return LowerStringComparison(CodeFactory::StringLessThan(isolate()), node); 2116f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 2117f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 211862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerStringLessThanOrEqual(Node* node) { 2119f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return LowerStringComparison(CodeFactory::StringLessThanOrEqual(isolate()), 212062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch node); 2121f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 2122f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 212362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckFloat64Hole(Node* node, 212462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* frame_state) { 212513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // If we reach this point w/o eliminating the {node} that's marked 212613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // with allow-return-hole, we cannot do anything, so just deoptimize 212713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // in case of the hole NaN (similar to Crankshaft). 212813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* value = node->InputAt(0); 212962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ Word32Equal(__ Float64ExtractHighWord32(value), 213062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant(kHoleNanUpper32)); 213162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kHole, check, frame_state); 213262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return value; 213313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 213413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 213562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckTaggedHole(Node* node, 213662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* frame_state) { 213713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* value = node->InputAt(0); 213862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ WordEqual(value, __ TheHoleConstant()); 213962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kHole, check, frame_state); 214062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return value; 2141f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2142f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 214362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerConvertTaggedHoleToUndefined(Node* node) { 2144f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* value = node->InputAt(0); 214513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 214662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_is_hole = __ MakeDeferredLabel<1>(); 214762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); 2148f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 214962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ WordEqual(value, __ TheHoleConstant()); 215062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check, &if_is_hole); 215162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, value); 2152f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 215362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_is_hole); 215462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ UndefinedConstant()); 215513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 215662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 215762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 215813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 215913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 216062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::AllocateHeapNumberWithValue(Node* value) { 216162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* result = __ Allocate(NOT_TENURED, __ Int32Constant(HeapNumber::kSize)); 216262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ StoreField(AccessBuilder::ForMap(), result, __ HeapNumberMapConstant()); 216362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ StoreField(AccessBuilder::ForHeapNumberValue(), result, value); 216462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return result; 2165bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2166bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2167bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* EffectControlLinearizer::ChangeInt32ToSmi(Node* value) { 2168bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (machine()->Is64()) { 216962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch value = __ ChangeInt32ToInt64(value); 2170bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 217162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ WordShl(value, SmiShiftBitsConstant()); 2172bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2173bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2174bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* EffectControlLinearizer::ChangeUint32ToSmi(Node* value) { 2175bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (machine()->Is64()) { 217662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch value = __ ChangeUint32ToUint64(value); 2177bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 217862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ WordShl(value, SmiShiftBitsConstant()); 2179bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2180bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2181bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* EffectControlLinearizer::ChangeSmiToInt32(Node* value) { 218262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch value = __ WordSar(value, SmiShiftBitsConstant()); 2183bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (machine()->Is64()) { 218462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch value = __ TruncateInt64ToInt32(value); 2185bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 2186bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return value; 2187bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 218862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 2189bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* EffectControlLinearizer::ObjectIsSmi(Node* value) { 219062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ WordEqual(__ WordAnd(value, __ IntPtrConstant(kSmiTagMask)), 219162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ IntPtrConstant(kSmiTag)); 2192bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2193bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2194bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* EffectControlLinearizer::SmiMaxValueConstant() { 219562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ Int32Constant(Smi::kMaxValue); 2196bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2197bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2198bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* EffectControlLinearizer::SmiShiftBitsConstant() { 219962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ IntPtrConstant(kSmiShiftSize + kSmiTagSize); 2200bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2201bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 220262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerPlainPrimitiveToNumber(Node* node) { 220313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* value = node->InputAt(0); 220462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ ToNumber(value); 220513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 220613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 220762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerPlainPrimitiveToWord32(Node* node) { 220813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* value = node->InputAt(0); 220913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 221062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_smi = __ MakeDeferredLabel<1>(); 221162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_to_number_smi = __ MakeLabel<1>(); 221262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<3>(MachineRepresentation::kWord32); 221313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 221462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check0 = ObjectIsSmi(value); 221562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check0, &if_not_smi); 221662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, ChangeSmiToInt32(value)); 221713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 221862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_smi); 221962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* to_number = __ ToNumber(value); 222013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 222162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check1 = ObjectIsSmi(to_number); 222262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check1, &if_to_number_smi); 222362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), to_number); 222462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ TruncateFloat64ToWord32(number)); 222513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 222662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_to_number_smi); 222762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, ChangeSmiToInt32(to_number)); 222813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 222962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 223062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 223113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 223213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 223362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerPlainPrimitiveToFloat64(Node* node) { 223413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Node* value = node->InputAt(0); 223513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 223662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_smi = __ MakeDeferredLabel<1>(); 223762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_to_number_smi = __ MakeLabel<1>(); 223862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<3>(MachineRepresentation::kFloat64); 223913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 224062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check0 = ObjectIsSmi(value); 224162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check0, &if_not_smi); 224262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* from_smi = ChangeSmiToInt32(value); 224362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ ChangeInt32ToFloat64(from_smi)); 224413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 224562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_smi); 224662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* to_number = __ ToNumber(value); 224762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check1 = ObjectIsSmi(to_number); 224862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check1, &if_to_number_smi); 224913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 225062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), to_number); 225162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, number); 225213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 225362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_to_number_smi); 225462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* number_from_smi = ChangeSmiToInt32(to_number); 225562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch number_from_smi = __ ChangeInt32ToFloat64(number_from_smi); 225662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, number_from_smi); 225713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 225862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 225962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 226013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 226113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 226262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerEnsureWritableFastElements(Node* node) { 2263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* object = node->InputAt(0); 2264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* elements = node->InputAt(1); 2265f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 226662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_fixed_array = __ MakeDeferredLabel<1>(); 226762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); 226862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 2269f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Load the current map of {elements}. 227062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* elements_map = __ LoadField(AccessBuilder::ForMap(), elements); 2271f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2272f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if {elements} is not a copy-on-write FixedArray. 227362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ WordEqual(elements_map, __ FixedArrayMapConstant()); 227462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check, &if_not_fixed_array); 2275f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Nothing to do if the {elements} are not copy-on-write. 227662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, elements); 2277f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 227862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_fixed_array); 2279f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // We need to take a copy of the {elements} and set them up for {object}. 228062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Operator::Properties properties = Operator::kEliminatable; 228162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Callable callable = CodeFactory::CopyFastSmiOrObjectElements(isolate()); 228262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 228362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallDescriptor const* const desc = Linkage::GetStubCallDescriptor( 228462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); 228562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* result = __ Call(desc, __ HeapConstant(callable.code()), object, 228662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ NoContextConstant()); 228762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, result); 2288f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 228962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 229062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 2291f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2292f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 229362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerMaybeGrowFastElements(Node* node, 229462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* frame_state) { 2295f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GrowFastElementsFlags flags = GrowFastElementsFlagsOf(node->op()); 2296f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* object = node->InputAt(0); 2297f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* elements = node->InputAt(1); 2298f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* index = node->InputAt(2); 2299f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* length = node->InputAt(3); 2300f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 230162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); 230262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done_grow = __ MakeLabel<2>(MachineRepresentation::kTagged); 230362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_grow = __ MakeDeferredLabel<1>(); 230462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_grow = __ MakeLabel<1>(); 2305f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 230662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check0 = (flags & GrowFastElementsFlag::kHoleyElements) 230762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ? __ Uint32LessThanOrEqual(length, index) 230862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch : __ Word32Equal(length, index); 230962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check0, &if_not_grow); 2310f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 2311f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Load the length of the {elements} backing store. 231262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* elements_length = 231362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadField(AccessBuilder::ForFixedArrayLength(), elements); 2314f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch elements_length = ChangeSmiToInt32(elements_length); 2315f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2316f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if we need to grow the {elements} backing store. 231762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check1 = __ Uint32LessThan(index, elements_length); 231862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check1, &if_grow); 231962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done_grow, elements); 2320f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 232162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_grow); 232262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // We need to grow the {elements} for {object}. 232362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Operator::Properties properties = Operator::kEliminatable; 232462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Callable callable = 232562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch (flags & GrowFastElementsFlag::kDoubleElements) 232662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ? CodeFactory::GrowFastDoubleElements(isolate()) 232762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch : CodeFactory::GrowFastSmiOrObjectElements(isolate()); 232862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallDescriptor::Flags call_flags = CallDescriptor::kNoFlags; 232962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallDescriptor const* const desc = Linkage::GetStubCallDescriptor( 233062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate(), graph()->zone(), callable.descriptor(), 0, call_flags, 233162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch properties); 233262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* new_object = __ Call(desc, __ HeapConstant(callable.code()), object, 233362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ChangeInt32ToSmi(index), __ NoContextConstant()); 233462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 233562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Ensure that we were able to grow the {elements}. 233662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // TODO(turbofan): We use kSmi as reason here similar to Crankshaft, 233762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // but maybe we should just introduce a reason that makes sense. 233862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeIf(DeoptimizeReason::kSmi, ObjectIsSmi(new_object), 233962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch frame_state); 234062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done_grow, new_object); 234162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 234262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done_grow); 2343f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2344f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // For JSArray {object}s we also need to update the "length". 2345f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (flags & GrowFastElementsFlag::kArrayObject) { 2346f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Compute the new {length}. 234762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* object_length = 234862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ChangeInt32ToSmi(__ Int32Add(index, __ Int32Constant(1))); 2349f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2350f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Update the "length" property of the {object}. 235162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ StoreField(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS), object, 235262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch object_length); 2353f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 235462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, done_grow.PhiAt(0)); 2355f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2356f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 235762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_grow); 2358f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 2359f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // In case of non-holey {elements}, we need to verify that the {index} is 2360f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // in-bounds, otherwise for holey {elements}, the check above already 2361f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // guards the index (and the operator forces {index} to be unsigned). 2362f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!(flags & GrowFastElementsFlag::kHoleyElements)) { 236362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check1 = __ Uint32LessThan(index, length); 236462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DeoptimizeUnless(DeoptimizeReason::kOutOfBounds, check1, frame_state); 2365f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 236662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, elements); 2367f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 236862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 236962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 2370f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2371f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 237262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid EffectControlLinearizer::LowerTransitionElementsKind(Node* node) { 2373f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ElementsTransition const transition = ElementsTransitionOf(node->op()); 2374f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* object = node->InputAt(0); 237562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 237662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_map_same = __ MakeDeferredLabel<1>(); 237762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<2>(); 237862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 237962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* source_map = __ HeapConstant(transition.source()); 238062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* target_map = __ HeapConstant(transition.target()); 2381f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2382f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Load the current map of {object}. 238362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* object_map = __ LoadField(AccessBuilder::ForMap(), object); 2384f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2385f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check if {object_map} is the same as {source_map}. 238662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check = __ WordEqual(object_map, source_map); 238762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check, &if_map_same); 238862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done); 238962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 239062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_map_same); 239162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch switch (transition.mode()) { 239262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case ElementsTransition::kFastTransition: 239362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // In-place migration of {object}, just store the {target_map}. 239462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ StoreField(AccessBuilder::ForMap(), object, target_map); 239562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 239662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case ElementsTransition::kSlowTransition: { 239762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Instance migration, call out to the runtime for {object}. 239862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; 239962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Runtime::FunctionId id = Runtime::kTransitionElementsKind; 240062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor( 240162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags); 240262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Call(desc, __ CEntryStubConstant(1), object, target_map, 240362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ ExternalConstant(ExternalReference(id, isolate())), 240462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Int32Constant(2), __ NoContextConstant()); 240562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 2406f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2407f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 240862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done); 2409f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 241062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 2411f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2412f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 241362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerLoadTypedElement(Node* node) { 2414f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ExternalArrayType array_type = ExternalArrayTypeOf(node->op()); 2415f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* buffer = node->InputAt(0); 2416f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* base = node->InputAt(1); 2417f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* external = node->InputAt(2); 2418f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* index = node->InputAt(3); 2419f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2420f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // We need to keep the {buffer} alive so that the GC will not release the 2421f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ArrayBuffer (if there's any) as long as we are still operating on it. 242262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Retain(buffer); 2423f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 242462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Compute the effective storage pointer, handling the case where the 242562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // {external} pointer is the effective storage pointer (i.e. the {base} 242662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // is Smi zero). 242762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* storage = NumberMatcher(base).Is(0) ? external : __ UnsafePointerAdd( 242862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch base, external); 2429f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2430f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Perform the actual typed element access. 243162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return __ LoadElement(AccessBuilder::ForTypedArrayElement(array_type, true), 243262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch storage, index); 2433f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2434f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 243562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid EffectControlLinearizer::LowerStoreTypedElement(Node* node) { 2436f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ExternalArrayType array_type = ExternalArrayTypeOf(node->op()); 2437f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* buffer = node->InputAt(0); 2438f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* base = node->InputAt(1); 2439f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* external = node->InputAt(2); 2440f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* index = node->InputAt(3); 2441f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* value = node->InputAt(4); 2442f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2443f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // We need to keep the {buffer} alive so that the GC will not release the 2444f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ArrayBuffer (if there's any) as long as we are still operating on it. 244562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Retain(buffer); 2446f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 244762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Compute the effective storage pointer, handling the case where the 244862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // {external} pointer is the effective storage pointer (i.e. the {base} 244962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // is Smi zero). 245062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* storage = NumberMatcher(base).Is(0) ? external : __ UnsafePointerAdd( 245162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch base, external); 2452f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2453f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Perform the actual typed element access. 245462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ StoreElement(AccessBuilder::ForTypedArrayElement(array_type, true), 245562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch storage, index, value); 2456f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2457f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 245862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochMaybe<Node*> EffectControlLinearizer::LowerFloat64RoundUp(Node* node) { 2459f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Nothing to be done if a fast hardware instruction is available. 2460f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (machine()->Float64RoundUp().IsSupported()) { 246162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Nothing<Node*>(); 2462f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2463f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2464f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* const input = node->InputAt(0); 2465f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2466f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // General case for ceil. 2467f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 2468f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // if 0.0 < input then 2469f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // if 2^52 <= input then 2470f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // input 2471f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // else 2472f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // let temp1 = (2^52 + input) - 2^52 in 2473f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // if temp1 < input then 2474f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // temp1 + 1 2475f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // else 2476f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // temp1 2477f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // else 2478f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // if input == 0 then 2479f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // input 2480f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // else 2481f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // if input <= -2^52 then 2482f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // input 2483f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // else 2484f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // let temp1 = -0 - input in 2485f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // let temp2 = (2^52 + temp1) - 2^52 in 2486f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in 2487f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -0 - temp3 2488f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 248962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_positive = __ MakeDeferredLabel<1>(); 249062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_greater_than_two_52 = __ MakeDeferredLabel<1>(); 249162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_less_than_minus_two_52 = __ MakeDeferredLabel<1>(); 249262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_zero = __ MakeDeferredLabel<1>(); 249362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done_temp3 = __ MakeLabel<2>(MachineRepresentation::kFloat64); 249462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<6>(MachineRepresentation::kFloat64); 2495f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 249662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const zero = __ Float64Constant(0.0); 249762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const two_52 = __ Float64Constant(4503599627370496.0E0); 249862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const one = __ Float64Constant(1.0); 2499f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 250062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check0 = __ Float64LessThan(zero, input); 250162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check0, &if_not_positive); 250262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 250362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check1 = __ Float64LessThanOrEqual(two_52, input); 250462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check1, &if_greater_than_two_52); 2505f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 250662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52); 250762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(__ Float64LessThan(temp1, input), &done, temp1); 250862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Float64Add(temp1, one)); 2509f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2510f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 251162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_greater_than_two_52); 251262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, input); 2513f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2514f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 251562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_positive); 2516f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 251762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check1 = __ Float64Equal(input, zero); 251862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check1, &if_zero); 2519f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 252062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0); 252162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52); 252262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check2, &if_less_than_minus_two_52); 2523f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2524f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 252562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const minus_zero = __ Float64Constant(-0.0); 252662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* temp1 = __ Float64Sub(minus_zero, input); 252762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52); 252862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check3 = __ Float64LessThan(temp1, temp2); 252962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check3, &done_temp3, temp2); 253062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done_temp3, __ Float64Sub(temp2, one)); 253162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 253262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done_temp3); 253362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* temp3 = done_temp3.PhiAt(0); 253462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Float64Sub(minus_zero, temp3)); 2535f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 253662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_less_than_minus_two_52); 253762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, input); 2538f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 253962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_zero); 254062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, input); 2541f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 254262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 254362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Just(done.PhiAt(0)); 2544f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2545f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 254662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::BuildFloat64RoundDown(Node* value) { 254762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* round_down = __ Float64RoundDown(value); 254862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (round_down != nullptr) { 254962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return round_down; 255062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 2551c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 255262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const input = value; 2553c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 255462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // General case for floor. 255562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // 255662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // if 0.0 < input then 255762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // if 2^52 <= input then 255862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // input 255962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // else 256062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // let temp1 = (2^52 + input) - 2^52 in 256162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // if input < temp1 then 256262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // temp1 - 1 256362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // else 256462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // temp1 256562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // else 256662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // if input == 0 then 256762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // input 256862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // else 256962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // if input <= -2^52 then 257062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // input 257162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // else 257262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // let temp1 = -0 - input in 257362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // let temp2 = (2^52 + temp1) - 2^52 in 257462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // if temp2 < temp1 then 257562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // -1 - temp2 257662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // else 257762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // -0 - temp2 257862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 257962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_positive = __ MakeDeferredLabel<1>(); 258062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_greater_than_two_52 = __ MakeDeferredLabel<1>(); 258162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_less_than_minus_two_52 = __ MakeDeferredLabel<1>(); 258262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_temp2_lt_temp1 = __ MakeLabel<1>(); 258362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_zero = __ MakeDeferredLabel<1>(); 258462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<7>(MachineRepresentation::kFloat64); 258562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 258662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const zero = __ Float64Constant(0.0); 258762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const two_52 = __ Float64Constant(4503599627370496.0E0); 258862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 258962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check0 = __ Float64LessThan(zero, input); 259062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check0, &if_not_positive); 259162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 259262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check1 = __ Float64LessThanOrEqual(two_52, input); 259362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check1, &if_greater_than_two_52); 2594c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 259562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const one = __ Float64Constant(1.0); 259662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52); 259762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(__ Float64LessThan(input, temp1), &done, temp1); 259862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Float64Sub(temp1, one)); 259962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 2600c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 260162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_greater_than_two_52); 260262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, input); 260362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 2604c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 260562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_positive); 260662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 260762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check1 = __ Float64Equal(input, zero); 260862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check1, &if_zero); 2609c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 261062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0); 261162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52); 261262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check2, &if_less_than_minus_two_52); 2613c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 261462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 261562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const minus_zero = __ Float64Constant(-0.0); 261662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* temp1 = __ Float64Sub(minus_zero, input); 261762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52); 261862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check3 = __ Float64LessThan(temp2, temp1); 261962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check3, &if_temp2_lt_temp1); 262062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Float64Sub(minus_zero, temp2)); 262162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 262262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_temp2_lt_temp1); 262362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Float64Sub(__ Float64Constant(-1.0), temp2)); 2624c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 262562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_less_than_minus_two_52); 262662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, input); 2627c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 262862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_zero); 262962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, input); 2630c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 263162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 263262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return done.PhiAt(0); 2633c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2634c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 263562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochMaybe<Node*> EffectControlLinearizer::LowerFloat64RoundDown(Node* node) { 2636f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Nothing to be done if a fast hardware instruction is available. 2637f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (machine()->Float64RoundDown().IsSupported()) { 263862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Nothing<Node*>(); 2639f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2640f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2641c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Node* const input = node->InputAt(0); 264262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Just(BuildFloat64RoundDown(input)); 2643c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 2644c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 264562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochMaybe<Node*> EffectControlLinearizer::LowerFloat64RoundTiesEven(Node* node) { 2646c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Nothing to be done if a fast hardware instruction is available. 2647c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (machine()->Float64RoundTiesEven().IsSupported()) { 264862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Nothing<Node*>(); 2649c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 2650c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2651f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* const input = node->InputAt(0); 2652f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2653c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Generate case for round ties to even: 2654f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 2655c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // let value = floor(input) in 2656c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // let temp1 = input - value in 2657c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // if temp1 < 0.5 then 2658c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // value 2659c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // else if 0.5 < temp1 then 2660c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // value + 1.0 2661f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // else 2662c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // let temp2 = value % 2.0 in 2663c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // if temp2 == 0.0 then 2664c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // value 2665f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // else 2666c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // value + 1.0 2667f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 266862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_is_half = __ MakeLabel<1>(); 266962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<4>(MachineRepresentation::kFloat64); 2670f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 267162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value = BuildFloat64RoundDown(input); 267262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* temp1 = __ Float64Sub(input, value); 2673f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 267462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const half = __ Float64Constant(0.5); 267562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check0 = __ Float64LessThan(temp1, half); 267662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check0, &done, value); 2677f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 267862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const one = __ Float64Constant(1.0); 267962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check1 = __ Float64LessThan(half, temp1); 268062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check1, &if_is_half); 268162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Float64Add(value, one)); 2682f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 268362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_is_half); 268462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* temp2 = __ Float64Mod(value, __ Float64Constant(2.0)); 268562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check2 = __ Float64Equal(temp2, __ Float64Constant(0.0)); 268662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check2, &done, value); 268762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Float64Add(value, one)); 2688f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 268962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 269062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Just(done.PhiAt(0)); 2691f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2692f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 269362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochMaybe<Node*> EffectControlLinearizer::LowerFloat64RoundTruncate(Node* node) { 2694f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Nothing to be done if a fast hardware instruction is available. 2695f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (machine()->Float64RoundTruncate().IsSupported()) { 269662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Nothing<Node*>(); 2697f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2698f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2699f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Node* const input = node->InputAt(0); 2700f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2701f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // General case for trunc. 2702f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 2703f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // if 0.0 < input then 2704f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // if 2^52 <= input then 2705f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // input 2706f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // else 2707f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // let temp1 = (2^52 + input) - 2^52 in 2708f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // if input < temp1 then 2709f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // temp1 - 1 2710f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // else 2711f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // temp1 2712f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // else 2713f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // if input == 0 then 2714f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // input 2715f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // else 2716f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // if input <= -2^52 then 2717f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // input 2718f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // else 2719f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // let temp1 = -0 - input in 2720f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // let temp2 = (2^52 + temp1) - 2^52 in 2721f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in 2722f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -0 - temp3 2723f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 2724f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Note: We do not use the Diamond helper class here, because it really hurts 2725f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // readability with nested diamonds. 2726f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 272762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_not_positive = __ MakeDeferredLabel<1>(); 272862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_greater_than_two_52 = __ MakeDeferredLabel<1>(); 272962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_less_than_minus_two_52 = __ MakeDeferredLabel<1>(); 273062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_zero = __ MakeDeferredLabel<1>(); 273162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done_temp3 = __ MakeLabel<2>(MachineRepresentation::kFloat64); 273262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto done = __ MakeLabel<6>(MachineRepresentation::kFloat64); 2733f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 273462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const zero = __ Float64Constant(0.0); 273562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const two_52 = __ Float64Constant(4503599627370496.0E0); 273662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const one = __ Float64Constant(1.0); 2737f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 273862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check0 = __ Float64LessThan(zero, input); 273962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check0, &if_not_positive); 274062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 274162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check1 = __ Float64LessThanOrEqual(two_52, input); 274262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check1, &if_greater_than_two_52); 2743f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 274462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52); 274562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(__ Float64LessThan(input, temp1), &done, temp1); 274662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Float64Sub(temp1, one)); 2747f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2748f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 274962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_greater_than_two_52); 275062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, input); 2751f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2752f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 275362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_not_positive); 2754f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 275562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check1 = __ Float64Equal(input, zero); 275662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check1, &if_zero); 2757f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 275862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0); 275962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52); 276062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoIf(check2, &if_less_than_minus_two_52); 2761f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2762f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 276362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const minus_zero = __ Float64Constant(-0.0); 276462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* temp1 = __ Float64Sub(minus_zero, input); 276562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52); 276662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* check3 = __ Float64LessThan(temp1, temp2); 276762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ GotoUnless(check3, &done_temp3, temp2); 276862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done_temp3, __ Float64Sub(temp2, one)); 276962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 277062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done_temp3); 277162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* temp3 = done_temp3.PhiAt(0); 277262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, __ Float64Sub(minus_zero, temp3)); 2773f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 277462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_less_than_minus_two_52); 277562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, input); 2776f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 277762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&if_zero); 277862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Goto(&done, input); 2779f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 278062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Bind(&done); 278162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Just(done.PhiAt(0)); 2782f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2783f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 278462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#undef __ 278562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 278613e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochFactory* EffectControlLinearizer::factory() const { 278713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return isolate()->factory(); 278813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 278913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 279013e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochIsolate* EffectControlLinearizer::isolate() const { 279113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return jsgraph()->isolate(); 279213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 279313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 2794bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} // namespace compiler 2795bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} // namespace internal 2796bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} // namespace v8 2797