LCOV - code coverage report
Current view: top level - src/compiler - code-assembler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 591 721 82.0 %
Date: 2019-01-20 Functions: 240 290 82.8 %

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

Generated by: LCOV version 1.10