LCOV - code coverage report
Current view: top level - src/compiler - code-assembler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 606 732 82.8 %
Date: 2019-03-21 Functions: 246 294 83.7 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/code-assembler.h"
       6             : 
       7             : #include <ostream>
       8             : 
       9             : #include "src/code-factory.h"
      10             : #include "src/compiler/backend/instruction-selector.h"
      11             : #include "src/compiler/graph.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/memcopy.h"
      23             : #include "src/objects-inl.h"
      24             : #include "src/objects/smi.h"
      25             : #include "src/zone/zone.h"
      26             : 
      27             : namespace v8 {
      28             : namespace internal {
      29             : 
      30             : constexpr MachineType MachineTypeOf<Smi>::value;
      31             : constexpr MachineType MachineTypeOf<Object>::value;
      32             : 
      33             : namespace compiler {
      34             : 
      35             : static_assert(std::is_convertible<TNode<Number>, TNode<Object>>::value,
      36             :               "test subtyping");
      37             : static_assert(std::is_convertible<TNode<UnionT<Smi, HeapNumber>>,
      38             :                                   TNode<UnionT<Smi, HeapObject>>>::value,
      39             :               "test subtyping");
      40             : static_assert(
      41             :     !std::is_convertible<TNode<UnionT<Smi, HeapObject>>, TNode<Number>>::value,
      42             :     "test subtyping");
      43             : 
      44       47967 : CodeAssemblerState::CodeAssemblerState(
      45             :     Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor,
      46             :     Code::Kind kind, const char* name, PoisoningMitigationLevel poisoning_level,
      47             :     int32_t builtin_index)
      48             :     // TODO(rmcilroy): Should we use Linkage::GetBytecodeDispatchDescriptor for
      49             :     // bytecode handlers?
      50             :     : CodeAssemblerState(
      51             :           isolate, zone,
      52             :           Linkage::GetStubCallDescriptor(
      53             :               zone, descriptor, descriptor.GetStackParameterCount(),
      54             :               CallDescriptor::kNoFlags, Operator::kNoProperties),
      55       47967 :           kind, name, poisoning_level, builtin_index) {}
      56             : 
      57       19864 : CodeAssemblerState::CodeAssemblerState(Isolate* isolate, Zone* zone,
      58             :                                        int parameter_count, Code::Kind kind,
      59             :                                        const char* name,
      60             :                                        PoisoningMitigationLevel poisoning_level,
      61             :                                        int32_t builtin_index)
      62             :     : CodeAssemblerState(
      63             :           isolate, zone,
      64             :           Linkage::GetJSCallDescriptor(
      65             :               zone, false, parameter_count,
      66             :               (kind == Code::BUILTIN ? CallDescriptor::kPushArgumentCount
      67             :                                      : CallDescriptor::kNoFlags) |
      68             :                   CallDescriptor::kCanUseRoots),
      69       39728 :           kind, name, poisoning_level, builtin_index) {}
      70             : 
      71       68399 : CodeAssemblerState::CodeAssemblerState(Isolate* isolate, Zone* zone,
      72             :                                        CallDescriptor* call_descriptor,
      73             :                                        Code::Kind kind, const char* name,
      74             :                                        PoisoningMitigationLevel poisoning_level,
      75             :                                        int32_t builtin_index)
      76             :     : raw_assembler_(new RawMachineAssembler(
      77       68399 :           isolate, new (zone) Graph(zone), call_descriptor,
      78             :           MachineType::PointerRepresentation(),
      79      136798 :           InstructionSelector::SupportedMachineOperatorFlags(),
      80      205197 :           InstructionSelector::AlignmentRequirements(), poisoning_level)),
      81             :       kind_(kind),
      82             :       name_(name),
      83             :       builtin_index_(builtin_index),
      84             :       code_generated_(false),
      85      205197 :       variables_(zone) {}
      86             : 
      87             : CodeAssemblerState::~CodeAssemblerState() = default;
      88             : 
      89           0 : int CodeAssemblerState::parameter_count() const {
      90           0 :   return static_cast<int>(raw_assembler_->call_descriptor()->ParameterCount());
      91             : }
      92             : 
      93             : CodeAssembler::~CodeAssembler() = default;
      94             : 
      95             : #if DEBUG
      96             : void CodeAssemblerState::PrintCurrentBlock(std::ostream& os) {
      97             :   raw_assembler_->PrintCurrentBlock(os);
      98             : }
      99             : #endif
     100             : 
     101        3132 : bool CodeAssemblerState::InsideBlock() { return raw_assembler_->InsideBlock(); }
     102             : 
     103       63840 : void CodeAssemblerState::SetInitialDebugInformation(const char* msg,
     104             :                                                     const char* file,
     105             :                                                     int line) {
     106             : #if DEBUG
     107             :   AssemblerDebugInfo debug_info = {msg, file, line};
     108             :   raw_assembler_->SetSourcePosition(file, line);
     109             :   raw_assembler_->SetInitialDebugInformation(debug_info);
     110             : #endif  // DEBUG
     111       63840 : }
     112             : 
     113           0 : class BreakOnNodeDecorator final : public GraphDecorator {
     114             :  public:
     115           0 :   explicit BreakOnNodeDecorator(NodeId node_id) : node_id_(node_id) {}
     116             : 
     117           0 :   void Decorate(Node* node) final {
     118           0 :     if (node->id() == node_id_) {
     119           0 :       base::OS::DebugBreak();
     120             :     }
     121           0 :   }
     122             : 
     123             :  private:
     124             :   NodeId node_id_;
     125             : };
     126             : 
     127           0 : void CodeAssembler::BreakOnNode(int node_id) {
     128             :   Graph* graph = raw_assembler()->graph();
     129             :   Zone* zone = graph->zone();
     130             :   GraphDecorator* decorator =
     131           0 :       new (zone) BreakOnNodeDecorator(static_cast<NodeId>(node_id));
     132           0 :   graph->AddDecorator(decorator);
     133           0 : }
     134             : 
     135       27990 : void CodeAssembler::RegisterCallGenerationCallbacks(
     136             :     const CodeAssemblerCallback& call_prologue,
     137             :     const CodeAssemblerCallback& call_epilogue) {
     138             :   // The callback can be registered only once.
     139             :   DCHECK(!state_->call_prologue_);
     140             :   DCHECK(!state_->call_epilogue_);
     141       27990 :   state_->call_prologue_ = call_prologue;
     142       27990 :   state_->call_epilogue_ = call_epilogue;
     143       27990 : }
     144             : 
     145       27990 : void CodeAssembler::UnregisterCallGenerationCallbacks() {
     146       27990 :   state_->call_prologue_ = nullptr;
     147       27990 :   state_->call_epilogue_ = nullptr;
     148       27990 : }
     149             : 
     150      251318 : void CodeAssembler::CallPrologue() {
     151      251318 :   if (state_->call_prologue_) {
     152             :     state_->call_prologue_();
     153             :   }
     154      251318 : }
     155             : 
     156      251318 : void CodeAssembler::CallEpilogue() {
     157      251318 :   if (state_->call_epilogue_) {
     158             :     state_->call_epilogue_();
     159             :   }
     160      251318 : }
     161             : 
     162        1176 : bool CodeAssembler::Word32ShiftIsSafe() const {
     163        1176 :   return raw_assembler()->machine()->Word32ShiftIsSafe();
     164             : }
     165             : 
     166        5742 : PoisoningMitigationLevel CodeAssembler::poisoning_level() const {
     167        5742 :   return raw_assembler()->poisoning_level();
     168             : }
     169             : 
     170             : // static
     171       66916 : Handle<Code> CodeAssembler::GenerateCode(CodeAssemblerState* state,
     172             :                                          const AssemblerOptions& options) {
     173             :   DCHECK(!state->code_generated_);
     174             : 
     175             :   RawMachineAssembler* rasm = state->raw_assembler_.get();
     176             : 
     177             :   Handle<Code> code;
     178       66916 :   Graph* graph = rasm->ExportForOptimization();
     179             : 
     180      133832 :   code = Pipeline::GenerateCodeForCodeStub(
     181             :              rasm->isolate(), rasm->call_descriptor(), graph,
     182             :              rasm->source_positions(), state->kind_, state->name_,
     183       66916 :              state->builtin_index_, rasm->poisoning_level(), options)
     184             :              .ToHandleChecked();
     185             : 
     186       66916 :   state->code_generated_ = true;
     187       66916 :   return code;
     188             : }
     189             : 
     190      796288 : bool CodeAssembler::Is64() const { return raw_assembler()->machine()->Is64(); }
     191             : 
     192         118 : bool CodeAssembler::IsFloat64RoundUpSupported() const {
     193         118 :   return raw_assembler()->machine()->Float64RoundUp().IsSupported();
     194             : }
     195             : 
     196         125 : bool CodeAssembler::IsFloat64RoundDownSupported() const {
     197         125 :   return raw_assembler()->machine()->Float64RoundDown().IsSupported();
     198             : }
     199             : 
     200         392 : bool CodeAssembler::IsFloat64RoundTiesEvenSupported() const {
     201         392 :   return raw_assembler()->machine()->Float64RoundTiesEven().IsSupported();
     202             : }
     203             : 
     204         340 : bool CodeAssembler::IsFloat64RoundTruncateSupported() const {
     205         340 :   return raw_assembler()->machine()->Float64RoundTruncate().IsSupported();
     206             : }
     207             : 
     208           0 : bool CodeAssembler::IsInt32AbsWithOverflowSupported() const {
     209           0 :   return raw_assembler()->machine()->Int32AbsWithOverflow().IsSupported();
     210             : }
     211             : 
     212           0 : bool CodeAssembler::IsInt64AbsWithOverflowSupported() const {
     213          56 :   return raw_assembler()->machine()->Int64AbsWithOverflow().IsSupported();
     214             : }
     215             : 
     216          56 : bool CodeAssembler::IsIntPtrAbsWithOverflowSupported() const {
     217             :   return Is64() ? IsInt64AbsWithOverflowSupported()
     218         112 :                 : IsInt32AbsWithOverflowSupported();
     219             : }
     220             : 
     221             : #ifdef DEBUG
     222             : void CodeAssembler::GenerateCheckMaybeObjectIsObject(Node* node,
     223             :                                                      const char* location) {
     224             :   Label ok(this);
     225             :   GotoIf(WordNotEqual(WordAnd(BitcastMaybeObjectToWord(node),
     226             :                               IntPtrConstant(kHeapObjectTagMask)),
     227             :                       IntPtrConstant(kWeakHeapObjectTag)),
     228             :          &ok);
     229             :   Node* message_node = StringConstant(location);
     230             :   DebugAbort(message_node);
     231             :   Unreachable();
     232             :   Bind(&ok);
     233             : }
     234             : #endif
     235             : 
     236      625091 : TNode<Int32T> CodeAssembler::Int32Constant(int32_t value) {
     237      793299 :   return UncheckedCast<Int32T>(raw_assembler()->Int32Constant(value));
     238             : }
     239             : 
     240       11372 : TNode<Int64T> CodeAssembler::Int64Constant(int64_t value) {
     241       11372 :   return UncheckedCast<Int64T>(raw_assembler()->Int64Constant(value));
     242             : }
     243             : 
     244     3400917 : TNode<IntPtrT> CodeAssembler::IntPtrConstant(intptr_t value) {
     245     3400917 :   return UncheckedCast<IntPtrT>(raw_assembler()->IntPtrConstant(value));
     246             : }
     247             : 
     248       10644 : TNode<Number> CodeAssembler::NumberConstant(double value) {
     249             :   int smi_value;
     250       10644 :   if (DoubleToSmiInteger(value, &smi_value)) {
     251             :     return UncheckedCast<Number>(SmiConstant(smi_value));
     252             :   } else {
     253             :     // We allocate the heap number constant eagerly at this point instead of
     254             :     // deferring allocation to code generation
     255             :     // (see AllocateAndInstallRequestedHeapObjects) since that makes it easier
     256             :     // to generate constant lookups for embedded builtins.
     257             :     return UncheckedCast<Number>(HeapConstant(
     258        1740 :         isolate()->factory()->NewHeapNumber(value, AllocationType::kOld)));
     259             :   }
     260             : }
     261             : 
     262      302157 : TNode<Smi> CodeAssembler::SmiConstant(Smi value) {
     263             :   return UncheckedCast<Smi>(BitcastWordToTaggedSigned(
     264      604314 :       IntPtrConstant(static_cast<intptr_t>(value.ptr()))));
     265             : }
     266             : 
     267      280809 : TNode<Smi> CodeAssembler::SmiConstant(int value) {
     268      289713 :   return SmiConstant(Smi::FromInt(value));
     269             : }
     270             : 
     271      142406 : TNode<HeapObject> CodeAssembler::UntypedHeapConstant(
     272             :     Handle<HeapObject> object) {
     273      752898 :   return UncheckedCast<HeapObject>(raw_assembler()->HeapConstant(object));
     274             : }
     275             : 
     276       18088 : TNode<String> CodeAssembler::StringConstant(const char* str) {
     277             :   Handle<String> internalized_string =
     278       18088 :       factory()->InternalizeOneByteString(OneByteVector(str));
     279       18088 :   return UncheckedCast<String>(HeapConstant(internalized_string));
     280             : }
     281             : 
     282         316 : TNode<Oddball> CodeAssembler::BooleanConstant(bool value) {
     283         632 :   Handle<Object> object = isolate()->factory()->ToBoolean(value);
     284             :   return UncheckedCast<Oddball>(
     285         316 :       raw_assembler()->HeapConstant(Handle<HeapObject>::cast(object)));
     286             : }
     287             : 
     288       62202 : TNode<ExternalReference> CodeAssembler::ExternalConstant(
     289             :     ExternalReference address) {
     290             :   return UncheckedCast<ExternalReference>(
     291      211998 :       raw_assembler()->ExternalConstant(address));
     292             : }
     293             : 
     294       10924 : TNode<Float64T> CodeAssembler::Float64Constant(double value) {
     295       10924 :   return UncheckedCast<Float64T>(raw_assembler()->Float64Constant(value));
     296             : }
     297             : 
     298           0 : TNode<HeapNumber> CodeAssembler::NaNConstant() {
     299           0 :   return UncheckedCast<HeapNumber>(LoadRoot(RootIndex::kNanValue));
     300             : }
     301             : 
     302     2368401 : bool CodeAssembler::ToInt32Constant(Node* node, int32_t& out_value) {
     303             :   {
     304             :     Int64Matcher m(node);
     305     2554306 :     if (m.HasValue() && m.IsInRange(std::numeric_limits<int32_t>::min(),
     306             :                                     std::numeric_limits<int32_t>::max())) {
     307      185901 :       out_value = static_cast<int32_t>(m.Value());
     308             :       return true;
     309             :     }
     310             :   }
     311             : 
     312             :   {
     313             :     Int32Matcher m(node);
     314     2182500 :     if (m.HasValue()) {
     315           0 :       out_value = m.Value();
     316             :       return true;
     317             :     }
     318             :   }
     319             : 
     320     2182500 :   return false;
     321             : }
     322             : 
     323          20 : bool CodeAssembler::ToInt64Constant(Node* node, int64_t& out_value) {
     324             :   Int64Matcher m(node);
     325        5132 :   if (m.HasValue()) out_value = m.Value();
     326          20 :   return m.HasValue();
     327             : }
     328             : 
     329       33272 : bool CodeAssembler::ToSmiConstant(Node* node, Smi* out_value) {
     330       33272 :   if (node->opcode() == IrOpcode::kBitcastWordToTaggedSigned) {
     331             :     node = node->InputAt(0);
     332             :   }
     333             :   IntPtrMatcher m(node);
     334       33272 :   if (m.HasValue()) {
     335             :     intptr_t value = m.Value();
     336             :     // Make sure that the value is actually a smi
     337             :     CHECK_EQ(0, value & ((static_cast<intptr_t>(1) << kSmiShiftSize) - 1));
     338        2344 :     *out_value = Smi(static_cast<Address>(value));
     339        2344 :     return true;
     340             :   }
     341             :   return false;
     342             : }
     343             : 
     344     5158657 : bool CodeAssembler::ToIntPtrConstant(Node* node, intptr_t& out_value) {
     345     5158657 :   if (node->opcode() == IrOpcode::kBitcastWordToTaggedSigned ||
     346             :       node->opcode() == IrOpcode::kBitcastWordToTagged) {
     347             :     node = node->InputAt(0);
     348             :   }
     349             :   IntPtrMatcher m(node);
     350     5158657 :   if (m.HasValue()) out_value = m.Value();
     351     5158657 :   return m.HasValue();
     352             : }
     353             : 
     354        1848 : bool CodeAssembler::IsUndefinedConstant(TNode<Object> node) {
     355             :   compiler::HeapObjectMatcher m(node);
     356        1848 :   return m.Is(isolate()->factory()->undefined_value());
     357             : }
     358             : 
     359        1568 : bool CodeAssembler::IsNullConstant(TNode<Object> node) {
     360             :   compiler::HeapObjectMatcher m(node);
     361        1568 :   return m.Is(isolate()->factory()->null_value());
     362             : }
     363             : 
     364      261832 : Node* CodeAssembler::Parameter(int index) {
     365      262056 :   if (index == kTargetParameterIndex) return raw_assembler()->TargetParameter();
     366      523216 :   return raw_assembler()->Parameter(index);
     367             : }
     368             : 
     369           0 : bool CodeAssembler::IsJSFunctionCall() const {
     370             :   auto call_descriptor = raw_assembler()->call_descriptor();
     371           0 :   return call_descriptor->IsJSFunctionCall();
     372             : }
     373             : 
     374       19040 : TNode<Context> CodeAssembler::GetJSContextParameter() {
     375             :   auto call_descriptor = raw_assembler()->call_descriptor();
     376             :   DCHECK(call_descriptor->IsJSFunctionCall());
     377       38080 :   return CAST(Parameter(Linkage::GetJSCallContextParamIndex(
     378             :       static_cast<int>(call_descriptor->JSParameterCount()))));
     379             : }
     380             : 
     381       60636 : void CodeAssembler::Return(SloppyTNode<Object> value) {
     382       60860 :   return raw_assembler()->Return(value);
     383             : }
     384             : 
     385           0 : void CodeAssembler::Return(SloppyTNode<Object> value1,
     386             :                            SloppyTNode<Object> value2) {
     387           0 :   return raw_assembler()->Return(value1, value2);
     388             : }
     389             : 
     390           0 : void CodeAssembler::Return(SloppyTNode<Object> value1,
     391             :                            SloppyTNode<Object> value2,
     392             :                            SloppyTNode<Object> value3) {
     393           0 :   return raw_assembler()->Return(value1, value2, value3);
     394             : }
     395             : 
     396       13352 : void CodeAssembler::PopAndReturn(Node* pop, Node* value) {
     397       13352 :   return raw_assembler()->PopAndReturn(pop, value);
     398             : }
     399             : 
     400         224 : void CodeAssembler::ReturnIf(Node* condition, Node* value) {
     401         224 :   Label if_return(this), if_continue(this);
     402         224 :   Branch(condition, &if_return, &if_continue);
     403             :   Bind(&if_return);
     404             :   Return(value);
     405             :   Bind(&if_continue);
     406         224 : }
     407             : 
     408         336 : void CodeAssembler::ReturnRaw(Node* value) {
     409         336 :   return raw_assembler()->Return(value);
     410             : }
     411             : 
     412           0 : void CodeAssembler::DebugAbort(Node* message) {
     413           0 :   raw_assembler()->DebugAbort(message);
     414           0 : }
     415             : 
     416      217464 : void CodeAssembler::DebugBreak() { raw_assembler()->DebugBreak(); }
     417             : 
     418       65512 : void CodeAssembler::Unreachable() {
     419             :   DebugBreak();
     420       65512 :   raw_assembler()->Unreachable();
     421       65512 : }
     422             : 
     423           4 : void CodeAssembler::Comment(std::string str) {
     424           4 :   if (!FLAG_code_comments) return;
     425           4 :   raw_assembler()->Comment(str);
     426             : }
     427             : 
     428      863532 : void CodeAssembler::SetSourcePosition(const char* file, int line) {
     429      863532 :   raw_assembler()->SetSourcePosition(file, line);
     430      863532 : }
     431             : 
     432     3631636 : void CodeAssembler::Bind(Label* label) { return label->Bind(); }
     433             : 
     434             : #if DEBUG
     435             : void CodeAssembler::Bind(Label* label, AssemblerDebugInfo debug_info) {
     436             :   return label->Bind(debug_info);
     437             : }
     438             : #endif  // DEBUG
     439             : 
     440        8004 : Node* CodeAssembler::LoadFramePointer() {
     441        8004 :   return raw_assembler()->LoadFramePointer();
     442             : }
     443             : 
     444       28664 : Node* CodeAssembler::LoadParentFramePointer() {
     445       28664 :   return raw_assembler()->LoadParentFramePointer();
     446             : }
     447             : 
     448       19264 : Node* CodeAssembler::LoadStackPointer() {
     449       19264 :   return raw_assembler()->LoadStackPointer();
     450             : }
     451             : 
     452       19056 : TNode<Object> CodeAssembler::TaggedPoisonOnSpeculation(
     453             :     SloppyTNode<Object> value) {
     454             :   return UncheckedCast<Object>(
     455       19056 :       raw_assembler()->TaggedPoisonOnSpeculation(value));
     456             : }
     457             : 
     458       45864 : TNode<WordT> CodeAssembler::WordPoisonOnSpeculation(SloppyTNode<WordT> value) {
     459       45864 :   return UncheckedCast<WordT>(raw_assembler()->WordPoisonOnSpeculation(value));
     460             : }
     461             : 
     462             : #define DEFINE_CODE_ASSEMBLER_BINARY_OP(name, ResType, Arg1Type, Arg2Type) \
     463             :   TNode<ResType> CodeAssembler::name(SloppyTNode<Arg1Type> a,              \
     464             :                                      SloppyTNode<Arg2Type> b) {            \
     465             :     return UncheckedCast<ResType>(raw_assembler()->name(a, b));            \
     466             :   }
     467      870720 : CODE_ASSEMBLER_BINARY_OP_LIST(DEFINE_CODE_ASSEMBLER_BINARY_OP)
     468             : #undef DEFINE_CODE_ASSEMBLER_BINARY_OP
     469             : 
     470      707023 : TNode<WordT> CodeAssembler::IntPtrAdd(SloppyTNode<WordT> left,
     471             :                                       SloppyTNode<WordT> right) {
     472             :   intptr_t left_constant;
     473      707023 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     474             :   intptr_t right_constant;
     475      707023 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     476      707023 :   if (is_left_constant) {
     477      313610 :     if (is_right_constant) {
     478      101266 :       return IntPtrConstant(left_constant + right_constant);
     479             :     }
     480      262977 :     if (left_constant == 0) {
     481       38301 :       return right;
     482             :     }
     483      393413 :   } else if (is_right_constant) {
     484      304259 :     if (right_constant == 0) {
     485       25621 :       return left;
     486             :     }
     487             :   }
     488             :   return UncheckedCast<WordT>(raw_assembler()->IntPtrAdd(left, right));
     489             : }
     490             : 
     491         509 : TNode<IntPtrT> CodeAssembler::IntPtrDiv(TNode<IntPtrT> left,
     492             :                                         TNode<IntPtrT> right) {
     493             :   intptr_t left_constant;
     494         509 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     495             :   intptr_t right_constant;
     496         509 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     497         509 :   if (is_right_constant) {
     498          61 :     if (is_left_constant) {
     499           2 :       return IntPtrConstant(left_constant / right_constant);
     500             :     }
     501         118 :     if (base::bits::IsPowerOfTwo(right_constant)) {
     502          58 :       return WordSar(left, WhichPowerOf2(right_constant));
     503             :     }
     504             :   }
     505             :   return UncheckedCast<IntPtrT>(raw_assembler()->IntPtrDiv(left, right));
     506             : }
     507             : 
     508      108325 : TNode<WordT> CodeAssembler::IntPtrSub(SloppyTNode<WordT> left,
     509             :                                       SloppyTNode<WordT> right) {
     510             :   intptr_t left_constant;
     511      108325 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     512             :   intptr_t right_constant;
     513      108325 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     514      108325 :   if (is_left_constant) {
     515       19561 :     if (is_right_constant) {
     516       13682 :       return IntPtrConstant(left_constant - right_constant);
     517             :     }
     518       88764 :   } else if (is_right_constant) {
     519       82600 :     if (right_constant == 0) {
     520        8601 :       return left;
     521             :     }
     522             :   }
     523       92883 :   return UncheckedCast<IntPtrT>(raw_assembler()->IntPtrSub(left, right));
     524             : }
     525             : 
     526       54774 : TNode<WordT> CodeAssembler::IntPtrMul(SloppyTNode<WordT> left,
     527             :                                       SloppyTNode<WordT> right) {
     528             :   intptr_t left_constant;
     529       54774 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     530             :   intptr_t right_constant;
     531       54774 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     532       54774 :   if (is_left_constant) {
     533        2011 :     if (is_right_constant) {
     534        4018 :       return IntPtrConstant(left_constant * right_constant);
     535             :     }
     536           4 :     if (base::bits::IsPowerOfTwo(left_constant)) {
     537           2 :       return WordShl(right, WhichPowerOf2(left_constant));
     538             :     }
     539       52763 :   } else if (is_right_constant) {
     540      104406 :     if (base::bits::IsPowerOfTwo(right_constant)) {
     541       17926 :       return WordShl(left, WhichPowerOf2(right_constant));
     542             :     }
     543             :   }
     544       34837 :   return UncheckedCast<IntPtrT>(raw_assembler()->IntPtrMul(left, right));
     545             : }
     546             : 
     547      112851 : TNode<WordT> CodeAssembler::WordShl(SloppyTNode<WordT> value, int shift) {
     548      217343 :   return (shift != 0) ? WordShl(value, IntPtrConstant(shift)) : value;
     549             : }
     550             : 
     551       28808 : TNode<WordT> CodeAssembler::WordShr(SloppyTNode<WordT> value, int shift) {
     552       51399 :   return (shift != 0) ? WordShr(value, IntPtrConstant(shift)) : value;
     553             : }
     554             : 
     555         562 : TNode<WordT> CodeAssembler::WordSar(SloppyTNode<WordT> value, int shift) {
     556        1123 :   return (shift != 0) ? WordSar(value, IntPtrConstant(shift)) : value;
     557             : }
     558             : 
     559       37632 : TNode<Word32T> CodeAssembler::Word32Shr(SloppyTNode<Word32T> value, int shift) {
     560       63832 :   return (shift != 0) ? Word32Shr(value, Int32Constant(shift)) : value;
     561             : }
     562             : 
     563        7752 : TNode<WordT> CodeAssembler::WordOr(SloppyTNode<WordT> left,
     564             :                                    SloppyTNode<WordT> right) {
     565             :   intptr_t left_constant;
     566        7752 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     567             :   intptr_t right_constant;
     568        7752 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     569        7752 :   if (is_left_constant) {
     570        3530 :     if (is_right_constant) {
     571        7058 :       return IntPtrConstant(left_constant | right_constant);
     572             :     }
     573           1 :     if (left_constant == 0) {
     574           1 :       return right;
     575             :     }
     576        4222 :   } else if (is_right_constant) {
     577        2522 :     if (right_constant == 0) {
     578           1 :       return left;
     579             :     }
     580             :   }
     581        4221 :   return UncheckedCast<WordT>(raw_assembler()->WordOr(left, right));
     582             : }
     583             : 
     584      307482 : TNode<WordT> CodeAssembler::WordAnd(SloppyTNode<WordT> left,
     585             :                                     SloppyTNode<WordT> right) {
     586             :   intptr_t left_constant;
     587      307482 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     588             :   intptr_t right_constant;
     589      307482 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     590      307482 :   if (is_left_constant) {
     591         393 :     if (is_right_constant) {
     592         786 :       return IntPtrConstant(left_constant & right_constant);
     593             :     }
     594             :   }
     595      307089 :   return UncheckedCast<WordT>(raw_assembler()->WordAnd(left, right));
     596             : }
     597             : 
     598         294 : TNode<WordT> CodeAssembler::WordXor(SloppyTNode<WordT> left,
     599             :                                     SloppyTNode<WordT> right) {
     600             :   intptr_t left_constant;
     601         294 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     602             :   intptr_t right_constant;
     603         294 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     604         294 :   if (is_left_constant) {
     605           1 :     if (is_right_constant) {
     606           2 :       return IntPtrConstant(left_constant ^ right_constant);
     607             :     }
     608             :   }
     609         293 :   return UncheckedCast<WordT>(raw_assembler()->WordXor(left, right));
     610             : }
     611             : 
     612      470037 : TNode<WordT> CodeAssembler::WordShl(SloppyTNode<WordT> left,
     613             :                                     SloppyTNode<IntegralT> right) {
     614             :   intptr_t left_constant;
     615      470037 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     616             :   intptr_t right_constant;
     617      470037 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     618      470037 :   if (is_left_constant) {
     619       11433 :     if (is_right_constant) {
     620       22754 :       return IntPtrConstant(left_constant << right_constant);
     621             :     }
     622      458604 :   } else if (is_right_constant) {
     623      458044 :     if (right_constant == 0) {
     624           0 :       return left;
     625             :     }
     626             :   }
     627      458660 :   return UncheckedCast<WordT>(raw_assembler()->WordShl(left, right));
     628             : }
     629             : 
     630       28043 : TNode<WordT> CodeAssembler::WordShr(SloppyTNode<WordT> left,
     631             :                                     SloppyTNode<IntegralT> right) {
     632             :   intptr_t left_constant;
     633       28043 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     634             :   intptr_t right_constant;
     635       28043 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     636       28043 :   if (is_left_constant) {
     637        3698 :     if (is_right_constant) {
     638        3698 :       return IntPtrConstant(static_cast<uintptr_t>(left_constant) >>
     639        7396 :                             right_constant);
     640             :     }
     641       24345 :   } else if (is_right_constant) {
     642       23841 :     if (right_constant == 0) {
     643           0 :       return left;
     644             :     }
     645             :   }
     646       24345 :   return UncheckedCast<WordT>(raw_assembler()->WordShr(left, right));
     647             : }
     648             : 
     649      230893 : TNode<WordT> CodeAssembler::WordSar(SloppyTNode<WordT> left,
     650             :                                     SloppyTNode<IntegralT> right) {
     651             :   intptr_t left_constant;
     652      230893 :   bool is_left_constant = ToIntPtrConstant(left, left_constant);
     653             :   intptr_t right_constant;
     654      230893 :   bool is_right_constant = ToIntPtrConstant(right, right_constant);
     655      230893 :   if (is_left_constant) {
     656           2 :     if (is_right_constant) {
     657           4 :       return IntPtrConstant(left_constant >> right_constant);
     658             :     }
     659      230891 :   } else if (is_right_constant) {
     660      230779 :     if (right_constant == 0) {
     661           1 :       return left;
     662             :     }
     663             :   }
     664      230890 :   return UncheckedCast<WordT>(raw_assembler()->WordSar(left, right));
     665             : }
     666             : 
     667       62568 : TNode<Word32T> CodeAssembler::Word32Or(SloppyTNode<Word32T> left,
     668             :                                        SloppyTNode<Word32T> right) {
     669             :   int32_t left_constant;
     670       62568 :   bool is_left_constant = ToInt32Constant(left, left_constant);
     671             :   int32_t right_constant;
     672       62568 :   bool is_right_constant = ToInt32Constant(right, right_constant);
     673       62568 :   if (is_left_constant) {
     674           0 :     if (is_right_constant) {
     675           0 :       return Int32Constant(left_constant | right_constant);
     676             :     }
     677           0 :     if (left_constant == 0) {
     678           0 :       return right;
     679             :     }
     680       62568 :   } else if (is_right_constant) {
     681          56 :     if (right_constant == 0) {
     682           0 :       return left;
     683             :     }
     684             :   }
     685       62568 :   return UncheckedCast<Word32T>(raw_assembler()->Word32Or(left, right));
     686             : }
     687             : 
     688      133008 : TNode<Word32T> CodeAssembler::Word32And(SloppyTNode<Word32T> left,
     689             :                                         SloppyTNode<Word32T> right) {
     690             :   int32_t left_constant;
     691      133008 :   bool is_left_constant = ToInt32Constant(left, left_constant);
     692             :   int32_t right_constant;
     693      133008 :   bool is_right_constant = ToInt32Constant(right, right_constant);
     694      133008 :   if (is_left_constant) {
     695          12 :     if (is_right_constant) {
     696           8 :       return Int32Constant(left_constant & right_constant);
     697             :     }
     698             :   }
     699      133004 :   return UncheckedCast<Word32T>(raw_assembler()->Word32And(left, right));
     700             : }
     701             : 
     702        2472 : TNode<Word32T> CodeAssembler::Word32Xor(SloppyTNode<Word32T> left,
     703             :                                         SloppyTNode<Word32T> right) {
     704             :   int32_t left_constant;
     705        2472 :   bool is_left_constant = ToInt32Constant(left, left_constant);
     706             :   int32_t right_constant;
     707        2472 :   bool is_right_constant = ToInt32Constant(right, right_constant);
     708        2472 :   if (is_left_constant) {
     709           4 :     if (is_right_constant) {
     710           8 :       return Int32Constant(left_constant ^ right_constant);
     711             :     }
     712             :   }
     713        2468 :   return UncheckedCast<Word32T>(raw_assembler()->Word32Xor(left, right));
     714             : }
     715             : 
     716        8512 : TNode<Word32T> CodeAssembler::Word32Shl(SloppyTNode<Word32T> left,
     717             :                                         SloppyTNode<Word32T> right) {
     718             :   int32_t left_constant;
     719        8512 :   bool is_left_constant = ToInt32Constant(left, left_constant);
     720             :   int32_t right_constant;
     721        8512 :   bool is_right_constant = ToInt32Constant(right, right_constant);
     722        8512 :   if (is_left_constant) {
     723           0 :     if (is_right_constant) {
     724           0 :       return Int32Constant(left_constant << right_constant);
     725             :     }
     726        8512 :   } else if (is_right_constant) {
     727        4872 :     if (right_constant == 0) {
     728           0 :       return left;
     729             :     }
     730             :   }
     731        8512 :   return UncheckedCast<Word32T>(raw_assembler()->Word32Shl(left, right));
     732             : }
     733             : 
     734       36588 : TNode<Word32T> CodeAssembler::Word32Shr(SloppyTNode<Word32T> left,
     735             :                                         SloppyTNode<Word32T> right) {
     736             :   int32_t left_constant;
     737       36588 :   bool is_left_constant = ToInt32Constant(left, left_constant);
     738             :   int32_t right_constant;
     739       36588 :   bool is_right_constant = ToInt32Constant(right, right_constant);
     740       36588 :   if (is_left_constant) {
     741           0 :     if (is_right_constant) {
     742           0 :       return Int32Constant(static_cast<uint32_t>(left_constant) >>
     743           0 :                            right_constant);
     744             :     }
     745       36588 :   } else if (is_right_constant) {
     746       34572 :     if (right_constant == 0) {
     747           0 :       return left;
     748             :     }
     749             :   }
     750       36588 :   return UncheckedCast<Word32T>(raw_assembler()->Word32Shr(left, right));
     751             : }
     752             : 
     753         392 : TNode<Word32T> CodeAssembler::Word32Sar(SloppyTNode<Word32T> left,
     754             :                                         SloppyTNode<Word32T> right) {
     755             :   int32_t left_constant;
     756         392 :   bool is_left_constant = ToInt32Constant(left, left_constant);
     757             :   int32_t right_constant;
     758         392 :   bool is_right_constant = ToInt32Constant(right, right_constant);
     759         392 :   if (is_left_constant) {
     760           0 :     if (is_right_constant) {
     761           0 :       return Int32Constant(left_constant >> right_constant);
     762             :     }
     763         392 :   } else if (is_right_constant) {
     764           0 :     if (right_constant == 0) {
     765           0 :       return left;
     766             :     }
     767             :   }
     768         392 :   return UncheckedCast<Word32T>(raw_assembler()->Word32Sar(left, right));
     769             : }
     770             : 
     771           0 : TNode<Word64T> CodeAssembler::Word64Or(SloppyTNode<Word64T> left,
     772             :                                        SloppyTNode<Word64T> right) {
     773             :   int64_t left_constant;
     774             :   bool is_left_constant = ToInt64Constant(left, left_constant);
     775             :   int64_t right_constant;
     776             :   bool is_right_constant = ToInt64Constant(right, right_constant);
     777           0 :   if (is_left_constant) {
     778           0 :     if (is_right_constant) {
     779           0 :       return Int64Constant(left_constant | right_constant);
     780             :     }
     781           0 :     if (left_constant == 0) {
     782           0 :       return right;
     783             :     }
     784           0 :   } else if (is_right_constant) {
     785           0 :     if (right_constant == 0) {
     786           0 :       return left;
     787             :     }
     788             :   }
     789           0 :   return UncheckedCast<Word64T>(raw_assembler()->Word64Or(left, right));
     790             : }
     791             : 
     792           0 : TNode<Word64T> CodeAssembler::Word64And(SloppyTNode<Word64T> left,
     793             :                                         SloppyTNode<Word64T> right) {
     794             :   int64_t left_constant;
     795             :   bool is_left_constant = ToInt64Constant(left, left_constant);
     796             :   int64_t right_constant;
     797             :   bool is_right_constant = ToInt64Constant(right, right_constant);
     798           0 :   if (is_left_constant) {
     799           0 :     if (is_right_constant) {
     800           0 :       return Int64Constant(left_constant & right_constant);
     801             :     }
     802             :   }
     803           0 :   return UncheckedCast<Word64T>(raw_assembler()->Word64And(left, right));
     804             : }
     805             : 
     806           0 : TNode<Word64T> CodeAssembler::Word64Xor(SloppyTNode<Word64T> left,
     807             :                                         SloppyTNode<Word64T> right) {
     808             :   int64_t left_constant;
     809             :   bool is_left_constant = ToInt64Constant(left, left_constant);
     810             :   int64_t right_constant;
     811             :   bool is_right_constant = ToInt64Constant(right, right_constant);
     812           0 :   if (is_left_constant) {
     813           0 :     if (is_right_constant) {
     814           0 :       return Int64Constant(left_constant ^ right_constant);
     815             :     }
     816             :   }
     817           0 :   return UncheckedCast<Word64T>(raw_assembler()->Word64Xor(left, right));
     818             : }
     819             : 
     820           0 : TNode<Word64T> CodeAssembler::Word64Shl(SloppyTNode<Word64T> left,
     821             :                                         SloppyTNode<Word64T> right) {
     822             :   int64_t left_constant;
     823             :   bool is_left_constant = ToInt64Constant(left, left_constant);
     824             :   int64_t right_constant;
     825             :   bool is_right_constant = ToInt64Constant(right, right_constant);
     826           0 :   if (is_left_constant) {
     827           0 :     if (is_right_constant) {
     828           0 :       return Int64Constant(left_constant << right_constant);
     829             :     }
     830           0 :   } else if (is_right_constant) {
     831           0 :     if (right_constant == 0) {
     832           0 :       return left;
     833             :     }
     834             :   }
     835           0 :   return UncheckedCast<Word64T>(raw_assembler()->Word64Shl(left, right));
     836             : }
     837             : 
     838           0 : TNode<Word64T> CodeAssembler::Word64Shr(SloppyTNode<Word64T> left,
     839             :                                         SloppyTNode<Word64T> right) {
     840             :   int64_t left_constant;
     841             :   bool is_left_constant = ToInt64Constant(left, left_constant);
     842             :   int64_t right_constant;
     843             :   bool is_right_constant = ToInt64Constant(right, right_constant);
     844           0 :   if (is_left_constant) {
     845           0 :     if (is_right_constant) {
     846           0 :       return Int64Constant(static_cast<uint64_t>(left_constant) >>
     847           0 :                            right_constant);
     848             :     }
     849           0 :   } else if (is_right_constant) {
     850           0 :     if (right_constant == 0) {
     851           0 :       return left;
     852             :     }
     853             :   }
     854           0 :   return UncheckedCast<Word64T>(raw_assembler()->Word64Shr(left, right));
     855             : }
     856             : 
     857           0 : TNode<Word64T> CodeAssembler::Word64Sar(SloppyTNode<Word64T> left,
     858             :                                         SloppyTNode<Word64T> right) {
     859             :   int64_t left_constant;
     860             :   bool is_left_constant = ToInt64Constant(left, left_constant);
     861             :   int64_t right_constant;
     862             :   bool is_right_constant = ToInt64Constant(right, right_constant);
     863           0 :   if (is_left_constant) {
     864           0 :     if (is_right_constant) {
     865           0 :       return Int64Constant(left_constant >> right_constant);
     866             :     }
     867           0 :   } else if (is_right_constant) {
     868           0 :     if (right_constant == 0) {
     869           0 :       return left;
     870             :     }
     871             :   }
     872           0 :   return UncheckedCast<Word64T>(raw_assembler()->Word64Sar(left, right));
     873             : }
     874             : 
     875             : #define CODE_ASSEMBLER_COMPARE(Name, ArgT, VarT, ToConstant, op)     \
     876             :   TNode<BoolT> CodeAssembler::Name(SloppyTNode<ArgT> left,           \
     877             :                                    SloppyTNode<ArgT> right) {        \
     878             :     VarT lhs, rhs;                                                   \
     879             :     if (ToConstant(left, lhs) && ToConstant(right, rhs)) {           \
     880             :       return BoolConstant(lhs op rhs);                               \
     881             :     }                                                                \
     882             :     return UncheckedCast<BoolT>(raw_assembler()->Name(left, right)); \
     883             :   }
     884             : 
     885        7224 : CODE_ASSEMBLER_COMPARE(IntPtrEqual, WordT, intptr_t, ToIntPtrConstant, ==)
     886     1145956 : CODE_ASSEMBLER_COMPARE(WordEqual, WordT, intptr_t, ToIntPtrConstant, ==)
     887       96440 : CODE_ASSEMBLER_COMPARE(WordNotEqual, WordT, intptr_t, ToIntPtrConstant, !=)
     888      476272 : CODE_ASSEMBLER_COMPARE(Word32Equal, Word32T, int32_t, ToInt32Constant, ==)
     889       77272 : CODE_ASSEMBLER_COMPARE(Word32NotEqual, Word32T, int32_t, ToInt32Constant, !=)
     890       15336 : CODE_ASSEMBLER_COMPARE(Word64Equal, Word64T, int64_t, ToInt64Constant, ==)
     891           0 : CODE_ASSEMBLER_COMPARE(Word64NotEqual, Word64T, int64_t, ToInt64Constant, !=)
     892             : #undef CODE_ASSEMBLER_COMPARE
     893             : 
     894      115249 : TNode<UintPtrT> CodeAssembler::ChangeUint32ToWord(SloppyTNode<Word32T> value) {
     895      115249 :   if (raw_assembler()->machine()->Is64()) {
     896             :     return UncheckedCast<UintPtrT>(
     897      115249 :         raw_assembler()->ChangeUint32ToUint64(value));
     898             :   }
     899             :   return ReinterpretCast<UintPtrT>(value);
     900             : }
     901             : 
     902      151756 : TNode<IntPtrT> CodeAssembler::ChangeInt32ToIntPtr(SloppyTNode<Word32T> value) {
     903      151756 :   if (raw_assembler()->machine()->Is64()) {
     904      151756 :     return ReinterpretCast<IntPtrT>(raw_assembler()->ChangeInt32ToInt64(value));
     905             :   }
     906             :   return ReinterpretCast<IntPtrT>(value);
     907             : }
     908             : 
     909        1456 : TNode<UintPtrT> CodeAssembler::ChangeFloat64ToUintPtr(
     910             :     SloppyTNode<Float64T> value) {
     911        1456 :   if (raw_assembler()->machine()->Is64()) {
     912             :     return ReinterpretCast<UintPtrT>(
     913        1456 :         raw_assembler()->ChangeFloat64ToUint64(value));
     914             :   }
     915             :   return ReinterpretCast<UintPtrT>(
     916           0 :       raw_assembler()->ChangeFloat64ToUint32(value));
     917             : }
     918             : 
     919        1736 : TNode<Float64T> CodeAssembler::ChangeUintPtrToFloat64(TNode<UintPtrT> value) {
     920        1736 :   if (raw_assembler()->machine()->Is64()) {
     921             :     // TODO(turbofan): Maybe we should introduce a ChangeUint64ToFloat64
     922             :     // machine operator to TurboFan here?
     923             :     return ReinterpretCast<Float64T>(
     924        1736 :         raw_assembler()->RoundUint64ToFloat64(value));
     925             :   }
     926             :   return ReinterpretCast<Float64T>(
     927           0 :       raw_assembler()->ChangeUint32ToFloat64(value));
     928             : }
     929             : 
     930        1128 : Node* CodeAssembler::RoundIntPtrToFloat64(Node* value) {
     931        1128 :   if (raw_assembler()->machine()->Is64()) {
     932        1128 :     return raw_assembler()->RoundInt64ToFloat64(value);
     933             :   }
     934           0 :   return raw_assembler()->ChangeInt32ToFloat64(value);
     935             : }
     936             : 
     937             : #define DEFINE_CODE_ASSEMBLER_UNARY_OP(name, ResType, ArgType) \
     938             :   TNode<ResType> CodeAssembler::name(SloppyTNode<ArgType> a) { \
     939             :     return UncheckedCast<ResType>(raw_assembler()->name(a));   \
     940             :   }
     941     3474521 : CODE_ASSEMBLER_UNARY_OP_LIST(DEFINE_CODE_ASSEMBLER_UNARY_OP)
     942             : #undef DEFINE_CODE_ASSEMBLER_UNARY_OP
     943             : 
     944       48188 : Node* CodeAssembler::Load(MachineType rep, Node* base,
     945             :                           LoadSensitivity needs_poisoning) {
     946       67508 :   return raw_assembler()->Load(rep, base, needs_poisoning);
     947             : }
     948             : 
     949     1401383 : Node* CodeAssembler::Load(MachineType rep, Node* base, Node* offset,
     950             :                           LoadSensitivity needs_poisoning) {
     951     1485759 :   return raw_assembler()->Load(rep, base, offset, needs_poisoning);
     952             : }
     953             : 
     954       19320 : Node* CodeAssembler::LoadFullTagged(Node* base,
     955             :                                     LoadSensitivity needs_poisoning) {
     956             :   return BitcastWordToTagged(
     957       19320 :       Load(MachineType::Pointer(), base, needs_poisoning));
     958             : }
     959             : 
     960       84376 : Node* CodeAssembler::LoadFullTagged(Node* base, Node* offset,
     961             :                                     LoadSensitivity needs_poisoning) {
     962             :   return BitcastWordToTagged(
     963       84376 :       Load(MachineType::Pointer(), base, offset, needs_poisoning));
     964             : }
     965             : 
     966         448 : Node* CodeAssembler::AtomicLoad(MachineType rep, Node* base, Node* offset) {
     967         448 :   return raw_assembler()->AtomicLoad(rep, base, offset);
     968             : }
     969             : 
     970      442948 : TNode<Object> CodeAssembler::LoadRoot(RootIndex root_index) {
     971      442948 :   if (RootsTable::IsImmortalImmovable(root_index)) {
     972             :     Handle<Object> root = isolate()->root_handle(root_index);
     973      442608 :     if (root->IsSmi()) {
     974           0 :       return SmiConstant(Smi::cast(*root));
     975             :     } else {
     976      442608 :       return HeapConstant(Handle<HeapObject>::cast(root));
     977             :     }
     978             :   }
     979             : 
     980             :   // TODO(jgruber): In theory we could generate better code for this by
     981             :   // letting the macro assembler decide how to load from the roots list. In most
     982             :   // cases, it would boil down to loading from a fixed kRootRegister offset.
     983             :   Node* isolate_root =
     984         340 :       ExternalConstant(ExternalReference::isolate_root(isolate()));
     985             :   int offset = IsolateData::root_slot_offset(root_index);
     986             :   return UncheckedCast<Object>(
     987         680 :       LoadFullTagged(isolate_root, IntPtrConstant(offset)));
     988             : }
     989             : 
     990           0 : Node* CodeAssembler::Store(Node* base, Node* value) {
     991             :   return raw_assembler()->Store(MachineRepresentation::kTagged, base, value,
     992           0 :                                 kFullWriteBarrier);
     993             : }
     994             : 
     995      249356 : void CodeAssembler::OptimizedStoreField(MachineRepresentation rep,
     996             :                                         TNode<HeapObject> object, int offset,
     997             :                                         Node* value,
     998             :                                         WriteBarrierKind write_barrier) {
     999      249356 :   raw_assembler()->OptimizedStoreField(rep, object, offset, value,
    1000      249356 :                                        write_barrier);
    1001      249356 : }
    1002       10764 : void CodeAssembler::OptimizedStoreMap(TNode<HeapObject> object,
    1003             :                                       TNode<Map> map) {
    1004       10764 :   raw_assembler()->OptimizedStoreMap(object, map);
    1005       10764 : }
    1006             : 
    1007       27920 : Node* CodeAssembler::Store(Node* base, Node* offset, Node* value) {
    1008             :   return raw_assembler()->Store(MachineRepresentation::kTagged, base, offset,
    1009       27920 :                                 value, kFullWriteBarrier);
    1010             : }
    1011             : 
    1012        8844 : Node* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base,
    1013             :                                          Node* value) {
    1014        9908 :   return raw_assembler()->Store(rep, base, value, kNoWriteBarrier);
    1015             : }
    1016             : 
    1017      153989 : Node* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base,
    1018             :                                          Node* offset, Node* value) {
    1019      159869 :   return raw_assembler()->Store(rep, base, offset, value, kNoWriteBarrier);
    1020             : }
    1021             : 
    1022        1064 : Node* CodeAssembler::StoreFullTaggedNoWriteBarrier(Node* base,
    1023             :                                                    Node* tagged_value) {
    1024             :   return StoreNoWriteBarrier(MachineType::PointerRepresentation(), base,
    1025        1064 :                              BitcastTaggedToWord(tagged_value));
    1026             : }
    1027             : 
    1028        5880 : Node* CodeAssembler::StoreFullTaggedNoWriteBarrier(Node* base, Node* offset,
    1029             :                                                    Node* tagged_value) {
    1030             :   return StoreNoWriteBarrier(MachineType::PointerRepresentation(), base, offset,
    1031        5880 :                              BitcastTaggedToWord(tagged_value));
    1032             : }
    1033             : 
    1034         224 : Node* CodeAssembler::AtomicStore(MachineRepresentation rep, Node* base,
    1035             :                                  Node* offset, Node* value, Node* value_high) {
    1036         224 :   return raw_assembler()->AtomicStore(rep, base, offset, value, value_high);
    1037             : }
    1038             : 
    1039             : #define ATOMIC_FUNCTION(name)                                       \
    1040             :   Node* CodeAssembler::Atomic##name(MachineType type, Node* base,   \
    1041             :                                     Node* offset, Node* value,      \
    1042             :                                     Node* value_high) {             \
    1043             :     return raw_assembler()->Atomic##name(type, base, offset, value, \
    1044             :                                          value_high);               \
    1045             :   }
    1046         896 : ATOMIC_FUNCTION(Exchange)
    1047         896 : ATOMIC_FUNCTION(Add)
    1048         896 : ATOMIC_FUNCTION(Sub)
    1049         896 : ATOMIC_FUNCTION(And)
    1050         896 : ATOMIC_FUNCTION(Or)
    1051         896 : ATOMIC_FUNCTION(Xor)
    1052             : #undef ATOMIC_FUNCTION
    1053             : 
    1054         448 : Node* CodeAssembler::AtomicCompareExchange(MachineType type, Node* base,
    1055             :                                            Node* offset, Node* old_value,
    1056             :                                            Node* new_value,
    1057             :                                            Node* old_value_high,
    1058             :                                            Node* new_value_high) {
    1059             :   return raw_assembler()->AtomicCompareExchange(
    1060         448 :       type, base, offset, old_value, old_value_high, new_value, new_value_high);
    1061             : }
    1062             : 
    1063         112 : Node* CodeAssembler::StoreRoot(RootIndex root_index, Node* value) {
    1064             :   DCHECK(!RootsTable::IsImmortalImmovable(root_index));
    1065             :   Node* isolate_root =
    1066         112 :       ExternalConstant(ExternalReference::isolate_root(isolate()));
    1067             :   int offset = IsolateData::root_slot_offset(root_index);
    1068         112 :   return StoreFullTaggedNoWriteBarrier(isolate_root, IntPtrConstant(offset),
    1069         112 :                                        value);
    1070             : }
    1071             : 
    1072           0 : Node* CodeAssembler::Retain(Node* value) {
    1073           0 :   return raw_assembler()->Retain(value);
    1074             : }
    1075             : 
    1076       40368 : Node* CodeAssembler::Projection(int index, Node* value) {
    1077             :   DCHECK_LT(index, value->op()->ValueOutputCount());
    1078       40368 :   return raw_assembler()->Projection(index, value);
    1079             : }
    1080             : 
    1081        7856 : void CodeAssembler::GotoIfException(Node* node, Label* if_exception,
    1082             :                                     Variable* exception_var) {
    1083        7856 :   if (if_exception == nullptr) {
    1084             :     // If no handler is supplied, don't add continuations
    1085        3528 :     return;
    1086             :   }
    1087             : 
    1088             :   // No catch handlers should be active if we're using catch labels
    1089             :   DCHECK_EQ(state()->exception_handler_labels_.size(), 0);
    1090             :   DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
    1091             : 
    1092        4328 :   Label success(this), exception(this, Label::kDeferred);
    1093        4328 :   success.MergeVariables();
    1094        4328 :   exception.MergeVariables();
    1095             : 
    1096        8656 :   raw_assembler()->Continuations(node, success.label_, exception.label_);
    1097             : 
    1098             :   Bind(&exception);
    1099        4328 :   const Operator* op = raw_assembler()->common()->IfException();
    1100             :   Node* exception_value = raw_assembler()->AddNode(op, node, node);
    1101        4328 :   if (exception_var != nullptr) {
    1102             :     exception_var->Bind(exception_value);
    1103             :   }
    1104             :   Goto(if_exception);
    1105             : 
    1106             :   Bind(&success);
    1107        4328 :   raw_assembler()->AddNode(raw_assembler()->common()->IfSuccess(), node);
    1108             : }
    1109             : 
    1110       64444 : TNode<HeapObject> CodeAssembler::OptimizedAllocate(TNode<IntPtrT> size,
    1111             :                                                    AllocationType allocation) {
    1112             :   return UncheckedCast<HeapObject>(
    1113       64444 :       raw_assembler()->OptimizedAllocate(size, allocation));
    1114             : }
    1115             : 
    1116      251318 : void CodeAssembler::HandleException(Node* node) {
    1117      746446 :   if (state_->exception_handler_labels_.size() == 0) return;
    1118             :   CodeAssemblerExceptionHandlerLabel* label =
    1119        7508 :       state_->exception_handler_labels_.back();
    1120             : 
    1121        7508 :   if (node->op()->HasProperty(Operator::kNoThrow)) {
    1122             :     return;
    1123             :   }
    1124             : 
    1125        7508 :   Label success(this), exception(this, Label::kDeferred);
    1126        7508 :   success.MergeVariables();
    1127        7508 :   exception.MergeVariables();
    1128             : 
    1129       15016 :   raw_assembler()->Continuations(node, success.label_, exception.label_);
    1130             : 
    1131             :   Bind(&exception);
    1132        7508 :   const Operator* op = raw_assembler()->common()->IfException();
    1133             :   Node* exception_value = raw_assembler()->AddNode(op, node, node);
    1134        7508 :   label->AddInputs({UncheckedCast<Object>(exception_value)});
    1135             :   Goto(label->plain_label());
    1136             : 
    1137             :   Bind(&success);
    1138        7508 :   raw_assembler()->AddNode(raw_assembler()->common()->IfSuccess(), node);
    1139             : }
    1140             : 
    1141             : namespace {
    1142             : template <size_t kMaxSize>
    1143      267342 : class NodeArray {
    1144             :  public:
    1145             :   void Add(Node* node) {
    1146             :     DCHECK_GT(kMaxSize, size());
    1147     1183694 :     *ptr_++ = node;
    1148             :   }
    1149             : 
    1150             :   Node* const* data() const { return arr_; }
    1151      267342 :   int size() const { return static_cast<int>(ptr_ - arr_); }
    1152             : 
    1153             :  private:
    1154             :   Node* arr_[kMaxSize];
    1155             :   Node** ptr_ = arr_;
    1156             : };
    1157             : }  // namespace
    1158             : 
    1159      140096 : TNode<Object> CodeAssembler::CallRuntimeImpl(
    1160             :     Runtime::FunctionId function, TNode<Object> context,
    1161             :     std::initializer_list<TNode<Object>> args) {
    1162      140096 :   int result_size = Runtime::FunctionForId(function)->result_size;
    1163             :   TNode<Code> centry =
    1164      280192 :       HeapConstant(CodeFactory::RuntimeCEntry(isolate(), result_size));
    1165      140096 :   return CallRuntimeWithCEntryImpl(function, centry, context, args);
    1166             : }
    1167             : 
    1168      140320 : TNode<Object> CodeAssembler::CallRuntimeWithCEntryImpl(
    1169             :     Runtime::FunctionId function, TNode<Code> centry, TNode<Object> context,
    1170             :     std::initializer_list<TNode<Object>> args) {
    1171             :   constexpr size_t kMaxNumArgs = 6;
    1172             :   DCHECK_GE(kMaxNumArgs, args.size());
    1173      140320 :   int argc = static_cast<int>(args.size());
    1174      140320 :   auto call_descriptor = Linkage::GetRuntimeCallDescriptor(
    1175             :       zone(), function, argc, Operator::kNoProperties,
    1176      140320 :       CallDescriptor::kNoFlags);
    1177             : 
    1178      140320 :   Node* ref = ExternalConstant(ExternalReference::Create(function));
    1179             :   Node* arity = Int32Constant(argc);
    1180             : 
    1181             :   NodeArray<kMaxNumArgs + 4> inputs;
    1182             :   inputs.Add(centry);
    1183      506992 :   for (auto arg : args) inputs.Add(arg);
    1184             :   inputs.Add(ref);
    1185             :   inputs.Add(arity);
    1186             :   inputs.Add(context);
    1187             : 
    1188      140320 :   CallPrologue();
    1189             :   Node* return_value =
    1190      140320 :       raw_assembler()->CallN(call_descriptor, inputs.size(), inputs.data());
    1191      140320 :   HandleException(return_value);
    1192      140320 :   CallEpilogue();
    1193      140320 :   return UncheckedCast<Object>(return_value);
    1194             : }
    1195             : 
    1196        7960 : void CodeAssembler::TailCallRuntimeImpl(
    1197             :     Runtime::FunctionId function, TNode<Int32T> arity, TNode<Object> context,
    1198             :     std::initializer_list<TNode<Object>> args) {
    1199        7960 :   int result_size = Runtime::FunctionForId(function)->result_size;
    1200             :   TNode<Code> centry =
    1201       15920 :       HeapConstant(CodeFactory::RuntimeCEntry(isolate(), result_size));
    1202        7960 :   return TailCallRuntimeWithCEntryImpl(function, arity, centry, context, args);
    1203             : }
    1204             : 
    1205        9024 : void CodeAssembler::TailCallRuntimeWithCEntryImpl(
    1206             :     Runtime::FunctionId function, TNode<Int32T> arity, TNode<Code> centry,
    1207             :     TNode<Object> context, std::initializer_list<TNode<Object>> args) {
    1208             :   constexpr size_t kMaxNumArgs = 6;
    1209             :   DCHECK_GE(kMaxNumArgs, args.size());
    1210        9024 :   int argc = static_cast<int>(args.size());
    1211        9024 :   auto call_descriptor = Linkage::GetRuntimeCallDescriptor(
    1212             :       zone(), function, argc, Operator::kNoProperties,
    1213        9024 :       CallDescriptor::kNoFlags);
    1214             : 
    1215        9024 :   Node* ref = ExternalConstant(ExternalReference::Create(function));
    1216             : 
    1217             :   NodeArray<kMaxNumArgs + 4> inputs;
    1218             :   inputs.Add(centry);
    1219       65384 :   for (auto arg : args) inputs.Add(arg);
    1220             :   inputs.Add(ref);
    1221             :   inputs.Add(arity);
    1222             :   inputs.Add(context);
    1223             : 
    1224        9024 :   raw_assembler()->TailCallN(call_descriptor, inputs.size(), inputs.data());
    1225        9024 : }
    1226             : 
    1227      110998 : Node* CodeAssembler::CallStubN(StubCallMode call_mode,
    1228             :                                const CallInterfaceDescriptor& descriptor,
    1229             :                                size_t result_size, int input_count,
    1230             :                                Node* const* inputs) {
    1231             :   DCHECK(call_mode == StubCallMode::kCallCodeObject ||
    1232             :          call_mode == StubCallMode::kCallBuiltinPointer);
    1233             : 
    1234             :   // implicit nodes are target and optionally context.
    1235      110998 :   int implicit_nodes = descriptor.HasContextParameter() ? 2 : 1;
    1236             :   DCHECK_LE(implicit_nodes, input_count);
    1237      110998 :   int argc = input_count - implicit_nodes;
    1238             :   DCHECK_LE(descriptor.GetParameterCount(), argc);
    1239             :   // Extra arguments not mentioned in the descriptor are passed on the stack.
    1240      110998 :   int stack_parameter_count = argc - descriptor.GetRegisterParameterCount();
    1241             :   DCHECK_LE(descriptor.GetStackParameterCount(), stack_parameter_count);
    1242             :   DCHECK_EQ(result_size, descriptor.GetReturnCount());
    1243             : 
    1244      110998 :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    1245             :       zone(), descriptor, stack_parameter_count, CallDescriptor::kNoFlags,
    1246      110998 :       Operator::kNoProperties, call_mode);
    1247             : 
    1248      110998 :   CallPrologue();
    1249             :   Node* return_value =
    1250      110998 :       raw_assembler()->CallN(call_descriptor, input_count, inputs);
    1251      110998 :   HandleException(return_value);
    1252      110998 :   CallEpilogue();
    1253      110998 :   return return_value;
    1254             : }
    1255             : 
    1256        7504 : void CodeAssembler::TailCallStubImpl(const CallInterfaceDescriptor& descriptor,
    1257             :                                      TNode<Code> target, TNode<Object> context,
    1258             :                                      std::initializer_list<Node*> args) {
    1259             :   constexpr size_t kMaxNumArgs = 11;
    1260             :   DCHECK_GE(kMaxNumArgs, args.size());
    1261             :   DCHECK_EQ(descriptor.GetParameterCount(), args.size());
    1262        7504 :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    1263             :       zone(), descriptor, descriptor.GetStackParameterCount(),
    1264        7504 :       CallDescriptor::kNoFlags, Operator::kNoProperties);
    1265             : 
    1266             :   NodeArray<kMaxNumArgs + 2> inputs;
    1267             :   inputs.Add(target);
    1268       56336 :   for (auto arg : args) inputs.Add(arg);
    1269        7504 :   if (descriptor.HasContextParameter()) {
    1270             :     inputs.Add(context);
    1271             :   }
    1272             : 
    1273        7504 :   raw_assembler()->TailCallN(call_descriptor, inputs.size(), inputs.data());
    1274        7504 : }
    1275             : 
    1276      108310 : Node* CodeAssembler::CallStubRImpl(StubCallMode call_mode,
    1277             :                                    const CallInterfaceDescriptor& descriptor,
    1278             :                                    size_t result_size, Node* target,
    1279             :                                    SloppyTNode<Object> context,
    1280             :                                    std::initializer_list<Node*> args) {
    1281             :   DCHECK(call_mode == StubCallMode::kCallCodeObject ||
    1282             :          call_mode == StubCallMode::kCallBuiltinPointer);
    1283             : 
    1284             :   constexpr size_t kMaxNumArgs = 10;
    1285             :   DCHECK_GE(kMaxNumArgs, args.size());
    1286             : 
    1287             :   NodeArray<kMaxNumArgs + 2> inputs;
    1288             :   inputs.Add(target);
    1289      603954 :   for (auto arg : args) inputs.Add(arg);
    1290      108310 :   if (descriptor.HasContextParameter()) {
    1291             :     inputs.Add(context);
    1292             :   }
    1293             : 
    1294             :   return CallStubN(call_mode, descriptor, result_size, inputs.size(),
    1295      108310 :                    inputs.data());
    1296             : }
    1297             : 
    1298        2184 : Node* CodeAssembler::TailCallStubThenBytecodeDispatchImpl(
    1299             :     const CallInterfaceDescriptor& descriptor, Node* target, Node* context,
    1300             :     std::initializer_list<Node*> args) {
    1301             :   constexpr size_t kMaxNumArgs = 6;
    1302             :   DCHECK_GE(kMaxNumArgs, args.size());
    1303             : 
    1304             :   DCHECK_LE(descriptor.GetParameterCount(), args.size());
    1305        2184 :   int argc = static_cast<int>(args.size());
    1306             :   // Extra arguments not mentioned in the descriptor are passed on the stack.
    1307        2184 :   int stack_parameter_count = argc - descriptor.GetRegisterParameterCount();
    1308             :   DCHECK_LE(descriptor.GetStackParameterCount(), stack_parameter_count);
    1309        2184 :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    1310             :       zone(), descriptor, stack_parameter_count, CallDescriptor::kNoFlags,
    1311        2184 :       Operator::kNoProperties);
    1312             : 
    1313             :   NodeArray<kMaxNumArgs + 2> inputs;
    1314             :   inputs.Add(target);
    1315       17304 :   for (auto arg : args) inputs.Add(arg);
    1316             :   inputs.Add(context);
    1317             : 
    1318             :   return raw_assembler()->TailCallN(call_descriptor, inputs.size(),
    1319        2184 :                                     inputs.data());
    1320             : }
    1321             : 
    1322             : template <class... TArgs>
    1323       43680 : Node* CodeAssembler::TailCallBytecodeDispatch(
    1324             :     const CallInterfaceDescriptor& descriptor, Node* target, TArgs... args) {
    1325             :   DCHECK_EQ(descriptor.GetParameterCount(), sizeof...(args));
    1326             :   auto call_descriptor = Linkage::GetBytecodeDispatchCallDescriptor(
    1327       43680 :       zone(), descriptor, descriptor.GetStackParameterCount());
    1328             : 
    1329       43680 :   Node* nodes[] = {target, args...};
    1330       87360 :   CHECK_EQ(descriptor.GetParameterCount() + 1, arraysize(nodes));
    1331       43680 :   return raw_assembler()->TailCallN(call_descriptor, arraysize(nodes), nodes);
    1332             : }
    1333             : 
    1334             : // Instantiate TailCallBytecodeDispatch() for argument counts used by
    1335             : // CSA-generated code
    1336             : template V8_EXPORT_PRIVATE Node* CodeAssembler::TailCallBytecodeDispatch(
    1337             :     const CallInterfaceDescriptor& descriptor, Node* target, Node*, Node*,
    1338             :     Node*, Node*);
    1339             : 
    1340         504 : TNode<Object> CodeAssembler::TailCallJSCode(TNode<Code> code,
    1341             :                                             TNode<Context> context,
    1342             :                                             TNode<JSFunction> function,
    1343             :                                             TNode<Object> new_target,
    1344             :                                             TNode<Int32T> arg_count) {
    1345             :   JSTrampolineDescriptor descriptor;
    1346         504 :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    1347             :       zone(), descriptor, descriptor.GetStackParameterCount(),
    1348         504 :       CallDescriptor::kFixedTargetRegister, Operator::kNoProperties);
    1349             : 
    1350        2520 :   Node* nodes[] = {code, function, new_target, arg_count, context};
    1351        1008 :   CHECK_EQ(descriptor.GetParameterCount() + 2, arraysize(nodes));
    1352             :   return UncheckedCast<Object>(
    1353        1008 :       raw_assembler()->TailCallN(call_descriptor, arraysize(nodes), nodes));
    1354             : }
    1355             : 
    1356           0 : Node* CodeAssembler::CallCFunctionN(Signature<MachineType>* signature,
    1357             :                                     int input_count, Node* const* inputs) {
    1358           0 :   auto call_descriptor = Linkage::GetSimplifiedCDescriptor(zone(), signature);
    1359           0 :   return raw_assembler()->CallN(call_descriptor, input_count, inputs);
    1360             : }
    1361             : 
    1362         504 : Node* CodeAssembler::CallCFunction1(MachineType return_type,
    1363             :                                     MachineType arg0_type, Node* function,
    1364             :                                     Node* arg0) {
    1365             :   return raw_assembler()->CallCFunction1(return_type, arg0_type, function,
    1366         504 :                                          arg0);
    1367             : }
    1368             : 
    1369         224 : Node* CodeAssembler::CallCFunction1WithCallerSavedRegisters(
    1370             :     MachineType return_type, MachineType arg0_type, Node* function, Node* arg0,
    1371             :     SaveFPRegsMode mode) {
    1372             :   DCHECK(return_type.LessThanOrEqualPointerSize());
    1373             :   return raw_assembler()->CallCFunction1WithCallerSavedRegisters(
    1374         224 :       return_type, arg0_type, function, arg0, mode);
    1375             : }
    1376             : 
    1377        4492 : Node* CodeAssembler::CallCFunction2(MachineType return_type,
    1378             :                                     MachineType arg0_type,
    1379             :                                     MachineType arg1_type, Node* function,
    1380             :                                     Node* arg0, Node* arg1) {
    1381             :   return raw_assembler()->CallCFunction2(return_type, arg0_type, arg1_type,
    1382        4492 :                                          function, arg0, arg1);
    1383             : }
    1384             : 
    1385        5908 : Node* CodeAssembler::CallCFunction3(MachineType return_type,
    1386             :                                     MachineType arg0_type,
    1387             :                                     MachineType arg1_type,
    1388             :                                     MachineType arg2_type, Node* function,
    1389             :                                     Node* arg0, Node* arg1, Node* arg2) {
    1390             :   return raw_assembler()->CallCFunction3(return_type, arg0_type, arg1_type,
    1391        5908 :                                          arg2_type, function, arg0, arg1, arg2);
    1392             : }
    1393             : 
    1394         116 : Node* CodeAssembler::CallCFunction3WithCallerSavedRegisters(
    1395             :     MachineType return_type, MachineType arg0_type, MachineType arg1_type,
    1396             :     MachineType arg2_type, Node* function, Node* arg0, Node* arg1, Node* arg2,
    1397             :     SaveFPRegsMode mode) {
    1398             :   DCHECK(return_type.LessThanOrEqualPointerSize());
    1399             :   return raw_assembler()->CallCFunction3WithCallerSavedRegisters(
    1400             :       return_type, arg0_type, arg1_type, arg2_type, function, arg0, arg1, arg2,
    1401         116 :       mode);
    1402             : }
    1403             : 
    1404         112 : Node* CodeAssembler::CallCFunction4(
    1405             :     MachineType return_type, MachineType arg0_type, MachineType arg1_type,
    1406             :     MachineType arg2_type, MachineType arg3_type, Node* function, Node* arg0,
    1407             :     Node* arg1, Node* arg2, Node* arg3) {
    1408             :   return raw_assembler()->CallCFunction4(return_type, arg0_type, arg1_type,
    1409             :                                          arg2_type, arg3_type, function, arg0,
    1410         112 :                                          arg1, arg2, arg3);
    1411             : }
    1412             : 
    1413         280 : Node* CodeAssembler::CallCFunction5(
    1414             :     MachineType return_type, MachineType arg0_type, MachineType arg1_type,
    1415             :     MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
    1416             :     Node* function, Node* arg0, Node* arg1, Node* arg2, Node* arg3,
    1417             :     Node* arg4) {
    1418             :   return raw_assembler()->CallCFunction5(
    1419             :       return_type, arg0_type, arg1_type, arg2_type, arg3_type, arg4_type,
    1420         280 :       function, arg0, arg1, arg2, arg3, arg4);
    1421             : }
    1422             : 
    1423         672 : Node* CodeAssembler::CallCFunction6(
    1424             :     MachineType return_type, MachineType arg0_type, MachineType arg1_type,
    1425             :     MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
    1426             :     MachineType arg5_type, Node* function, Node* arg0, Node* arg1, Node* arg2,
    1427             :     Node* arg3, Node* arg4, Node* arg5) {
    1428             :   return raw_assembler()->CallCFunction6(
    1429             :       return_type, arg0_type, arg1_type, arg2_type, arg3_type, arg4_type,
    1430         672 :       arg5_type, function, arg0, arg1, arg2, arg3, arg4, arg5);
    1431             : }
    1432             : 
    1433         564 : Node* CodeAssembler::CallCFunction9(
    1434             :     MachineType return_type, MachineType arg0_type, MachineType arg1_type,
    1435             :     MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
    1436             :     MachineType arg5_type, MachineType arg6_type, MachineType arg7_type,
    1437             :     MachineType arg8_type, Node* function, Node* arg0, Node* arg1, Node* arg2,
    1438             :     Node* arg3, Node* arg4, Node* arg5, Node* arg6, Node* arg7, Node* arg8) {
    1439             :   return raw_assembler()->CallCFunction9(
    1440             :       return_type, arg0_type, arg1_type, arg2_type, arg3_type, arg4_type,
    1441             :       arg5_type, arg6_type, arg7_type, arg8_type, function, arg0, arg1, arg2,
    1442         564 :       arg3, arg4, arg5, arg6, arg7, arg8);
    1443             : }
    1444             : 
    1445     2120193 : void CodeAssembler::Goto(Label* label) {
    1446     2132493 :   label->MergeVariables();
    1447     4264986 :   raw_assembler()->Goto(label->label_);
    1448     2120193 : }
    1449             : 
    1450      578668 : void CodeAssembler::GotoIf(SloppyTNode<IntegralT> condition,
    1451             :                            Label* true_label) {
    1452      578668 :   Label false_label(this);
    1453      578668 :   Branch(condition, true_label, &false_label);
    1454             :   Bind(&false_label);
    1455      578668 : }
    1456             : 
    1457      172855 : void CodeAssembler::GotoIfNot(SloppyTNode<IntegralT> condition,
    1458             :                               Label* false_label) {
    1459      172855 :   Label true_label(this);
    1460      172855 :   Branch(condition, &true_label, false_label);
    1461             :   Bind(&true_label);
    1462      172855 : }
    1463             : 
    1464     1341127 : void CodeAssembler::Branch(SloppyTNode<IntegralT> condition, Label* true_label,
    1465             :                            Label* false_label) {
    1466             :   int32_t constant;
    1467     1341127 :   if (ToInt32Constant(condition, constant)) {
    1468         976 :     if ((true_label->is_used() || true_label->is_bound()) &&
    1469           0 :         (false_label->is_used() || false_label->is_bound())) {
    1470           0 :       return Goto(constant ? true_label : false_label);
    1471             :     }
    1472             :   }
    1473     1341127 :   true_label->MergeVariables();
    1474     1341127 :   false_label->MergeVariables();
    1475     1341127 :   return raw_assembler()->Branch(condition, true_label->label_,
    1476     1341127 :                                  false_label->label_);
    1477             : }
    1478             : 
    1479       26772 : void CodeAssembler::Branch(TNode<BoolT> condition,
    1480             :                            const std::function<void()>& true_body,
    1481             :                            const std::function<void()>& false_body) {
    1482             :   int32_t constant;
    1483       26772 :   if (ToInt32Constant(condition, constant)) {
    1484           0 :     return constant ? true_body() : false_body();
    1485             :   }
    1486             : 
    1487       26772 :   Label vtrue(this), vfalse(this);
    1488       26772 :   Branch(condition, &vtrue, &vfalse);
    1489             : 
    1490             :   Bind(&vtrue);
    1491             :   true_body();
    1492             : 
    1493             :   Bind(&vfalse);
    1494             :   false_body();
    1495             : }
    1496             : 
    1497         976 : void CodeAssembler::Branch(TNode<BoolT> condition, Label* true_label,
    1498             :                            const std::function<void()>& false_body) {
    1499             :   int32_t constant;
    1500         976 :   if (ToInt32Constant(condition, constant)) {
    1501        1272 :     return constant ? Goto(true_label) : false_body();
    1502             :   }
    1503             : 
    1504         340 :   Label vfalse(this);
    1505         340 :   Branch(condition, true_label, &vfalse);
    1506             :   Bind(&vfalse);
    1507             :   false_body();
    1508             : }
    1509             : 
    1510           0 : void CodeAssembler::Branch(TNode<BoolT> condition,
    1511             :                            const std::function<void()>& true_body,
    1512             :                            Label* false_label) {
    1513             :   int32_t constant;
    1514           0 :   if (ToInt32Constant(condition, constant)) {
    1515           0 :     return constant ? true_body() : Goto(false_label);
    1516             :   }
    1517             : 
    1518           0 :   Label vtrue(this);
    1519           0 :   Branch(condition, &vtrue, false_label);
    1520             :   Bind(&vtrue);
    1521             :   true_body();
    1522             : }
    1523             : 
    1524        9936 : void CodeAssembler::Switch(Node* index, Label* default_label,
    1525             :                            const int32_t* case_values, Label** case_labels,
    1526             :                            size_t case_count) {
    1527             :   RawMachineLabel** labels =
    1528        9936 :       new (zone()->New(sizeof(RawMachineLabel*) * case_count))
    1529        9936 :           RawMachineLabel*[case_count];
    1530      159800 :   for (size_t i = 0; i < case_count; ++i) {
    1531       74932 :     labels[i] = case_labels[i]->label_;
    1532       74932 :     case_labels[i]->MergeVariables();
    1533             :   }
    1534        9936 :   default_label->MergeVariables();
    1535        9936 :   return raw_assembler()->Switch(index, default_label->label_, case_values,
    1536        9936 :                                  labels, case_count);
    1537             : }
    1538             : 
    1539         112 : bool CodeAssembler::UnalignedLoadSupported(MachineRepresentation rep) const {
    1540         112 :   return raw_assembler()->machine()->UnalignedLoadSupported(rep);
    1541             : }
    1542         112 : bool CodeAssembler::UnalignedStoreSupported(MachineRepresentation rep) const {
    1543         112 :   return raw_assembler()->machine()->UnalignedStoreSupported(rep);
    1544             : }
    1545             : 
    1546             : // RawMachineAssembler delegate helpers:
    1547      370288 : Isolate* CodeAssembler::isolate() const { return raw_assembler()->isolate(); }
    1548             : 
    1549        8736 : Factory* CodeAssembler::factory() const { return isolate()->factory(); }
    1550             : 
    1551      137296 : Zone* CodeAssembler::zone() const { return raw_assembler()->zone(); }
    1552             : 
    1553           0 : bool CodeAssembler::IsExceptionHandlerActive() const {
    1554           0 :   return state_->exception_handler_labels_.size() != 0;
    1555             : }
    1556             : 
    1557           0 : RawMachineAssembler* CodeAssembler::raw_assembler() const {
    1558    24362316 :   return state_->raw_assembler_.get();
    1559             : }
    1560             : 
    1561             : // The core implementation of Variable is stored through an indirection so
    1562             : // that it can outlive the often block-scoped Variable declarations. This is
    1563             : // needed to ensure that variable binding and merging through phis can
    1564             : // properly be verified.
    1565             : class CodeAssemblerVariable::Impl : public ZoneObject {
    1566             :  public:
    1567             :   explicit Impl(MachineRepresentation rep, CodeAssemblerState::VariableId id)
    1568             :       :
    1569             : #if DEBUG
    1570             :         debug_info_(AssemblerDebugInfo(nullptr, nullptr, -1)),
    1571             : #endif
    1572             :         value_(nullptr),
    1573             :         rep_(rep),
    1574      616302 :         var_id_(id) {
    1575             :   }
    1576             : 
    1577             : #if DEBUG
    1578             :   AssemblerDebugInfo debug_info() const { return debug_info_; }
    1579             :   void set_debug_info(AssemblerDebugInfo debug_info) {
    1580             :     debug_info_ = debug_info;
    1581             :   }
    1582             : 
    1583             :   AssemblerDebugInfo debug_info_;
    1584             : #endif  // DEBUG
    1585             :   bool operator<(const CodeAssemblerVariable::Impl& other) const {
    1586     1214417 :     return var_id_ < other.var_id_;
    1587             :   }
    1588             :   Node* value_;
    1589             :   MachineRepresentation rep_;
    1590             :   CodeAssemblerState::VariableId var_id_;
    1591             : };
    1592             : 
    1593           0 : bool CodeAssemblerVariable::ImplComparator::operator()(
    1594             :     const CodeAssemblerVariable::Impl* a,
    1595             :     const CodeAssemblerVariable::Impl* b) const {
    1596           0 :   return *a < *b;
    1597             : }
    1598             : 
    1599      616302 : CodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler,
    1600             :                                              MachineRepresentation rep)
    1601             :     : impl_(new (assembler->zone())
    1602             :                 Impl(rep, assembler->state()->NextVariableId())),
    1603     1232604 :       state_(assembler->state()) {
    1604      616302 :   state_->variables_.insert(impl_);
    1605      616302 : }
    1606             : 
    1607      273021 : CodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler,
    1608             :                                              MachineRepresentation rep,
    1609             :                                              Node* initial_value)
    1610      273021 :     : CodeAssemblerVariable(assembler, rep) {
    1611             :   Bind(initial_value);
    1612      273021 : }
    1613             : 
    1614             : #if DEBUG
    1615             : CodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler,
    1616             :                                              AssemblerDebugInfo debug_info,
    1617             :                                              MachineRepresentation rep)
    1618             :     : impl_(new (assembler->zone())
    1619             :                 Impl(rep, assembler->state()->NextVariableId())),
    1620             :       state_(assembler->state()) {
    1621             :   impl_->set_debug_info(debug_info);
    1622             :   state_->variables_.insert(impl_);
    1623             : }
    1624             : 
    1625             : CodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler,
    1626             :                                              AssemblerDebugInfo debug_info,
    1627             :                                              MachineRepresentation rep,
    1628             :                                              Node* initial_value)
    1629             :     : CodeAssemblerVariable(assembler, debug_info, rep) {
    1630             :   impl_->set_debug_info(debug_info);
    1631             :   Bind(initial_value);
    1632             : }
    1633             : #endif  // DEBUG
    1634             : 
    1635     1232604 : CodeAssemblerVariable::~CodeAssemblerVariable() {
    1636      616302 :   state_->variables_.erase(impl_);
    1637      616302 : }
    1638             : 
    1639     1363416 : void CodeAssemblerVariable::Bind(Node* value) { impl_->value_ = value; }
    1640             : 
    1641     1506379 : Node* CodeAssemblerVariable::value() const {
    1642             : #if DEBUG
    1643             :   if (!IsBound()) {
    1644             :     std::stringstream str;
    1645             :     str << "#Use of unbound variable:"
    1646             :         << "#\n    Variable:      " << *this << "#\n    Current Block: ";
    1647             :     state_->PrintCurrentBlock(str);
    1648             :     FATAL("%s", str.str().c_str());
    1649             :   }
    1650             :   if (!state_->InsideBlock()) {
    1651             :     std::stringstream str;
    1652             :     str << "#Accessing variable value outside a block:"
    1653             :         << "#\n    Variable:      " << *this;
    1654             :     FATAL("%s", str.str().c_str());
    1655             :   }
    1656             : #endif  // DEBUG
    1657     1506379 :   return impl_->value_;
    1658             : }
    1659             : 
    1660           0 : MachineRepresentation CodeAssemblerVariable::rep() const { return impl_->rep_; }
    1661             : 
    1662      143565 : bool CodeAssemblerVariable::IsBound() const { return impl_->value_ != nullptr; }
    1663             : 
    1664           0 : std::ostream& operator<<(std::ostream& os,
    1665             :                          const CodeAssemblerVariable::Impl& impl) {
    1666             : #if DEBUG
    1667             :   AssemblerDebugInfo info = impl.debug_info();
    1668             :   if (info.name) os << "V" << info;
    1669             : #endif  // DEBUG
    1670           0 :   return os;
    1671             : }
    1672             : 
    1673           0 : std::ostream& operator<<(std::ostream& os,
    1674             :                          const CodeAssemblerVariable& variable) {
    1675             :   os << *variable.impl_;
    1676           0 :   return os;
    1677             : }
    1678             : 
    1679     3722508 : CodeAssemblerLabel::CodeAssemblerLabel(CodeAssembler* assembler,
    1680             :                                        size_t vars_count,
    1681             :                                        CodeAssemblerVariable* const* vars,
    1682             :                                        CodeAssemblerLabel::Type type)
    1683             :     : bound_(false),
    1684             :       merge_count_(0),
    1685             :       state_(assembler->state()),
    1686     7445016 :       label_(nullptr) {
    1687             :   void* buffer = assembler->zone()->New(sizeof(RawMachineLabel));
    1688             :   label_ = new (buffer)
    1689             :       RawMachineLabel(type == kDeferred ? RawMachineLabel::kDeferred
    1690     7445016 :                                         : RawMachineLabel::kNonDeferred);
    1691     4155444 :   for (size_t i = 0; i < vars_count; ++i) {
    1692      216468 :     variable_phis_[vars[i]->impl_] = nullptr;
    1693             :   }
    1694     3722508 : }
    1695             : 
    1696     7445016 : CodeAssemblerLabel::~CodeAssemblerLabel() { label_->~RawMachineLabel(); }
    1697             : 
    1698     4923287 : void CodeAssemblerLabel::MergeVariables() {
    1699     4923287 :   ++merge_count_;
    1700    26779149 :   for (CodeAssemblerVariable::Impl* var : state_->variables_) {
    1701             :     size_t count = 0;
    1702    16932575 :     Node* node = var->value_;
    1703    16932575 :     if (node != nullptr) {
    1704             :       auto i = variable_merges_.find(var);
    1705    12248917 :       if (i != variable_merges_.end()) {
    1706     4326177 :         i->second.push_back(node);
    1707             :         count = i->second.size();
    1708             :       } else {
    1709             :         count = 1;
    1710    15845480 :         variable_merges_[var] = std::vector<Node*>(1, node);
    1711             :       }
    1712             :     }
    1713             :     // If the following asserts, then you've jumped to a label without a bound
    1714             :     // variable along that path that expects to merge its value into a phi.
    1715             :     DCHECK(variable_phis_.find(var) == variable_phis_.end() ||
    1716             :            count == merge_count_);
    1717             :     USE(count);
    1718             : 
    1719             :     // If the label is already bound, we already know the set of variables to
    1720             :     // merge and phi nodes have already been created.
    1721    16932575 :     if (bound_) {
    1722             :       auto phi = variable_phis_.find(var);
    1723      749108 :       if (phi != variable_phis_.end()) {
    1724             :         DCHECK_NOT_NULL(phi->second);
    1725      431912 :         state_->raw_assembler_->AppendPhiInput(phi->second, node);
    1726             :       } else {
    1727             :         auto i = variable_merges_.find(var);
    1728             :         if (i != variable_merges_.end()) {
    1729             :           // If the following assert fires, then you've declared a variable that
    1730             :           // has the same bound value along all paths up until the point you
    1731             :           // bound this label, but then later merged a path with a new value for
    1732             :           // the variable after the label bind (it's not possible to add phis to
    1733             :           // the bound label after the fact, just make sure to list the variable
    1734             :           // in the label's constructor's list of merged variables).
    1735             : #if DEBUG
    1736             :           if (find_if(i->second.begin(), i->second.end(),
    1737             :                       [node](Node* e) -> bool { return node != e; }) !=
    1738             :               i->second.end()) {
    1739             :             std::stringstream str;
    1740             :             str << "Unmerged variable found when jumping to block. \n"
    1741             :                 << "#    Variable:      " << *var;
    1742             :             if (bound_) {
    1743             :               str << "\n#    Target block:  " << *label_->block();
    1744             :             }
    1745             :             str << "\n#    Current Block: ";
    1746             :             state_->PrintCurrentBlock(str);
    1747             :             FATAL("%s", str.str().c_str());
    1748             :           }
    1749             : #endif  // DEBUG
    1750             :         }
    1751             :       }
    1752             :     }
    1753             :   }
    1754     4923287 : }
    1755             : 
    1756             : #if DEBUG
    1757             : void CodeAssemblerLabel::Bind(AssemblerDebugInfo debug_info) {
    1758             :   if (bound_) {
    1759             :     std::stringstream str;
    1760             :     str << "Cannot bind the same label twice:"
    1761             :         << "\n#    current:  " << debug_info
    1762             :         << "\n#    previous: " << *label_->block();
    1763             :     FATAL("%s", str.str().c_str());
    1764             :   }
    1765             :   if (FLAG_enable_source_at_csa_bind) {
    1766             :     state_->raw_assembler_->SetSourcePosition(debug_info.file, debug_info.line);
    1767             :   }
    1768             :   state_->raw_assembler_->Bind(label_, debug_info);
    1769             :   UpdateVariablesAfterBind();
    1770             : }
    1771             : #endif  // DEBUG
    1772             : 
    1773     3631636 : void CodeAssemblerLabel::Bind() {
    1774             :   DCHECK(!bound_);
    1775     7263272 :   state_->raw_assembler_->Bind(label_);
    1776     3631636 :   UpdateVariablesAfterBind();
    1777     3631636 : }
    1778             : 
    1779     3631636 : void CodeAssemblerLabel::UpdateVariablesAfterBind() {
    1780             :   // Make sure that all variables that have changed along any path up to this
    1781             :   // point are marked as merge variables.
    1782    18337031 :   for (auto var : state_->variables_) {
    1783             :     Node* shared_value = nullptr;
    1784             :     auto i = variable_merges_.find(var);
    1785    11073759 :     if (i != variable_merges_.end()) {
    1786    18830645 :       for (auto value : i->second) {
    1787             :         DCHECK_NOT_NULL(value);
    1788    11090377 :         if (value != shared_value) {
    1789     8404339 :           if (shared_value == nullptr) {
    1790             :             shared_value = value;
    1791             :           } else {
    1792      664071 :             variable_phis_[var] = nullptr;
    1793             :           }
    1794             :         }
    1795             :       }
    1796             :     }
    1797             :   }
    1798             : 
    1799     4204989 :   for (auto var : variable_phis_) {
    1800      573353 :     CodeAssemblerVariable::Impl* var_impl = var.first;
    1801             :     auto i = variable_merges_.find(var_impl);
    1802             : #if DEBUG
    1803             :     bool not_found = i == variable_merges_.end();
    1804             :     if (not_found || i->second.size() != merge_count_) {
    1805             :       std::stringstream str;
    1806             :       str << "A variable that has been marked as beeing merged at the label"
    1807             :           << "\n# doesn't have a bound value along all of the paths that "
    1808             :           << "\n# have been merged into the label up to this point."
    1809             :           << "\n#"
    1810             :           << "\n# This can happen in the following cases:"
    1811             :           << "\n# - By explicitly marking it so in the label constructor"
    1812             :           << "\n# - By having seen different bound values at branches"
    1813             :           << "\n#"
    1814             :           << "\n# Merge count:     expected=" << merge_count_
    1815             :           << " vs. found=" << (not_found ? 0 : i->second.size())
    1816             :           << "\n# Variable:      " << *var_impl
    1817             :           << "\n# Current Block: " << *label_->block();
    1818             :       FATAL("%s", str.str().c_str());
    1819             :     }
    1820             : #endif  // DEBUG
    1821      573353 :     Node* phi = state_->raw_assembler_->Phi(
    1822     1146706 :         var.first->rep_, static_cast<int>(merge_count_), &(i->second[0]));
    1823      573353 :     variable_phis_[var_impl] = phi;
    1824             :   }
    1825             : 
    1826             :   // Bind all variables to a merge phi, the common value along all paths or
    1827             :   // null.
    1828    18337031 :   for (auto var : state_->variables_) {
    1829             :     auto i = variable_phis_.find(var);
    1830    11073759 :     if (i != variable_phis_.end()) {
    1831      573353 :       var->value_ = i->second;
    1832             :     } else {
    1833             :       auto j = variable_merges_.find(var);
    1834    17667321 :       if (j != variable_merges_.end() && j->second.size() == merge_count_) {
    1835    14245422 :         var->value_ = j->second.back();
    1836             :       } else {
    1837     3377695 :         var->value_ = nullptr;
    1838             :       }
    1839             :     }
    1840             :   }
    1841             : 
    1842     3631636 :   bound_ = true;
    1843     3631636 : }
    1844             : 
    1845     1332280 : void CodeAssemblerParameterizedLabelBase::AddInputs(std::vector<Node*> inputs) {
    1846     1332280 :   if (!phi_nodes_.empty()) {
    1847             :     DCHECK_EQ(inputs.size(), phi_nodes_.size());
    1848      123592 :     for (size_t i = 0; i < inputs.size(); ++i) {
    1849             :       // We use {nullptr} as a sentinel for an uninitialized value.
    1850       59080 :       if (phi_nodes_[i] == nullptr) continue;
    1851      118160 :       state_->raw_assembler_->AppendPhiInput(phi_nodes_[i], inputs[i]);
    1852             :     }
    1853             :   } else {
    1854             :     DCHECK_EQ(inputs.size(), phi_inputs_.size());
    1855     9930256 :     for (size_t i = 0; i < inputs.size(); ++i) {
    1856     4301704 :       phi_inputs_[i].push_back(inputs[i]);
    1857             :     }
    1858             :   }
    1859     1332280 : }
    1860             : 
    1861     3891504 : Node* CodeAssemblerParameterizedLabelBase::CreatePhi(
    1862             :     MachineRepresentation rep, const std::vector<Node*>& inputs) {
    1863     8175680 :   for (Node* input : inputs) {
    1864             :     // We use {nullptr} as a sentinel for an uninitialized value. We must not
    1865             :     // create phi nodes for these.
    1866     4301088 :     if (input == nullptr) return nullptr;
    1867             :   }
    1868     3874592 :   return state_->raw_assembler_->Phi(rep, static_cast<int>(inputs.size()),
    1869     3874592 :                                      &inputs.front());
    1870             : }
    1871             : 
    1872     1245032 : const std::vector<Node*>& CodeAssemblerParameterizedLabelBase::CreatePhis(
    1873             :     std::vector<MachineRepresentation> representations) {
    1874             :   DCHECK(is_used());
    1875             :   DCHECK(phi_nodes_.empty());
    1876     1245032 :   phi_nodes_.reserve(phi_inputs_.size());
    1877             :   DCHECK_EQ(representations.size(), phi_inputs_.size());
    1878     9028040 :   for (size_t i = 0; i < phi_inputs_.size(); ++i) {
    1879     7783008 :     phi_nodes_.push_back(CreatePhi(representations[i], phi_inputs_[i]));
    1880             :   }
    1881     1245032 :   return phi_nodes_;
    1882             : }
    1883             : 
    1884           0 : void CodeAssemblerState::PushExceptionHandler(
    1885             :     CodeAssemblerExceptionHandlerLabel* label) {
    1886         956 :   exception_handler_labels_.push_back(label);
    1887           0 : }
    1888             : 
    1889           0 : void CodeAssemblerState::PopExceptionHandler() {
    1890             :   exception_handler_labels_.pop_back();
    1891           0 : }
    1892             : 
    1893         728 : CodeAssemblerScopedExceptionHandler::CodeAssemblerScopedExceptionHandler(
    1894             :     CodeAssembler* assembler, CodeAssemblerExceptionHandlerLabel* label)
    1895         728 :     : has_handler_(label != nullptr),
    1896             :       assembler_(assembler),
    1897             :       compatibility_label_(nullptr),
    1898        1456 :       exception_(nullptr) {
    1899         728 :   if (has_handler_) {
    1900             :     assembler_->state()->PushExceptionHandler(label);
    1901             :   }
    1902         728 : }
    1903             : 
    1904         564 : CodeAssemblerScopedExceptionHandler::CodeAssemblerScopedExceptionHandler(
    1905             :     CodeAssembler* assembler, CodeAssemblerLabel* label,
    1906             :     TypedCodeAssemblerVariable<Object>* exception)
    1907         564 :     : has_handler_(label != nullptr),
    1908             :       assembler_(assembler),
    1909             :       compatibility_label_(label),
    1910        1128 :       exception_(exception) {
    1911         564 :   if (has_handler_) {
    1912         456 :     label_ = base::make_unique<CodeAssemblerExceptionHandlerLabel>(
    1913             :         assembler, CodeAssemblerLabel::kDeferred);
    1914         228 :     assembler_->state()->PushExceptionHandler(label_.get());
    1915             :   }
    1916         564 : }
    1917             : 
    1918        2584 : CodeAssemblerScopedExceptionHandler::~CodeAssemblerScopedExceptionHandler() {
    1919        1292 :   if (has_handler_) {
    1920         956 :     assembler_->state()->PopExceptionHandler();
    1921             :   }
    1922        1292 :   if (label_ && label_->is_used()) {
    1923         456 :     CodeAssembler::Label skip(assembler_);
    1924         228 :     bool inside_block = assembler_->state()->InsideBlock();
    1925         228 :     if (inside_block) {
    1926         228 :       assembler_->Goto(&skip);
    1927             :     }
    1928             :     TNode<Object> e;
    1929             :     assembler_->Bind(label_.get(), &e);
    1930         228 :     *exception_ = e;
    1931         228 :     assembler_->Goto(compatibility_label_);
    1932         228 :     if (inside_block) {
    1933             :       assembler_->Bind(&skip);
    1934             :     }
    1935             :   }
    1936        1292 : }
    1937             : 
    1938             : }  // namespace compiler
    1939             : 
    1940           0 : Address CheckObjectType(Address raw_value, Address raw_type,
    1941             :                         Address raw_location) {
    1942             : #ifdef DEBUG
    1943             :   Object value(raw_value);
    1944             :   Smi type(raw_type);
    1945             :   String location = String::cast(Object(raw_location));
    1946             :   const char* expected;
    1947             :   switch (static_cast<ObjectType>(type->value())) {
    1948             : #define TYPE_CASE(Name)                                  \
    1949             :   case ObjectType::k##Name:                              \
    1950             :     if (value->Is##Name()) return Smi::FromInt(0).ptr(); \
    1951             :     expected = #Name;                                    \
    1952             :     break;
    1953             : #define TYPE_STRUCT_CASE(NAME, Name, name)               \
    1954             :   case ObjectType::k##Name:                              \
    1955             :     if (value->Is##Name()) return Smi::FromInt(0).ptr(); \
    1956             :     expected = #Name;                                    \
    1957             :     break;
    1958             : 
    1959             :     TYPE_CASE(Object)
    1960             :     OBJECT_TYPE_LIST(TYPE_CASE)
    1961             :     HEAP_OBJECT_TYPE_LIST(TYPE_CASE)
    1962             :     STRUCT_LIST(TYPE_STRUCT_CASE)
    1963             : #undef TYPE_CASE
    1964             : #undef TYPE_STRUCT_CASE
    1965             :   }
    1966             :   std::stringstream value_description;
    1967             :   value->Print(value_description);
    1968             :   V8_Fatal(__FILE__, __LINE__,
    1969             :            "Type cast failed in %s\n"
    1970             :            "  Expected %s but found %s",
    1971             :            location->ToAsciiArray(), expected, value_description.str().c_str());
    1972             : #else
    1973           0 :   UNREACHABLE();
    1974             : #endif
    1975             : }
    1976             : 
    1977             : }  // namespace internal
    1978      120216 : }  // namespace v8

Generated by: LCOV version 1.10