LCOV - code coverage report
Current view: top level - src/compiler - code-assembler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 445 569 78.2 %
Date: 2017-10-20 Functions: 231 289 79.9 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/code-assembler.h"
       6             : 
       7             : #include <ostream>
       8             : 
       9             : #include "src/code-factory.h"
      10             : #include "src/compiler/graph.h"
      11             : #include "src/compiler/instruction-selector.h"
      12             : #include "src/compiler/linkage.h"
      13             : #include "src/compiler/node-matchers.h"
      14             : #include "src/compiler/pipeline.h"
      15             : #include "src/compiler/raw-machine-assembler.h"
      16             : #include "src/compiler/schedule.h"
      17             : #include "src/frames.h"
      18             : #include "src/interface-descriptors.h"
      19             : #include "src/interpreter/bytecodes.h"
      20             : #include "src/machine-type.h"
      21             : #include "src/macro-assembler.h"
      22             : #include "src/objects-inl.h"
      23             : #include "src/utils.h"
      24             : #include "src/zone/zone.h"
      25             : 
      26             : #define REPEAT_1_TO_2(V, T) V(T) V(T, T)
      27             : #define REPEAT_1_TO_3(V, T) REPEAT_1_TO_2(V, T) V(T, T, T)
      28             : #define REPEAT_1_TO_4(V, T) REPEAT_1_TO_3(V, T) V(T, T, T, T)
      29             : #define REPEAT_1_TO_5(V, T) REPEAT_1_TO_4(V, T) V(T, T, T, T, T)
      30             : #define REPEAT_1_TO_6(V, T) REPEAT_1_TO_5(V, T) V(T, T, T, T, T, T)
      31             : #define REPEAT_1_TO_7(V, T) REPEAT_1_TO_6(V, T) V(T, T, T, T, T, T, T)
      32             : #define REPEAT_1_TO_8(V, T) REPEAT_1_TO_7(V, T) V(T, T, T, T, T, T, T, T)
      33             : #define REPEAT_1_TO_9(V, T) REPEAT_1_TO_8(V, T) V(T, T, T, T, T, T, T, T, T)
      34             : #define REPEAT_1_TO_10(V, T) REPEAT_1_TO_9(V, T) V(T, T, T, T, T, T, T, T, T, T)
      35             : #define REPEAT_1_TO_11(V, T) \
      36             :   REPEAT_1_TO_10(V, T) V(T, T, T, T, T, T, T, T, T, T, T)
      37             : #define REPEAT_1_TO_12(V, T) \
      38             :   REPEAT_1_TO_11(V, T) V(T, T, T, T, T, T, T, T, T, T, T, T)
      39             : 
      40             : namespace v8 {
      41             : namespace internal {
      42             : 
      43             : constexpr MachineType MachineTypeOf<Smi>::value;
      44             : constexpr MachineType MachineTypeOf<Object>::value;
      45             : 
      46             : namespace compiler {
      47             : 
      48             : static_assert(std::is_convertible<TNode<Number>, TNode<Object>>::value,
      49             :               "test subtyping");
      50             : static_assert(std::is_convertible<TNode<UnionT<Smi, HeapNumber>>,
      51             :                                   TNode<UnionT<Smi, HeapObject>>>::value,
      52             :               "test subtyping");
      53             : static_assert(
      54             :     !std::is_convertible<TNode<UnionT<Smi, HeapObject>>, TNode<Number>>::value,
      55             :     "test subtyping");
      56             : 
      57       44586 : CodeAssemblerState::CodeAssemblerState(
      58             :     Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor,
      59             :     Code::Kind kind, const char* name, size_t result_size)
      60             :     : CodeAssemblerState(
      61             :           isolate, zone,
      62             :           Linkage::GetStubCallDescriptor(
      63             :               isolate, zone, descriptor, descriptor.GetStackParameterCount(),
      64             :               CallDescriptor::kNoFlags, Operator::kNoProperties,
      65             :               MachineType::AnyTagged(), result_size),
      66       44586 :           kind, name) {}
      67             : 
      68        8688 : CodeAssemblerState::CodeAssemblerState(Isolate* isolate, Zone* zone,
      69             :                                        int parameter_count, Code::Kind kind,
      70             :                                        const char* name)
      71             :     : CodeAssemblerState(
      72             :           isolate, zone,
      73             :           Linkage::GetJSCallDescriptor(zone, false, parameter_count,
      74             :                                        kind == Code::BUILTIN
      75             :                                            ? CallDescriptor::kPushArgumentCount
      76             :                                            : CallDescriptor::kNoFlags),
      77       17376 :           kind, name) {}
      78             : 
      79       53292 : CodeAssemblerState::CodeAssemblerState(Isolate* isolate, Zone* zone,
      80             :                                        CallDescriptor* call_descriptor,
      81             :                                        Code::Kind kind, const char* name)
      82             :     : raw_assembler_(new RawMachineAssembler(
      83       53292 :           isolate, new (zone) Graph(zone), call_descriptor,
      84             :           MachineType::PointerRepresentation(),
      85             :           InstructionSelector::SupportedMachineOperatorFlags(),
      86       53292 :           InstructionSelector::AlignmentRequirements())),
      87             :       kind_(kind),
      88             :       name_(name),
      89             :       code_generated_(false),
      90      159876 :       variables_(zone) {}
      91             : 
      92      106584 : CodeAssemblerState::~CodeAssemblerState() {}
      93             : 
      94           0 : int CodeAssemblerState::parameter_count() const {
      95           0 :   return static_cast<int>(raw_assembler_->call_descriptor()->ParameterCount());
      96             : }
      97             : 
      98       58506 : CodeAssembler::~CodeAssembler() {}
      99             : 
     100             : #if DEBUG
     101             : void CodeAssemblerState::PrintCurrentBlock(std::ostream& os) {
     102             :   raw_assembler_->PrintCurrentBlock(os);
     103             : }
     104             : #endif
     105             : 
     106       25854 : void CodeAssemblerState::SetInitialDebugInformation(const char* msg,
     107             :                                                     const char* file,
     108             :                                                     int line) {
     109             : #if DEBUG
     110             :   AssemblerDebugInfo debug_info = {msg, file, line};
     111             :   raw_assembler_->SetInitialDebugInformation(debug_info);
     112             : #endif  // DEBUG
     113       25854 : }
     114             : 
     115           0 : class BreakOnNodeDecorator final : public GraphDecorator {
     116             :  public:
     117           0 :   explicit BreakOnNodeDecorator(NodeId node_id) : node_id_(node_id) {}
     118             : 
     119           0 :   void Decorate(Node* node) final {
     120           0 :     if (node->id() == node_id_) {
     121           0 :       base::OS::DebugBreak();
     122             :     }
     123           0 :   }
     124             : 
     125             :  private:
     126             :   NodeId node_id_;
     127             : };
     128             : 
     129           0 : void CodeAssembler::BreakOnNode(int node_id) {
     130           0 :   Graph* graph = raw_assembler()->graph();
     131             :   Zone* zone = graph->zone();
     132             :   GraphDecorator* decorator =
     133           0 :       new (zone) BreakOnNodeDecorator(static_cast<NodeId>(node_id));
     134           0 :   graph->AddDecorator(decorator);
     135           0 : }
     136             : 
     137       15786 : void CodeAssembler::RegisterCallGenerationCallbacks(
     138             :     const CodeAssemblerCallback& call_prologue,
     139             :     const CodeAssemblerCallback& call_epilogue) {
     140             :   // The callback can be registered only once.
     141             :   DCHECK(!state_->call_prologue_);
     142             :   DCHECK(!state_->call_epilogue_);
     143       15786 :   state_->call_prologue_ = call_prologue;
     144       15786 :   state_->call_epilogue_ = call_epilogue;
     145       15786 : }
     146             : 
     147       15786 : void CodeAssembler::UnregisterCallGenerationCallbacks() {
     148       15786 :   state_->call_prologue_ = nullptr;
     149       15786 :   state_->call_epilogue_ = nullptr;
     150       15786 : }
     151             : 
     152           0 : void CodeAssembler::CallPrologue() {
     153      245852 :   if (state_->call_prologue_) {
     154       34805 :     state_->call_prologue_();
     155             :   }
     156           0 : }
     157             : 
     158           0 : void CodeAssembler::CallEpilogue() {
     159      245852 :   if (state_->call_epilogue_) {
     160       34805 :     state_->call_epilogue_();
     161             :   }
     162           0 : }
     163             : 
     164             : // static
     165       51346 : Handle<Code> CodeAssembler::GenerateCode(CodeAssemblerState* state) {
     166             :   DCHECK(!state->code_generated_);
     167             : 
     168      125838 :   RawMachineAssembler* rasm = state->raw_assembler_.get();
     169       51346 :   Schedule* schedule = rasm->Export();
     170             : 
     171             :   JumpOptimizationInfo jump_opt;
     172             :   bool should_optimize_jumps =
     173       51346 :       rasm->isolate()->serializer_enabled() && FLAG_turbo_rewrite_far_jumps;
     174             : 
     175             :   Handle<Code> code = Pipeline::GenerateCodeForCodeStub(
     176             :       rasm->isolate(), rasm->call_descriptor(), rasm->graph(), schedule,
     177      102692 :       state->kind_, state->name_, should_optimize_jumps ? &jump_opt : nullptr);
     178             : 
     179       51346 :   if (jump_opt.is_optimizable()) {
     180             :     jump_opt.set_optimizing();
     181             : 
     182             :     // Regenerate machine code
     183             :     code = Pipeline::GenerateCodeForCodeStub(
     184             :         rasm->isolate(), rasm->call_descriptor(), rasm->graph(), schedule,
     185       46292 :         state->kind_, state->name_, &jump_opt);
     186             :   }
     187             : 
     188       51346 :   state->code_generated_ = true;
     189      102692 :   return code;
     190             : }
     191             : 
     192      215630 : bool CodeAssembler::Is64() const { return raw_assembler()->machine()->Is64(); }
     193             : 
     194         101 : bool CodeAssembler::IsFloat64RoundUpSupported() const {
     195         101 :   return raw_assembler()->machine()->Float64RoundUp().IsSupported();
     196             : }
     197             : 
     198         102 : bool CodeAssembler::IsFloat64RoundDownSupported() const {
     199         102 :   return raw_assembler()->machine()->Float64RoundDown().IsSupported();
     200             : }
     201             : 
     202         141 : bool CodeAssembler::IsFloat64RoundTiesEvenSupported() const {
     203         141 :   return raw_assembler()->machine()->Float64RoundTiesEven().IsSupported();
     204             : }
     205             : 
     206        1215 : bool CodeAssembler::IsFloat64RoundTruncateSupported() const {
     207        1215 :   return raw_assembler()->machine()->Float64RoundTruncate().IsSupported();
     208             : }
     209             : 
     210           0 : bool CodeAssembler::IsInt32AbsWithOverflowSupported() const {
     211           0 :   return raw_assembler()->machine()->Int32AbsWithOverflow().IsSupported();
     212             : }
     213             : 
     214           0 : bool CodeAssembler::IsInt64AbsWithOverflowSupported() const {
     215          31 :   return raw_assembler()->machine()->Int64AbsWithOverflow().IsSupported();
     216             : }
     217             : 
     218          31 : bool CodeAssembler::IsIntPtrAbsWithOverflowSupported() const {
     219             :   return Is64() ? IsInt64AbsWithOverflowSupported()
     220          62 :                 : IsInt32AbsWithOverflowSupported();
     221             : }
     222             : 
     223      278107 : TNode<Int32T> CodeAssembler::Int32Constant(int32_t value) {
     224      372156 :   return UncheckedCast<Int32T>(raw_assembler()->Int32Constant(value));
     225             : }
     226             : 
     227       11056 : TNode<Int64T> CodeAssembler::Int64Constant(int64_t value) {
     228       11056 :   return UncheckedCast<Int64T>(raw_assembler()->Int64Constant(value));
     229             : }
     230             : 
     231     1831045 : TNode<IntPtrT> CodeAssembler::IntPtrConstant(intptr_t value) {
     232     1831045 :   return UncheckedCast<IntPtrT>(raw_assembler()->IntPtrConstant(value));
     233             : }
     234             : 
     235         173 : TNode<Number> CodeAssembler::NumberConstant(double value) {
     236         173 :   return UncheckedCast<Number>(raw_assembler()->NumberConstant(value));
     237             : }
     238             : 
     239       10019 : TNode<Smi> CodeAssembler::SmiConstant(Smi* value) {
     240             :   return UncheckedCast<Smi>(
     241       10019 :       BitcastWordToTaggedSigned(IntPtrConstant(bit_cast<intptr_t>(value))));
     242             : }
     243             : 
     244      157337 : TNode<Smi> CodeAssembler::SmiConstant(int value) {
     245      157337 :   return SmiConstant(Smi::FromInt(value));
     246             : }
     247             : 
     248       59283 : TNode<HeapObject> CodeAssembler::UntypedHeapConstant(
     249             :     Handle<HeapObject> object) {
     250      350061 :   return UncheckedCast<HeapObject>(raw_assembler()->HeapConstant(object));
     251             : }
     252             : 
     253        6262 : TNode<String> CodeAssembler::StringConstant(const char* str) {
     254             :   return UncheckedCast<String>(
     255       12524 :       HeapConstant(factory()->NewStringFromAsciiChecked(str, TENURED)));
     256             : }
     257             : 
     258        9178 : TNode<Oddball> CodeAssembler::BooleanConstant(bool value) {
     259       18356 :   return UncheckedCast<Oddball>(raw_assembler()->BooleanConstant(value));
     260             : }
     261             : 
     262       46839 : TNode<ExternalReference> CodeAssembler::ExternalConstant(
     263             :     ExternalReference address) {
     264             :   return UncheckedCast<ExternalReference>(
     265      133407 :       raw_assembler()->ExternalConstant(address));
     266             : }
     267             : 
     268        4857 : TNode<Float64T> CodeAssembler::Float64Constant(double value) {
     269        4857 :   return UncheckedCast<Float64T>(raw_assembler()->Float64Constant(value));
     270             : }
     271             : 
     272          31 : TNode<HeapNumber> CodeAssembler::NaNConstant() {
     273          31 :   return UncheckedCast<HeapNumber>(LoadRoot(Heap::kNanValueRootIndex));
     274             : }
     275             : 
     276      250938 : bool CodeAssembler::ToInt32Constant(Node* node, int32_t& out_value) {
     277             :   Int64Matcher m(node);
     278      354958 :   if (m.HasValue() &&
     279             :       m.IsInRange(std::numeric_limits<int32_t>::min(),
     280             :                   std::numeric_limits<int32_t>::max())) {
     281      104014 :     out_value = static_cast<int32_t>(m.Value());
     282      104014 :     return true;
     283             :   }
     284             : 
     285             :   return false;
     286             : }
     287             : 
     288          30 : bool CodeAssembler::ToInt64Constant(Node* node, int64_t& out_value) {
     289             :   Int64Matcher m(node);
     290          30 :   if (m.HasValue()) out_value = m.Value();
     291          30 :   return m.HasValue();
     292             : }
     293             : 
     294       21907 : bool CodeAssembler::ToSmiConstant(Node* node, Smi*& out_value) {
     295       21907 :   if (node->opcode() == IrOpcode::kBitcastWordToTaggedSigned) {
     296             :     node = node->InputAt(0);
     297             :   }
     298             :   IntPtrMatcher m(node);
     299       21907 :   if (m.HasValue()) {
     300             :     intptr_t value = m.Value();
     301             :     // Make sure that the value is actually a smi
     302        5041 :     CHECK_EQ(0, value & ((static_cast<intptr_t>(1) << kSmiShiftSize) - 1));
     303        5041 :     out_value = Smi::cast(bit_cast<Object*>(value));
     304             :     return true;
     305             :   }
     306             :   return false;
     307             : }
     308             : 
     309     2091681 : bool CodeAssembler::ToIntPtrConstant(Node* node, intptr_t& out_value) {
     310     2091681 :   if (node->opcode() == IrOpcode::kBitcastWordToTaggedSigned ||
     311             :       node->opcode() == IrOpcode::kBitcastWordToTagged) {
     312             :     node = node->InputAt(0);
     313             :   }
     314             :   IntPtrMatcher m(node);
     315     2091681 :   if (m.HasValue()) out_value = m.Value();
     316     2091681 :   return m.HasValue();
     317             : }
     318             : 
     319      163279 : Node* CodeAssembler::Parameter(int value) {
     320      326558 :   return raw_assembler()->Parameter(value);
     321             : }
     322             : 
     323           0 : TNode<Context> CodeAssembler::GetJSContextParameter() {
     324           0 :   CallDescriptor* desc = raw_assembler()->call_descriptor();
     325             :   DCHECK(desc->IsJSFunctionCall());
     326           0 :   return CAST(Parameter(Linkage::GetJSCallContextParamIndex(
     327             :       static_cast<int>(desc->JSParameterCount()))));
     328             : }
     329             : 
     330       49799 : void CodeAssembler::Return(SloppyTNode<Object> value) {
     331       49861 :   return raw_assembler()->Return(value);
     332             : }
     333             : 
     334           0 : void CodeAssembler::Return(SloppyTNode<Object> value1,
     335             :                            SloppyTNode<Object> value2) {
     336           0 :   return raw_assembler()->Return(value1, value2);
     337             : }
     338             : 
     339           0 : void CodeAssembler::Return(SloppyTNode<Object> value1,
     340             :                            SloppyTNode<Object> value2,
     341             :                            SloppyTNode<Object> value3) {
     342           0 :   return raw_assembler()->Return(value1, value2, value3);
     343             : }
     344             : 
     345        6491 : void CodeAssembler::PopAndReturn(Node* pop, Node* value) {
     346        6491 :   return raw_assembler()->PopAndReturn(pop, value);
     347             : }
     348             : 
     349          62 : void CodeAssembler::ReturnIf(Node* condition, Node* value) {
     350          62 :   Label if_return(this), if_continue(this);
     351          62 :   Branch(condition, &if_return, &if_continue);
     352             :   Bind(&if_return);
     353             :   Return(value);
     354          62 :   Bind(&if_continue);
     355          62 : }
     356             : 
     357           0 : void CodeAssembler::DebugAbort(Node* message) {
     358           0 :   raw_assembler()->DebugAbort(message);
     359           0 : }
     360             : 
     361       11308 : void CodeAssembler::DebugBreak() { raw_assembler()->DebugBreak(); }
     362             : 
     363       11246 : void CodeAssembler::Unreachable() {
     364             :   DebugBreak();
     365       11246 :   raw_assembler()->Unreachable();
     366       11246 : }
     367             : 
     368      169754 : void CodeAssembler::Comment(const char* format, ...) {
     369      339508 :   if (!FLAG_code_comments) return;
     370             :   char buffer[4 * KB];
     371             :   StringBuilder builder(buffer, arraysize(buffer));
     372             :   va_list arguments;
     373           0 :   va_start(arguments, format);
     374           0 :   builder.AddFormattedList(format, arguments);
     375           0 :   va_end(arguments);
     376             : 
     377             :   // Copy the string before recording it in the assembler to avoid
     378             :   // issues when the stack allocated buffer goes out of scope.
     379             :   const int prefix_len = 2;
     380           0 :   int length = builder.position() + 1;
     381           0 :   char* copy = reinterpret_cast<char*>(malloc(length + prefix_len));
     382           0 :   MemCopy(copy + prefix_len, builder.Finalize(), length);
     383           0 :   copy[0] = ';';
     384           0 :   copy[1] = ' ';
     385           0 :   raw_assembler()->Comment(copy);
     386             : }
     387             : 
     388     1038889 : void CodeAssembler::Bind(Label* label) { return label->Bind(); }
     389             : 
     390             : #if DEBUG
     391             : void CodeAssembler::Bind(Label* label, AssemblerDebugInfo debug_info) {
     392             :   return label->Bind(debug_info);
     393             : }
     394             : #endif  // DEBUG
     395             : 
     396        2112 : Node* CodeAssembler::LoadFramePointer() {
     397        2112 :   return raw_assembler()->LoadFramePointer();
     398             : }
     399             : 
     400       15186 : Node* CodeAssembler::LoadParentFramePointer() {
     401       15186 :   return raw_assembler()->LoadParentFramePointer();
     402             : }
     403             : 
     404          31 : Node* CodeAssembler::LoadStackPointer() {
     405          31 :   return raw_assembler()->LoadStackPointer();
     406             : }
     407             : 
     408             : #define DEFINE_CODE_ASSEMBLER_BINARY_OP(name, ResType, Arg1Type, Arg2Type) \
     409             :   TNode<ResType> CodeAssembler::name(SloppyTNode<Arg1Type> a,              \
     410             :                                      SloppyTNode<Arg2Type> b) {            \
     411             :     return UncheckedCast<ResType>(raw_assembler()->name(a, b));            \
     412             :   }
     413     1191052 : CODE_ASSEMBLER_BINARY_OP_LIST(DEFINE_CODE_ASSEMBLER_BINARY_OP)
     414             : #undef DEFINE_CODE_ASSEMBLER_BINARY_OP
     415             : 
     416      417004 : TNode<WordT> CodeAssembler::IntPtrAdd(SloppyTNode<WordT> left,
     417             :                                       SloppyTNode<WordT> right) {
     418             :   intptr_t left_constant;
     419      417004 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     420             :   intptr_t right_constant;
     421      417004 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     422      417004 :   if (is_left_constant) {
     423      132801 :     if (is_right_constant) {
     424       15996 :       return IntPtrConstant(left_constant + right_constant);
     425             :     }
     426      124803 :     if (left_constant == 0) {
     427       16598 :       return right;
     428             :     }
     429      284203 :   } else if (is_right_constant) {
     430      239222 :     if (right_constant == 0) {
     431        1644 :       return left;
     432             :     }
     433             :   }
     434             :   return UncheckedCast<WordT>(raw_assembler()->IntPtrAdd(left, right));
     435             : }
     436             : 
     437       57650 : TNode<WordT> CodeAssembler::IntPtrSub(SloppyTNode<WordT> left,
     438             :                                       SloppyTNode<WordT> right) {
     439             :   intptr_t left_constant;
     440       57650 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     441             :   intptr_t right_constant;
     442       57650 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     443       57650 :   if (is_left_constant) {
     444        3899 :     if (is_right_constant) {
     445        6868 :       return IntPtrConstant(left_constant - right_constant);
     446             :     }
     447       53751 :   } else if (is_right_constant) {
     448       49569 :     if (right_constant == 0) {
     449        3993 :       return left;
     450             :     }
     451             :   }
     452       50223 :   return UncheckedCast<IntPtrT>(raw_assembler()->IntPtrSub(left, right));
     453             : }
     454             : 
     455       26377 : TNode<WordT> CodeAssembler::IntPtrMul(SloppyTNode<WordT> left,
     456             :                                       SloppyTNode<WordT> right) {
     457             :   intptr_t left_constant;
     458       26377 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     459             :   intptr_t right_constant;
     460       26377 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     461       26377 :   if (is_left_constant) {
     462         436 :     if (is_right_constant) {
     463         870 :       return IntPtrConstant(left_constant * right_constant);
     464             :     }
     465           1 :     if (left_constant == 1) {
     466           1 :       return right;
     467             :     }
     468       25941 :   } else if (is_right_constant) {
     469       25941 :     if (right_constant == 1) {
     470        3507 :       return left;
     471             :     }
     472             :   }
     473       22434 :   return UncheckedCast<IntPtrT>(raw_assembler()->IntPtrMul(left, right));
     474             : }
     475             : 
     476        2464 : TNode<WordT> CodeAssembler::WordShl(SloppyTNode<WordT> value, int shift) {
     477        4710 :   return (shift != 0) ? WordShl(value, IntPtrConstant(shift)) : value;
     478             : }
     479             : 
     480       15073 : TNode<WordT> CodeAssembler::WordShr(SloppyTNode<WordT> value, int shift) {
     481       27727 :   return (shift != 0) ? WordShr(value, IntPtrConstant(shift)) : value;
     482             : }
     483             : 
     484       11356 : TNode<Word32T> CodeAssembler::Word32Shr(SloppyTNode<Word32T> value, int shift) {
     485       19017 :   return (shift != 0) ? Word32Shr(value, Int32Constant(shift)) : value;
     486             : }
     487             : 
     488       22075 : TNode<WordT> CodeAssembler::WordOr(SloppyTNode<WordT> left,
     489             :                                    SloppyTNode<WordT> right) {
     490             :   intptr_t left_constant;
     491       22075 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     492             :   intptr_t right_constant;
     493       22075 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     494       22075 :   if (is_left_constant) {
     495        3381 :     if (is_right_constant) {
     496        5768 :       return IntPtrConstant(left_constant | right_constant);
     497             :     }
     498         497 :     if (left_constant == 0) {
     499          94 :       return right;
     500             :     }
     501       18694 :   } else if (is_right_constant) {
     502       11596 :     if (right_constant == 0) {
     503           1 :       return left;
     504             :     }
     505             :   }
     506       19096 :   return UncheckedCast<WordT>(raw_assembler()->WordOr(left, right));
     507             : }
     508             : 
     509      134126 : TNode<WordT> CodeAssembler::WordAnd(SloppyTNode<WordT> left,
     510             :                                     SloppyTNode<WordT> right) {
     511             :   intptr_t left_constant;
     512      134126 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     513             :   intptr_t right_constant;
     514      134126 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     515      134126 :   if (is_left_constant) {
     516         466 :     if (is_right_constant) {
     517         932 :       return IntPtrConstant(left_constant & right_constant);
     518             :     }
     519             :   }
     520      133660 :   return UncheckedCast<WordT>(raw_assembler()->WordAnd(left, right));
     521             : }
     522             : 
     523           2 : TNode<WordT> CodeAssembler::WordXor(SloppyTNode<WordT> left,
     524             :                                     SloppyTNode<WordT> right) {
     525             :   intptr_t left_constant;
     526           2 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     527             :   intptr_t right_constant;
     528           2 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     529           2 :   if (is_left_constant) {
     530           1 :     if (is_right_constant) {
     531           2 :       return IntPtrConstant(left_constant ^ right_constant);
     532             :     }
     533             :   }
     534           1 :   return UncheckedCast<WordT>(raw_assembler()->WordXor(left, right));
     535             : }
     536             : 
     537      183113 : TNode<WordT> CodeAssembler::WordShl(SloppyTNode<WordT> left,
     538             :                                     SloppyTNode<IntegralT> right) {
     539             :   intptr_t left_constant;
     540      183113 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     541             :   intptr_t right_constant;
     542      183113 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     543      183113 :   if (is_left_constant) {
     544        1272 :     if (is_right_constant) {
     545        2482 :       return IntPtrConstant(left_constant << right_constant);
     546             :     }
     547      181841 :   } else if (is_right_constant) {
     548      181841 :     if (right_constant == 0) {
     549           0 :       return left;
     550             :     }
     551             :   }
     552      181872 :   return UncheckedCast<WordT>(raw_assembler()->WordShl(left, right));
     553             : }
     554             : 
     555       28459 : TNode<WordT> CodeAssembler::WordShr(SloppyTNode<WordT> left,
     556             :                                     SloppyTNode<IntegralT> right) {
     557             :   intptr_t left_constant;
     558       28459 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     559             :   intptr_t right_constant;
     560       28459 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     561       28459 :   if (is_left_constant) {
     562        2606 :     if (is_right_constant) {
     563        2606 :       return IntPtrConstant(static_cast<uintptr_t>(left_constant) >>
     564        5212 :                             right_constant);
     565             :     }
     566       25853 :   } else if (is_right_constant) {
     567       25853 :     if (right_constant == 0) {
     568           0 :       return left;
     569             :     }
     570             :   }
     571       25853 :   return UncheckedCast<WordT>(raw_assembler()->WordShr(left, right));
     572             : }
     573             : 
     574       62917 : TNode<WordT> CodeAssembler::WordSar(SloppyTNode<WordT> left,
     575             :                                     SloppyTNode<IntegralT> right) {
     576             :   intptr_t left_constant;
     577       62917 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     578             :   intptr_t right_constant;
     579       62917 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     580       62917 :   if (is_left_constant) {
     581           2 :     if (is_right_constant) {
     582           4 :       return IntPtrConstant(left_constant >> right_constant);
     583             :     }
     584       62915 :   } else if (is_right_constant) {
     585       62915 :     if (right_constant == 0) {
     586           1 :       return left;
     587             :     }
     588             :   }
     589       62914 :   return UncheckedCast<WordT>(raw_assembler()->WordSar(left, right));
     590             : }
     591             : 
     592        2511 : TNode<Word32T> CodeAssembler::Word32Or(SloppyTNode<Word32T> left,
     593             :                                        SloppyTNode<Word32T> right) {
     594             :   int32_t left_constant;
     595        2511 :   bool is_left_constant = ToInt32Constant(left, left_constant);
     596             :   int32_t right_constant;
     597        2511 :   bool is_right_constant = ToInt32Constant(right, right_constant);
     598        2511 :   if (is_left_constant) {
     599           0 :     if (is_right_constant) {
     600           0 :       return Int32Constant(left_constant | right_constant);
     601             :     }
     602           0 :     if (left_constant == 0) {
     603           0 :       return right;
     604             :     }
     605        2511 :   } else if (is_right_constant) {
     606           0 :     if (right_constant == 0) {
     607           0 :       return left;
     608             :     }
     609             :   }
     610        2511 :   return UncheckedCast<Word32T>(raw_assembler()->Word32Or(left, right));
     611             : }
     612             : 
     613       60268 : TNode<Word32T> CodeAssembler::Word32And(SloppyTNode<Word32T> left,
     614             :                                         SloppyTNode<Word32T> right) {
     615             :   int32_t left_constant;
     616       60268 :   bool is_left_constant = ToInt32Constant(left, left_constant);
     617             :   int32_t right_constant;
     618       60268 :   bool is_right_constant = ToInt32Constant(right, right_constant);
     619       60268 :   if (is_left_constant) {
     620           6 :     if (is_right_constant) {
     621          12 :       return Int32Constant(left_constant & right_constant);
     622             :     }
     623             :   }
     624       60262 :   return UncheckedCast<Word32T>(raw_assembler()->Word32And(left, right));
     625             : }
     626             : 
     627        4211 : TNode<Word32T> CodeAssembler::Word32Xor(SloppyTNode<Word32T> left,
     628             :                                         SloppyTNode<Word32T> right) {
     629             :   int32_t left_constant;
     630        4211 :   bool is_left_constant = ToInt32Constant(left, left_constant);
     631             :   int32_t right_constant;
     632        4211 :   bool is_right_constant = ToInt32Constant(right, right_constant);
     633        4211 :   if (is_left_constant) {
     634           6 :     if (is_right_constant) {
     635          12 :       return Int32Constant(left_constant ^ right_constant);
     636             :     }
     637             :   }
     638        4205 :   return UncheckedCast<Word32T>(raw_assembler()->Word32Xor(left, right));
     639             : }
     640             : 
     641        2466 : TNode<Word32T> CodeAssembler::Word32Shl(SloppyTNode<Word32T> left,
     642             :                                         SloppyTNode<Word32T> right) {
     643             :   int32_t left_constant;
     644        2466 :   bool is_left_constant = ToInt32Constant(left, left_constant);
     645             :   int32_t right_constant;
     646        2466 :   bool is_right_constant = ToInt32Constant(right, right_constant);
     647        2466 :   if (is_left_constant) {
     648           0 :     if (is_right_constant) {
     649           0 :       return Int32Constant(left_constant << right_constant);
     650             :     }
     651        2466 :   } else if (is_right_constant) {
     652        2249 :     if (right_constant == 0) {
     653           0 :       return left;
     654             :     }
     655             :   }
     656        2466 :   return UncheckedCast<Word32T>(raw_assembler()->Word32Shl(left, right));
     657             : }
     658             : 
     659       14899 : TNode<Word32T> CodeAssembler::Word32Shr(SloppyTNode<Word32T> left,
     660             :                                         SloppyTNode<Word32T> right) {
     661             :   int32_t left_constant;
     662       14899 :   bool is_left_constant = ToInt32Constant(left, left_constant);
     663             :   int32_t right_constant;
     664       14899 :   bool is_right_constant = ToInt32Constant(right, right_constant);
     665       14899 :   if (is_left_constant) {
     666           0 :     if (is_right_constant) {
     667           0 :       return Int32Constant(static_cast<uint32_t>(left_constant) >>
     668           0 :                            right_constant);
     669             :     }
     670       14899 :   } else if (is_right_constant) {
     671       14217 :     if (right_constant == 0) {
     672           0 :       return left;
     673             :     }
     674             :   }
     675       14899 :   return UncheckedCast<Word32T>(raw_assembler()->Word32Shr(left, right));
     676             : }
     677             : 
     678         217 : TNode<Word32T> CodeAssembler::Word32Sar(SloppyTNode<Word32T> left,
     679             :                                         SloppyTNode<Word32T> right) {
     680             :   int32_t left_constant;
     681         217 :   bool is_left_constant = ToInt32Constant(left, left_constant);
     682             :   int32_t right_constant;
     683         217 :   bool is_right_constant = ToInt32Constant(right, right_constant);
     684         217 :   if (is_left_constant) {
     685           0 :     if (is_right_constant) {
     686           0 :       return Int32Constant(left_constant >> right_constant);
     687             :     }
     688         217 :   } else if (is_right_constant) {
     689           0 :     if (right_constant == 0) {
     690           0 :       return left;
     691             :     }
     692             :   }
     693         217 :   return UncheckedCast<Word32T>(raw_assembler()->Word32Sar(left, right));
     694             : }
     695             : 
     696           0 : TNode<Word64T> CodeAssembler::Word64Or(SloppyTNode<Word64T> left,
     697             :                                        SloppyTNode<Word64T> right) {
     698             :   int64_t left_constant;
     699             :   bool is_left_constant = ToInt64Constant(left, left_constant);
     700             :   int64_t right_constant;
     701             :   bool is_right_constant = ToInt64Constant(right, right_constant);
     702           0 :   if (is_left_constant) {
     703           0 :     if (is_right_constant) {
     704           0 :       return Int64Constant(left_constant | right_constant);
     705             :     }
     706           0 :     if (left_constant == 0) {
     707           0 :       return right;
     708             :     }
     709           0 :   } else if (is_right_constant) {
     710           0 :     if (right_constant == 0) {
     711           0 :       return left;
     712             :     }
     713             :   }
     714           0 :   return UncheckedCast<Word64T>(raw_assembler()->Word64Or(left, right));
     715             : }
     716             : 
     717           0 : TNode<Word64T> CodeAssembler::Word64And(SloppyTNode<Word64T> left,
     718             :                                         SloppyTNode<Word64T> right) {
     719             :   int64_t left_constant;
     720             :   bool is_left_constant = ToInt64Constant(left, left_constant);
     721             :   int64_t right_constant;
     722             :   bool is_right_constant = ToInt64Constant(right, right_constant);
     723           0 :   if (is_left_constant) {
     724           0 :     if (is_right_constant) {
     725           0 :       return Int64Constant(left_constant & right_constant);
     726             :     }
     727             :   }
     728           0 :   return UncheckedCast<Word64T>(raw_assembler()->Word64And(left, right));
     729             : }
     730             : 
     731           0 : TNode<Word64T> CodeAssembler::Word64Xor(SloppyTNode<Word64T> left,
     732             :                                         SloppyTNode<Word64T> right) {
     733             :   int64_t left_constant;
     734             :   bool is_left_constant = ToInt64Constant(left, left_constant);
     735             :   int64_t right_constant;
     736             :   bool is_right_constant = ToInt64Constant(right, right_constant);
     737           0 :   if (is_left_constant) {
     738           0 :     if (is_right_constant) {
     739           0 :       return Int64Constant(left_constant ^ right_constant);
     740             :     }
     741             :   }
     742           0 :   return UncheckedCast<Word64T>(raw_assembler()->Word64Xor(left, right));
     743             : }
     744             : 
     745           0 : TNode<Word64T> CodeAssembler::Word64Shl(SloppyTNode<Word64T> left,
     746             :                                         SloppyTNode<Word64T> right) {
     747             :   int64_t left_constant;
     748             :   bool is_left_constant = ToInt64Constant(left, left_constant);
     749             :   int64_t right_constant;
     750             :   bool is_right_constant = ToInt64Constant(right, right_constant);
     751           0 :   if (is_left_constant) {
     752           0 :     if (is_right_constant) {
     753           0 :       return Int64Constant(left_constant << right_constant);
     754             :     }
     755           0 :   } else if (is_right_constant) {
     756           0 :     if (right_constant == 0) {
     757           0 :       return left;
     758             :     }
     759             :   }
     760           0 :   return UncheckedCast<Word64T>(raw_assembler()->Word64Shl(left, right));
     761             : }
     762             : 
     763           0 : TNode<Word64T> CodeAssembler::Word64Shr(SloppyTNode<Word64T> left,
     764             :                                         SloppyTNode<Word64T> right) {
     765             :   int64_t left_constant;
     766             :   bool is_left_constant = ToInt64Constant(left, left_constant);
     767             :   int64_t right_constant;
     768             :   bool is_right_constant = ToInt64Constant(right, right_constant);
     769           0 :   if (is_left_constant) {
     770           0 :     if (is_right_constant) {
     771           0 :       return Int64Constant(static_cast<uint64_t>(left_constant) >>
     772           0 :                            right_constant);
     773             :     }
     774           0 :   } else if (is_right_constant) {
     775           0 :     if (right_constant == 0) {
     776           0 :       return left;
     777             :     }
     778             :   }
     779           0 :   return UncheckedCast<Word64T>(raw_assembler()->Word64Shr(left, right));
     780             : }
     781             : 
     782           0 : TNode<Word64T> CodeAssembler::Word64Sar(SloppyTNode<Word64T> left,
     783             :                                         SloppyTNode<Word64T> right) {
     784             :   int64_t left_constant;
     785             :   bool is_left_constant = ToInt64Constant(left, left_constant);
     786             :   int64_t right_constant;
     787             :   bool is_right_constant = ToInt64Constant(right, right_constant);
     788           0 :   if (is_left_constant) {
     789           0 :     if (is_right_constant) {
     790           0 :       return Int64Constant(left_constant >> right_constant);
     791             :     }
     792           0 :   } else if (is_right_constant) {
     793           0 :     if (right_constant == 0) {
     794           0 :       return left;
     795             :     }
     796             :   }
     797           0 :   return UncheckedCast<Word64T>(raw_assembler()->Word64Sar(left, right));
     798             : }
     799             : 
     800       39975 : TNode<UintPtrT> CodeAssembler::ChangeUint32ToWord(SloppyTNode<Word32T> value) {
     801       39975 :   if (raw_assembler()->machine()->Is64()) {
     802             :     return UncheckedCast<UintPtrT>(
     803       39975 :         raw_assembler()->ChangeUint32ToUint64(value));
     804             :   }
     805             :   return ReinterpretCast<UintPtrT>(value);
     806             : }
     807             : 
     808       44142 : TNode<IntPtrT> CodeAssembler::ChangeInt32ToIntPtr(SloppyTNode<Word32T> value) {
     809       44142 :   if (raw_assembler()->machine()->Is64()) {
     810       44142 :     return ReinterpretCast<IntPtrT>(raw_assembler()->ChangeInt32ToInt64(value));
     811             :   }
     812             :   return ReinterpretCast<IntPtrT>(value);
     813             : }
     814             : 
     815          93 : TNode<UintPtrT> CodeAssembler::ChangeFloat64ToUintPtr(
     816             :     SloppyTNode<Float64T> value) {
     817          93 :   if (raw_assembler()->machine()->Is64()) {
     818             :     return ReinterpretCast<UintPtrT>(
     819          93 :         raw_assembler()->ChangeFloat64ToUint64(value));
     820             :   }
     821             :   return ReinterpretCast<UintPtrT>(
     822           0 :       raw_assembler()->ChangeFloat64ToUint32(value));
     823             : }
     824             : 
     825         483 : Node* CodeAssembler::RoundIntPtrToFloat64(Node* value) {
     826         483 :   if (raw_assembler()->machine()->Is64()) {
     827         483 :     return raw_assembler()->RoundInt64ToFloat64(value);
     828             :   }
     829           0 :   return raw_assembler()->ChangeInt32ToFloat64(value);
     830             : }
     831             : 
     832             : #define DEFINE_CODE_ASSEMBLER_UNARY_OP(name, ResType, ArgType) \
     833             :   TNode<ResType> CodeAssembler::name(SloppyTNode<ArgType> a) { \
     834             :     return UncheckedCast<ResType>(raw_assembler()->name(a));   \
     835             :   }
     836      997404 : CODE_ASSEMBLER_UNARY_OP_LIST(DEFINE_CODE_ASSEMBLER_UNARY_OP)
     837             : #undef DEFINE_CODE_ASSEMBLER_UNARY_OP
     838             : 
     839       79156 : Node* CodeAssembler::Load(MachineType rep, Node* base) {
     840       79156 :   return raw_assembler()->Load(rep, base);
     841             : }
     842             : 
     843      736725 : Node* CodeAssembler::Load(MachineType rep, Node* base, Node* offset) {
     844      736917 :   return raw_assembler()->Load(rep, base, offset);
     845             : }
     846             : 
     847         186 : Node* CodeAssembler::AtomicLoad(MachineType rep, Node* base, Node* offset) {
     848         186 :   return raw_assembler()->AtomicLoad(rep, base, offset);
     849             : }
     850             : 
     851      198332 : TNode<Object> CodeAssembler::LoadRoot(Heap::RootListIndex root_index) {
     852      198332 :   if (isolate()->heap()->RootCanBeTreatedAsConstant(root_index)) {
     853             :     Handle<Object> root = isolate()->heap()->root_handle(root_index);
     854      198140 :     if (root->IsSmi()) {
     855           0 :       return SmiConstant(Smi::cast(*root));
     856             :     } else {
     857      198140 :       return HeapConstant(Handle<HeapObject>::cast(root));
     858             :     }
     859             :   }
     860             : 
     861             :   Node* roots_array_start =
     862         192 :       ExternalConstant(ExternalReference::roots_array_start(isolate()));
     863             :   return UncheckedCast<Object>(Load(MachineType::AnyTagged(), roots_array_start,
     864         192 :                                     IntPtrConstant(root_index * kPointerSize)));
     865             : }
     866             : 
     867           0 : Node* CodeAssembler::Store(Node* base, Node* value) {
     868             :   return raw_assembler()->Store(MachineRepresentation::kTagged, base, value,
     869           0 :                                 kFullWriteBarrier);
     870             : }
     871             : 
     872       26550 : Node* CodeAssembler::Store(Node* base, Node* offset, Node* value) {
     873             :   return raw_assembler()->Store(MachineRepresentation::kTagged, base, offset,
     874       26550 :                                 value, kFullWriteBarrier);
     875             : }
     876             : 
     877        3971 : Node* CodeAssembler::StoreWithMapWriteBarrier(Node* base, Node* offset,
     878             :                                               Node* value) {
     879             :   return raw_assembler()->Store(MachineRepresentation::kTagged, base, offset,
     880        3971 :                                 value, kMapWriteBarrier);
     881             : }
     882             : 
     883       38341 : Node* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base,
     884             :                                          Node* value) {
     885       38341 :   return raw_assembler()->Store(rep, base, value, kNoWriteBarrier);
     886             : }
     887             : 
     888      244133 : Node* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base,
     889             :                                          Node* offset, Node* value) {
     890      244133 :   return raw_assembler()->Store(rep, base, offset, value, kNoWriteBarrier);
     891             : }
     892             : 
     893          93 : Node* CodeAssembler::AtomicStore(MachineRepresentation rep, Node* base,
     894             :                                  Node* offset, Node* value) {
     895          93 :   return raw_assembler()->AtomicStore(rep, base, offset, value);
     896             : }
     897             : 
     898             : #define ATOMIC_FUNCTION(name)                                        \
     899             :   Node* CodeAssembler::Atomic##name(MachineType type, Node* base,    \
     900             :                                     Node* offset, Node* value) {     \
     901             :     return raw_assembler()->Atomic##name(type, base, offset, value); \
     902             :   }
     903         372 : ATOMIC_FUNCTION(Exchange);
     904         372 : ATOMIC_FUNCTION(Add);
     905         372 : ATOMIC_FUNCTION(Sub);
     906         372 : ATOMIC_FUNCTION(And);
     907         372 : ATOMIC_FUNCTION(Or);
     908         372 : ATOMIC_FUNCTION(Xor);
     909             : #undef ATOMIC_FUNCTION
     910             : 
     911         186 : Node* CodeAssembler::AtomicCompareExchange(MachineType type, Node* base,
     912             :                                            Node* offset, Node* old_value,
     913             :                                            Node* new_value) {
     914             :   return raw_assembler()->AtomicCompareExchange(type, base, offset, old_value,
     915         186 :                                                 new_value);
     916             : }
     917             : 
     918           0 : Node* CodeAssembler::StoreRoot(Heap::RootListIndex root_index, Node* value) {
     919             :   DCHECK(Heap::RootCanBeWrittenAfterInitialization(root_index));
     920             :   Node* roots_array_start =
     921           0 :       ExternalConstant(ExternalReference::roots_array_start(isolate()));
     922             :   return StoreNoWriteBarrier(MachineRepresentation::kTagged, roots_array_start,
     923           0 :                              IntPtrConstant(root_index * kPointerSize), value);
     924             : }
     925             : 
     926           0 : Node* CodeAssembler::Retain(Node* value) {
     927           0 :   return raw_assembler()->Retain(value);
     928             : }
     929             : 
     930        3496 : Node* CodeAssembler::Projection(int index, Node* value) {
     931        3496 :   return raw_assembler()->Projection(index, value);
     932             : }
     933             : 
     934        2287 : void CodeAssembler::GotoIfException(Node* node, Label* if_exception,
     935             :                                     Variable* exception_var) {
     936             :   DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
     937             : 
     938        2287 :   if (if_exception == nullptr) {
     939             :     // If no handler is supplied, don't add continuations
     940         496 :     return;
     941             :   }
     942             : 
     943        1791 :   Label success(this), exception(this, Label::kDeferred);
     944        1791 :   success.MergeVariables();
     945        1791 :   exception.MergeVariables();
     946             : 
     947        3582 :   raw_assembler()->Continuations(node, success.label_, exception.label_);
     948             : 
     949             :   Bind(&exception);
     950        1791 :   const Operator* op = raw_assembler()->common()->IfException();
     951             :   Node* exception_value = raw_assembler()->AddNode(op, node, node);
     952        1791 :   if (exception_var != nullptr) {
     953             :     exception_var->Bind(exception_value);
     954             :   }
     955        1791 :   Goto(if_exception);
     956             : 
     957        1791 :   Bind(&success);
     958             : }
     959             : 
     960             : template <class... TArgs>
     961       76968 : TNode<Object> CodeAssembler::CallRuntimeImpl(Runtime::FunctionId function,
     962             :                                              SloppyTNode<Object> context,
     963             :                                              TArgs... args) {
     964             :   int argc = static_cast<int>(sizeof...(args));
     965       76968 :   CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
     966             :       zone(), function, argc, Operator::kNoProperties,
     967       76968 :       CallDescriptor::kNoFlags);
     968       76968 :   int return_count = static_cast<int>(desc->ReturnCount());
     969             : 
     970             :   Node* centry =
     971       76968 :       HeapConstant(CodeFactory::RuntimeCEntry(isolate(), return_count));
     972      153936 :   Node* ref = ExternalConstant(ExternalReference(function, isolate()));
     973             :   Node* arity = Int32Constant(argc);
     974             : 
     975      265177 :   Node* nodes[] = {centry, args..., ref, arity, context};
     976             : 
     977             :   CallPrologue();
     978       76968 :   Node* return_value = raw_assembler()->CallN(desc, arraysize(nodes), nodes);
     979             :   CallEpilogue();
     980       76968 :   return UncheckedCast<Object>(return_value);
     981             : }
     982             : 
     983             : // Instantiate CallRuntime() for argument counts used by CSA-generated code
     984             : #define INSTANTIATE(...)                                                   \
     985             :   template V8_EXPORT_PRIVATE TNode<Object> CodeAssembler::CallRuntimeImpl( \
     986             :       Runtime::FunctionId, __VA_ARGS__);
     987             : REPEAT_1_TO_7(INSTANTIATE, SloppyTNode<Object>)
     988             : #undef INSTANTIATE
     989             : 
     990             : template <class... TArgs>
     991        9408 : TNode<Object> CodeAssembler::TailCallRuntimeImpl(Runtime::FunctionId function,
     992             :                                                  SloppyTNode<Object> context,
     993             :                                                  TArgs... args) {
     994             :   int argc = static_cast<int>(sizeof...(args));
     995        9408 :   CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
     996             :       zone(), function, argc, Operator::kNoProperties,
     997        9408 :       CallDescriptor::kSupportsTailCalls);
     998        9408 :   int return_count = static_cast<int>(desc->ReturnCount());
     999             : 
    1000             :   Node* centry =
    1001        9408 :       HeapConstant(CodeFactory::RuntimeCEntry(isolate(), return_count));
    1002       18816 :   Node* ref = ExternalConstant(ExternalReference(function, isolate()));
    1003             :   Node* arity = Int32Constant(argc);
    1004             : 
    1005       58363 :   Node* nodes[] = {centry, args..., ref, arity, context};
    1006             : 
    1007             :   return UncheckedCast<Object>(
    1008        9408 :       raw_assembler()->TailCallN(desc, arraysize(nodes), nodes));
    1009             : }
    1010             : 
    1011             : // Instantiate TailCallRuntime() for argument counts used by CSA-generated code
    1012             : #define INSTANTIATE(...)                                                       \
    1013             :   template V8_EXPORT_PRIVATE TNode<Object> CodeAssembler::TailCallRuntimeImpl( \
    1014             :       Runtime::FunctionId, __VA_ARGS__);
    1015             : REPEAT_1_TO_7(INSTANTIATE, SloppyTNode<Object>)
    1016             : #undef INSTANTIATE
    1017             : 
    1018             : template <class... TArgs>
    1019       44935 : Node* CodeAssembler::CallStubR(const CallInterfaceDescriptor& descriptor,
    1020             :                                size_t result_size, Node* target, Node* context,
    1021             :                                TArgs... args) {
    1022       44935 :   Node* nodes[] = {target, args..., context};
    1023       44935 :   return CallStubN(descriptor, result_size, arraysize(nodes), nodes);
    1024             : }
    1025             : 
    1026             : // Instantiate CallStubR() for argument counts used by CSA-generated code.
    1027             : #define INSTANTIATE(...)                                     \
    1028             :   template V8_EXPORT_PRIVATE Node* CodeAssembler::CallStubR( \
    1029             :       const CallInterfaceDescriptor& descriptor, size_t, Node*, __VA_ARGS__);
    1030             : REPEAT_1_TO_11(INSTANTIATE, Node*)
    1031             : #undef INSTANTIATE
    1032             : 
    1033       45958 : Node* CodeAssembler::CallStubN(const CallInterfaceDescriptor& descriptor,
    1034             :                                size_t result_size, int input_count,
    1035             :                                Node* const* inputs) {
    1036             :   // 2 is for target and context.
    1037             :   DCHECK_LE(2, input_count);
    1038       45958 :   int argc = input_count - 2;
    1039             :   DCHECK_LE(descriptor.GetParameterCount(), argc);
    1040             :   // Extra arguments not mentioned in the descriptor are passed on the stack.
    1041       45958 :   int stack_parameter_count = argc - descriptor.GetRegisterParameterCount();
    1042             :   DCHECK_LE(descriptor.GetStackParameterCount(), stack_parameter_count);
    1043             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    1044             :       isolate(), zone(), descriptor, stack_parameter_count,
    1045             :       CallDescriptor::kNoFlags, Operator::kNoProperties,
    1046       45958 :       MachineType::AnyTagged(), result_size);
    1047             : 
    1048             :   CallPrologue();
    1049       45958 :   Node* return_value = raw_assembler()->CallN(desc, input_count, inputs);
    1050             :   CallEpilogue();
    1051       45958 :   return return_value;
    1052             : }
    1053             : 
    1054             : template <class... TArgs>
    1055        2883 : Node* CodeAssembler::TailCallStubImpl(const CallInterfaceDescriptor& descriptor,
    1056             :                                       Node* target, Node* context,
    1057             :                                       TArgs... args) {
    1058             :   DCHECK_EQ(descriptor.GetParameterCount(), sizeof...(args));
    1059             :   size_t result_size = 1;
    1060             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    1061             :       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    1062             :       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
    1063        2883 :       MachineType::AnyTagged(), result_size);
    1064             : 
    1065        2883 :   Node* nodes[] = {target, args..., context};
    1066        5766 :   CHECK_EQ(descriptor.GetParameterCount() + 2, arraysize(nodes));
    1067        2883 :   return raw_assembler()->TailCallN(desc, arraysize(nodes), nodes);
    1068             : }
    1069             : 
    1070             : // Instantiate TailCallStub() for argument counts used by CSA-generated code
    1071             : #define INSTANTIATE(...)                                            \
    1072             :   template V8_EXPORT_PRIVATE Node* CodeAssembler::TailCallStubImpl( \
    1073             :       const CallInterfaceDescriptor& descriptor, Node*, __VA_ARGS__);
    1074             : REPEAT_1_TO_12(INSTANTIATE, Node*)
    1075             : #undef INSTANTIATE
    1076             : 
    1077             : template <class... TArgs>
    1078        1116 : Node* CodeAssembler::TailCallStubThenBytecodeDispatch(
    1079             :     const CallInterfaceDescriptor& descriptor, Node* target, Node* context,
    1080             :     TArgs... args) {
    1081             :   DCHECK_LE(descriptor.GetParameterCount(), sizeof...(args));
    1082             :   // Extra arguments not mentioned in the descriptor are passed on the stack.
    1083             :   int stack_parameter_count =
    1084        1116 :       sizeof...(args) - descriptor.GetRegisterParameterCount();
    1085             :   DCHECK_LE(descriptor.GetStackParameterCount(), stack_parameter_count);
    1086             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    1087             :       isolate(), zone(), descriptor, stack_parameter_count,
    1088             :       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
    1089        1116 :       MachineType::AnyTagged(), 0);
    1090             : 
    1091        1116 :   Node* nodes[] = {target, args..., context};
    1092        1116 :   return raw_assembler()->TailCallN(desc, arraysize(nodes), nodes);
    1093             : }
    1094             : 
    1095             : // Instantiate TailCallJSAndBytecodeDispatch() for argument counts used by
    1096             : // CSA-generated code
    1097             : #define INSTANTIATE(...)                           \
    1098             :   template V8_EXPORT_PRIVATE Node*                 \
    1099             :   CodeAssembler::TailCallStubThenBytecodeDispatch( \
    1100             :       const CallInterfaceDescriptor&, Node*, Node*, Node*, __VA_ARGS__);
    1101             : REPEAT_1_TO_7(INSTANTIATE, Node*)
    1102             : #undef INSTANTIATE
    1103             : 
    1104             : template <class... TArgs>
    1105       16616 : Node* CodeAssembler::TailCallBytecodeDispatch(
    1106             :     const CallInterfaceDescriptor& descriptor, Node* target, TArgs... args) {
    1107             :   DCHECK_EQ(descriptor.GetParameterCount(), sizeof...(args));
    1108             :   CallDescriptor* desc = Linkage::GetBytecodeDispatchCallDescriptor(
    1109       16616 :       isolate(), zone(), descriptor, descriptor.GetStackParameterCount());
    1110             : 
    1111       16616 :   Node* nodes[] = {target, args...};
    1112       33232 :   CHECK_EQ(descriptor.GetParameterCount() + 1, arraysize(nodes));
    1113       16616 :   return raw_assembler()->TailCallN(desc, arraysize(nodes), nodes);
    1114             : }
    1115             : 
    1116             : // Instantiate TailCallBytecodeDispatch() for argument counts used by
    1117             : // CSA-generated code
    1118             : template V8_EXPORT_PRIVATE Node* CodeAssembler::TailCallBytecodeDispatch(
    1119             :     const CallInterfaceDescriptor& descriptor, Node* target, Node*, Node*,
    1120             :     Node*, Node*);
    1121             : 
    1122           0 : Node* CodeAssembler::CallCFunctionN(Signature<MachineType>* signature,
    1123             :                                     int input_count, Node* const* inputs) {
    1124           0 :   CallDescriptor* desc = Linkage::GetSimplifiedCDescriptor(zone(), signature);
    1125           0 :   return raw_assembler()->CallN(desc, input_count, inputs);
    1126             : }
    1127             : 
    1128         124 : Node* CodeAssembler::CallCFunction1(MachineType return_type,
    1129             :                                     MachineType arg0_type, Node* function,
    1130             :                                     Node* arg0) {
    1131             :   return raw_assembler()->CallCFunction1(return_type, arg0_type, function,
    1132         124 :                                          arg0);
    1133             : }
    1134             : 
    1135         124 : Node* CodeAssembler::CallCFunction1WithCallerSavedRegisters(
    1136             :     MachineType return_type, MachineType arg0_type, Node* function, Node* arg0,
    1137             :     SaveFPRegsMode mode) {
    1138             :   DCHECK(return_type.LessThanOrEqualPointerSize());
    1139             :   return raw_assembler()->CallCFunction1WithCallerSavedRegisters(
    1140         124 :       return_type, arg0_type, function, arg0, mode);
    1141             : }
    1142             : 
    1143        1364 : Node* CodeAssembler::CallCFunction2(MachineType return_type,
    1144             :                                     MachineType arg0_type,
    1145             :                                     MachineType arg1_type, Node* function,
    1146             :                                     Node* arg0, Node* arg1) {
    1147             :   return raw_assembler()->CallCFunction2(return_type, arg0_type, arg1_type,
    1148        1364 :                                          function, arg0, arg1);
    1149             : }
    1150             : 
    1151         217 : Node* CodeAssembler::CallCFunction3(MachineType return_type,
    1152             :                                     MachineType arg0_type,
    1153             :                                     MachineType arg1_type,
    1154             :                                     MachineType arg2_type, Node* function,
    1155             :                                     Node* arg0, Node* arg1, Node* arg2) {
    1156             :   return raw_assembler()->CallCFunction3(return_type, arg0_type, arg1_type,
    1157         217 :                                          arg2_type, function, arg0, arg1, arg2);
    1158             : }
    1159             : 
    1160          68 : Node* CodeAssembler::CallCFunction3WithCallerSavedRegisters(
    1161             :     MachineType return_type, MachineType arg0_type, MachineType arg1_type,
    1162             :     MachineType arg2_type, Node* function, Node* arg0, Node* arg1, Node* arg2,
    1163             :     SaveFPRegsMode mode) {
    1164             :   DCHECK(return_type.LessThanOrEqualPointerSize());
    1165             :   return raw_assembler()->CallCFunction3WithCallerSavedRegisters(
    1166             :       return_type, arg0_type, arg1_type, arg2_type, function, arg0, arg1, arg2,
    1167          68 :       mode);
    1168             : }
    1169             : 
    1170         372 : Node* CodeAssembler::CallCFunction6(
    1171             :     MachineType return_type, MachineType arg0_type, MachineType arg1_type,
    1172             :     MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
    1173             :     MachineType arg5_type, Node* function, Node* arg0, Node* arg1, Node* arg2,
    1174             :     Node* arg3, Node* arg4, Node* arg5) {
    1175             :   return raw_assembler()->CallCFunction6(
    1176             :       return_type, arg0_type, arg1_type, arg2_type, arg3_type, arg4_type,
    1177         372 :       arg5_type, function, arg0, arg1, arg2, arg3, arg4, arg5);
    1178             : }
    1179             : 
    1180         316 : Node* CodeAssembler::CallCFunction9(
    1181             :     MachineType return_type, MachineType arg0_type, MachineType arg1_type,
    1182             :     MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
    1183             :     MachineType arg5_type, MachineType arg6_type, MachineType arg7_type,
    1184             :     MachineType arg8_type, Node* function, Node* arg0, Node* arg1, Node* arg2,
    1185             :     Node* arg3, Node* arg4, Node* arg5, Node* arg6, Node* arg7, Node* arg8) {
    1186             :   return raw_assembler()->CallCFunction9(
    1187             :       return_type, arg0_type, arg1_type, arg2_type, arg3_type, arg4_type,
    1188             :       arg5_type, arg6_type, arg7_type, arg8_type, function, arg0, arg1, arg2,
    1189         316 :       arg3, arg4, arg5, arg6, arg7, arg8);
    1190             : }
    1191             : 
    1192      410158 : void CodeAssembler::Goto(Label* label) {
    1193      410158 :   label->MergeVariables();
    1194      820316 :   raw_assembler()->Goto(label->label_);
    1195      410158 : }
    1196             : 
    1197      260407 : void CodeAssembler::GotoIf(SloppyTNode<IntegralT> condition,
    1198             :                            Label* true_label) {
    1199             :   Label false_label(this);
    1200      260407 :   Branch(condition, true_label, &false_label);
    1201      260407 :   Bind(&false_label);
    1202      260407 : }
    1203             : 
    1204       99184 : void CodeAssembler::GotoIfNot(SloppyTNode<IntegralT> condition,
    1205             :                               Label* false_label) {
    1206             :   Label true_label(this);
    1207       99184 :   Branch(condition, &true_label, false_label);
    1208       99184 :   Bind(&true_label);
    1209       99184 : }
    1210             : 
    1211      576171 : void CodeAssembler::Branch(SloppyTNode<IntegralT> condition, Label* true_label,
    1212             :                            Label* false_label) {
    1213      576171 :   true_label->MergeVariables();
    1214      576171 :   false_label->MergeVariables();
    1215             :   return raw_assembler()->Branch(condition, true_label->label_,
    1216     1152342 :                                  false_label->label_);
    1217             : }
    1218             : 
    1219        4234 : void CodeAssembler::Switch(Node* index, Label* default_label,
    1220             :                            const int32_t* case_values, Label** case_labels,
    1221             :                            size_t case_count) {
    1222             :   RawMachineLabel** labels =
    1223        4234 :       new (zone()->New(sizeof(RawMachineLabel*) * case_count))
    1224        4234 :           RawMachineLabel*[case_count];
    1225       35093 :   for (size_t i = 0; i < case_count; ++i) {
    1226       30859 :     labels[i] = case_labels[i]->label_;
    1227       30859 :     case_labels[i]->MergeVariables();
    1228             :   }
    1229        4234 :   default_label->MergeVariables();
    1230             :   return raw_assembler()->Switch(index, default_label->label_, case_values,
    1231        8468 :                                  labels, case_count);
    1232             : }
    1233             : 
    1234          31 : bool CodeAssembler::UnalignedLoadSupported(MachineRepresentation rep) const {
    1235          31 :   return raw_assembler()->machine()->UnalignedLoadSupported(rep);
    1236             : }
    1237          31 : bool CodeAssembler::UnalignedStoreSupported(MachineRepresentation rep) const {
    1238          31 :   return raw_assembler()->machine()->UnalignedStoreSupported(rep);
    1239             : }
    1240             : 
    1241             : // RawMachineAssembler delegate helpers:
    1242      889780 : Isolate* CodeAssembler::isolate() const { return raw_assembler()->isolate(); }
    1243             : 
    1244        4278 : Factory* CodeAssembler::factory() const { return isolate()->factory(); }
    1245             : 
    1246      115360 : Zone* CodeAssembler::zone() const { return raw_assembler()->zone(); }
    1247             : 
    1248           0 : RawMachineAssembler* CodeAssembler::raw_assembler() const {
    1249     9508893 :   return state_->raw_assembler_.get();
    1250             : }
    1251             : 
    1252             : // The core implementation of Variable is stored through an indirection so
    1253             : // that it can outlive the often block-scoped Variable declarations. This is
    1254             : // needed to ensure that variable binding and merging through phis can
    1255             : // properly be verified.
    1256             : class CodeAssemblerVariable::Impl : public ZoneObject {
    1257             :  public:
    1258             :   explicit Impl(MachineRepresentation rep)
    1259             :       :
    1260             : #if DEBUG
    1261             :         debug_info_(AssemblerDebugInfo(nullptr, nullptr, -1)),
    1262             : #endif
    1263             :         value_(nullptr),
    1264      376579 :         rep_(rep) {
    1265             :   }
    1266             : 
    1267             : #if DEBUG
    1268             :   AssemblerDebugInfo debug_info() const { return debug_info_; }
    1269             :   void set_debug_info(AssemblerDebugInfo debug_info) {
    1270             :     debug_info_ = debug_info;
    1271             :   }
    1272             : 
    1273             :   AssemblerDebugInfo debug_info_;
    1274             : #endif  // DEBUG
    1275             :   Node* value_;
    1276             :   MachineRepresentation rep_;
    1277             : };
    1278             : 
    1279      376579 : CodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler,
    1280             :                                              MachineRepresentation rep)
    1281      753158 :     : impl_(new (assembler->zone()) Impl(rep)), state_(assembler->state()) {
    1282      376579 :   state_->variables_.insert(impl_);
    1283      376579 : }
    1284             : 
    1285      203864 : CodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler,
    1286             :                                              MachineRepresentation rep,
    1287             :                                              Node* initial_value)
    1288      203864 :     : CodeAssemblerVariable(assembler, rep) {
    1289             :   Bind(initial_value);
    1290      203864 : }
    1291             : 
    1292             : #if DEBUG
    1293             : CodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler,
    1294             :                                              AssemblerDebugInfo debug_info,
    1295             :                                              MachineRepresentation rep)
    1296             :     : impl_(new (assembler->zone()) Impl(rep)), state_(assembler->state()) {
    1297             :   impl_->set_debug_info(debug_info);
    1298             :   state_->variables_.insert(impl_);
    1299             : }
    1300             : 
    1301             : CodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler,
    1302             :                                              AssemblerDebugInfo debug_info,
    1303             :                                              MachineRepresentation rep,
    1304             :                                              Node* initial_value)
    1305             :     : CodeAssemblerVariable(assembler, debug_info, rep) {
    1306             :   impl_->set_debug_info(debug_info);
    1307             :   Bind(initial_value);
    1308             : }
    1309             : #endif  // DEBUG
    1310             : 
    1311      376579 : CodeAssemblerVariable::~CodeAssemblerVariable() {
    1312      376579 :   state_->variables_.erase(impl_);
    1313      376579 : }
    1314             : 
    1315      760510 : void CodeAssemblerVariable::Bind(Node* value) { impl_->value_ = value; }
    1316             : 
    1317      794162 : Node* CodeAssemblerVariable::value() const {
    1318             : #if DEBUG
    1319             :   if (!IsBound()) {
    1320             :     std::stringstream str;
    1321             :     str << "#Use of unbound variable:"
    1322             :         << "#\n    Variable:      " << *this;
    1323             :     if (state_) {
    1324             :       str << "#\n    Current Block: ";
    1325             :       state_->PrintCurrentBlock(str);
    1326             :     }
    1327             :     FATAL(str.str().c_str());
    1328             :   }
    1329             : #endif  // DEBUG
    1330      794162 :   return impl_->value_;
    1331             : }
    1332             : 
    1333           0 : MachineRepresentation CodeAssemblerVariable::rep() const { return impl_->rep_; }
    1334             : 
    1335       78563 : bool CodeAssemblerVariable::IsBound() const { return impl_->value_ != nullptr; }
    1336             : 
    1337           0 : std::ostream& operator<<(std::ostream& os,
    1338             :                          const CodeAssemblerVariable::Impl& impl) {
    1339             : #if DEBUG
    1340             :   AssemblerDebugInfo info = impl.debug_info();
    1341             :   if (info.name) os << "V" << info;
    1342             : #endif  // DEBUG
    1343           0 :   return os;
    1344             : }
    1345             : 
    1346           0 : std::ostream& operator<<(std::ostream& os,
    1347             :                          const CodeAssemblerVariable& variable) {
    1348             :   os << *variable.impl_;
    1349           0 :   return os;
    1350             : }
    1351             : 
    1352     1052845 : CodeAssemblerLabel::CodeAssemblerLabel(CodeAssembler* assembler,
    1353             :                                        size_t vars_count,
    1354             :                                        CodeAssemblerVariable* const* vars,
    1355             :                                        CodeAssemblerLabel::Type type)
    1356             :     : bound_(false),
    1357             :       merge_count_(0),
    1358             :       state_(assembler->state()),
    1359     2105690 :       label_(nullptr) {
    1360     1052845 :   void* buffer = assembler->zone()->New(sizeof(RawMachineLabel));
    1361             :   label_ = new (buffer)
    1362             :       RawMachineLabel(type == kDeferred ? RawMachineLabel::kDeferred
    1363     2105690 :                                         : RawMachineLabel::kNonDeferred);
    1364     1206511 :   for (size_t i = 0; i < vars_count; ++i) {
    1365      153666 :     variable_phis_[vars[i]->impl_] = nullptr;
    1366             :   }
    1367     1052845 : }
    1368             : 
    1369     2114618 : CodeAssemblerLabel::~CodeAssemblerLabel() { label_->~RawMachineLabel(); }
    1370             : 
    1371     1601175 : void CodeAssemblerLabel::MergeVariables() {
    1372     1601175 :   ++merge_count_;
    1373    14170978 :   for (CodeAssemblerVariable::Impl* var : state_->variables_) {
    1374             :     size_t count = 0;
    1375     9367453 :     Node* node = var->value_;
    1376     9367453 :     if (node != nullptr) {
    1377             :       auto i = variable_merges_.find(var);
    1378     7087903 :       if (i != variable_merges_.end()) {
    1379     2594425 :         i->second.push_back(node);
    1380             :         count = i->second.size();
    1381             :       } else {
    1382             :         count = 1;
    1383     8986956 :         variable_merges_[var] = std::vector<Node*>(1, node);
    1384             :       }
    1385             :     }
    1386             :     // If the following asserts, then you've jumped to a label without a bound
    1387             :     // variable along that path that expects to merge its value into a phi.
    1388             :     DCHECK(variable_phis_.find(var) == variable_phis_.end() ||
    1389             :            count == merge_count_);
    1390             :     USE(count);
    1391             : 
    1392             :     // If the label is already bound, we already know the set of variables to
    1393             :     // merge and phi nodes have already been created.
    1394     9367453 :     if (bound_) {
    1395             :       auto phi = variable_phis_.find(var);
    1396      437271 :       if (phi != variable_phis_.end()) {
    1397             :         DCHECK_NOT_NULL(phi->second);
    1398      247948 :         state_->raw_assembler_->AppendPhiInput(phi->second, node);
    1399             :       } else {
    1400             :         auto i = variable_merges_.find(var);
    1401             :         if (i != variable_merges_.end()) {
    1402             :           // If the following assert fires, then you've declared a variable that
    1403             :           // has the same bound value along all paths up until the point you
    1404             :           // bound this label, but then later merged a path with a new value for
    1405             :           // the variable after the label bind (it's not possible to add phis to
    1406             :           // the bound label after the fact, just make sure to list the variable
    1407             :           // in the label's constructor's list of merged variables).
    1408             : #if DEBUG
    1409             :           if (find_if(i->second.begin(), i->second.end(),
    1410             :                       [node](Node* e) -> bool { return node != e; }) !=
    1411             :               i->second.end()) {
    1412             :             std::stringstream str;
    1413             :             str << "Unmerged variable found when jumping to block. \n"
    1414             :                 << "#    Variable:      " << *var;
    1415             :             if (bound_) {
    1416             :               str << "\n#    Target block:  " << *label_->block();
    1417             :             }
    1418             :             str << "\n#    Current Block: ";
    1419             :             state_->PrintCurrentBlock(str);
    1420             :             FATAL(str.str().c_str());
    1421             :           }
    1422             : #endif  // DEBUG
    1423             :         }
    1424             :       }
    1425             :     }
    1426             :   }
    1427     1601175 : }
    1428             : 
    1429             : #if DEBUG
    1430             : void CodeAssemblerLabel::Bind(AssemblerDebugInfo debug_info) {
    1431             :   if (bound_) {
    1432             :     std::stringstream str;
    1433             :     str << "Cannot bind the same label twice:"
    1434             :         << "\n#    current:  " << debug_info
    1435             :         << "\n#    previous: " << *label_->block();
    1436             :     FATAL(str.str().c_str());
    1437             :   }
    1438             :   state_->raw_assembler_->Bind(label_, debug_info);
    1439             :   UpdateVariablesAfterBind();
    1440             : }
    1441             : #endif  // DEBUG
    1442             : 
    1443     1038889 : void CodeAssemblerLabel::Bind() {
    1444             :   DCHECK(!bound_);
    1445     2077778 :   state_->raw_assembler_->Bind(label_);
    1446     1038889 :   UpdateVariablesAfterBind();
    1447     1038889 : }
    1448             : 
    1449     1038889 : void CodeAssemblerLabel::UpdateVariablesAfterBind() {
    1450             :   // Make sure that all variables that have changed along any path up to this
    1451             :   // point are marked as merge variables.
    1452     9103429 :   for (auto var : state_->variables_) {
    1453             :     Node* shared_value = nullptr;
    1454             :     auto i = variable_merges_.find(var);
    1455     5986762 :     if (i != variable_merges_.end()) {
    1456    15235930 :       for (auto value : i->second) {
    1457             :         DCHECK_NOT_NULL(value);
    1458     6412850 :         if (value != shared_value) {
    1459     4772308 :           if (shared_value == nullptr) {
    1460             :             shared_value = value;
    1461             :           } else {
    1462      360768 :             variable_phis_[var] = nullptr;
    1463             :           }
    1464             :         }
    1465             :       }
    1466             :     }
    1467             :   }
    1468             : 
    1469     2393041 :   for (auto var : variable_phis_) {
    1470      315263 :     CodeAssemblerVariable::Impl* var_impl = var.first;
    1471             :     auto i = variable_merges_.find(var_impl);
    1472             : #if DEBUG
    1473             :     bool not_found = i == variable_merges_.end();
    1474             :     if (not_found || i->second.size() != merge_count_) {
    1475             :       std::stringstream str;
    1476             :       str << "A variable that has been marked as beeing merged at the label"
    1477             :           << "\n# doesn't have a bound value along all of the paths that "
    1478             :           << "\n# have been merged into the label up to this point."
    1479             :           << "\n#"
    1480             :           << "\n# This can happen in the following cases:"
    1481             :           << "\n# - By explicitly marking it so in the label constructor"
    1482             :           << "\n# - By having seen different bound values at branches"
    1483             :           << "\n#"
    1484             :           << "\n# Merge count:     expected=" << merge_count_
    1485             :           << " vs. found=" << (not_found ? 0 : i->second.size())
    1486             :           << "\n# Variable:      " << *var_impl
    1487             :           << "\n# Current Block: " << *label_->block();
    1488             :       FATAL(str.str().c_str());
    1489             :     }
    1490             : #endif  // DEBUG
    1491             :     Node* phi = state_->raw_assembler_->Phi(
    1492      630526 :         var.first->rep_, static_cast<int>(merge_count_), &(i->second[0]));
    1493      315263 :     variable_phis_[var_impl] = phi;
    1494             :   }
    1495             : 
    1496             :   // Bind all variables to a merge phi, the common value along all paths or
    1497             :   // null.
    1498     9103429 :   for (auto var : state_->variables_) {
    1499             :     auto i = variable_phis_.find(var);
    1500     5986762 :     if (i != variable_phis_.end()) {
    1501      315263 :       var->value_ = i->second;
    1502             :     } else {
    1503             :       auto j = variable_merges_.find(var);
    1504     9767776 :       if (j != variable_merges_.end() && j->second.size() == merge_count_) {
    1505     8082754 :         var->value_ = j->second.back();
    1506             :       } else {
    1507     1630122 :         var->value_ = nullptr;
    1508             :       }
    1509             :     }
    1510             :   }
    1511             : 
    1512     1038889 :   bound_ = true;
    1513     1038889 : }
    1514             : 
    1515             : }  // namespace compiler
    1516             : 
    1517           0 : Smi* CheckObjectType(Object* value, Smi* type, String* location) {
    1518             : #ifdef DEBUG
    1519             :   const char* expected;
    1520             :   switch (static_cast<ObjectType>(type->value())) {
    1521             : #define TYPE_CASE(Name)                            \
    1522             :   case ObjectType::k##Name:                        \
    1523             :     if (value->Is##Name()) return Smi::FromInt(0); \
    1524             :     expected = #Name;                              \
    1525             :     break;
    1526             : #define TYPE_STRUCT_CASE(NAME, Name, name)         \
    1527             :   case ObjectType::k##Name:                        \
    1528             :     if (value->Is##Name()) return Smi::FromInt(0); \
    1529             :     expected = #Name;                              \
    1530             :     break;
    1531             : 
    1532             :     TYPE_CASE(Object)
    1533             :     OBJECT_TYPE_LIST(TYPE_CASE)
    1534             :     HEAP_OBJECT_TYPE_LIST(TYPE_CASE)
    1535             :     STRUCT_LIST(TYPE_STRUCT_CASE)
    1536             : #undef TYPE_CASE
    1537             : #undef TYPE_STRUCT_CASE
    1538             :   }
    1539             :   std::stringstream value_description;
    1540             :   value->Print(value_description);
    1541             :   V8_Fatal(__FILE__, __LINE__,
    1542             :            "Type cast failed in %s\n"
    1543             :            "  Expected %s but found %s",
    1544             :            location->ToAsciiArray(), expected, value_description.str().c_str());
    1545             : #else
    1546           0 :   UNREACHABLE();
    1547             : #endif
    1548             : }
    1549             : 
    1550             : }  // namespace internal
    1551             : }  // namespace v8

Generated by: LCOV version 1.10