Home | History | Annotate | Download | only in compiler
      1 // Copyright 2015 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/compiler/code-assembler.h"
      6 
      7 #include <ostream>
      8 
      9 #include "src/code-factory.h"
     10 #include "src/compiler/graph.h"
     11 #include "src/compiler/instruction-selector.h"
     12 #include "src/compiler/linkage.h"
     13 #include "src/compiler/node-matchers.h"
     14 #include "src/compiler/pipeline.h"
     15 #include "src/compiler/raw-machine-assembler.h"
     16 #include "src/compiler/schedule.h"
     17 #include "src/frames.h"
     18 #include "src/interface-descriptors.h"
     19 #include "src/interpreter/bytecodes.h"
     20 #include "src/machine-type.h"
     21 #include "src/macro-assembler.h"
     22 #include "src/utils.h"
     23 #include "src/zone/zone.h"
     24 
     25 namespace v8 {
     26 namespace internal {
     27 namespace compiler {
     28 
     29 CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone,
     30                              const CallInterfaceDescriptor& descriptor,
     31                              Code::Flags flags, const char* name,
     32                              size_t result_size)
     33     : CodeAssembler(
     34           isolate, zone,
     35           Linkage::GetStubCallDescriptor(
     36               isolate, zone, descriptor, descriptor.GetStackParameterCount(),
     37               CallDescriptor::kNoFlags, Operator::kNoProperties,
     38               MachineType::AnyTagged(), result_size),
     39           flags, name) {}
     40 
     41 CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone, int parameter_count,
     42                              Code::Flags flags, const char* name)
     43     : CodeAssembler(isolate, zone,
     44                     Linkage::GetJSCallDescriptor(
     45                         zone, false, parameter_count,
     46                         Code::ExtractKindFromFlags(flags) == Code::BUILTIN
     47                             ? CallDescriptor::kPushArgumentCount
     48                             : CallDescriptor::kNoFlags),
     49                     flags, name) {}
     50 
     51 CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone,
     52                              CallDescriptor* call_descriptor, Code::Flags flags,
     53                              const char* name)
     54     : raw_assembler_(new RawMachineAssembler(
     55           isolate, new (zone) Graph(zone), call_descriptor,
     56           MachineType::PointerRepresentation(),
     57           InstructionSelector::SupportedMachineOperatorFlags(),
     58           InstructionSelector::AlignmentRequirements())),
     59       flags_(flags),
     60       name_(name),
     61       code_generated_(false),
     62       variables_(zone) {}
     63 
     64 CodeAssembler::~CodeAssembler() {}
     65 
     66 void CodeAssembler::CallPrologue() {}
     67 
     68 void CodeAssembler::CallEpilogue() {}
     69 
     70 Handle<Code> CodeAssembler::GenerateCode() {
     71   DCHECK(!code_generated_);
     72 
     73   Schedule* schedule = raw_assembler_->Export();
     74   Handle<Code> code = Pipeline::GenerateCodeForCodeStub(
     75       isolate(), raw_assembler_->call_descriptor(), raw_assembler_->graph(),
     76       schedule, flags_, name_);
     77 
     78   code_generated_ = true;
     79   return code;
     80 }
     81 
     82 bool CodeAssembler::Is64() const { return raw_assembler_->machine()->Is64(); }
     83 
     84 bool CodeAssembler::IsFloat64RoundUpSupported() const {
     85   return raw_assembler_->machine()->Float64RoundUp().IsSupported();
     86 }
     87 
     88 bool CodeAssembler::IsFloat64RoundDownSupported() const {
     89   return raw_assembler_->machine()->Float64RoundDown().IsSupported();
     90 }
     91 
     92 bool CodeAssembler::IsFloat64RoundTiesEvenSupported() const {
     93   return raw_assembler_->machine()->Float64RoundTiesEven().IsSupported();
     94 }
     95 
     96 bool CodeAssembler::IsFloat64RoundTruncateSupported() const {
     97   return raw_assembler_->machine()->Float64RoundTruncate().IsSupported();
     98 }
     99 
    100 Node* CodeAssembler::Int32Constant(int32_t value) {
    101   return raw_assembler_->Int32Constant(value);
    102 }
    103 
    104 Node* CodeAssembler::Int64Constant(int64_t value) {
    105   return raw_assembler_->Int64Constant(value);
    106 }
    107 
    108 Node* CodeAssembler::IntPtrConstant(intptr_t value) {
    109   return raw_assembler_->IntPtrConstant(value);
    110 }
    111 
    112 Node* CodeAssembler::NumberConstant(double value) {
    113   return raw_assembler_->NumberConstant(value);
    114 }
    115 
    116 Node* CodeAssembler::SmiConstant(Smi* value) {
    117   return BitcastWordToTaggedSigned(IntPtrConstant(bit_cast<intptr_t>(value)));
    118 }
    119 
    120 Node* CodeAssembler::SmiConstant(int value) {
    121   return SmiConstant(Smi::FromInt(value));
    122 }
    123 
    124 Node* CodeAssembler::HeapConstant(Handle<HeapObject> object) {
    125   return raw_assembler_->HeapConstant(object);
    126 }
    127 
    128 Node* CodeAssembler::BooleanConstant(bool value) {
    129   return raw_assembler_->BooleanConstant(value);
    130 }
    131 
    132 Node* CodeAssembler::ExternalConstant(ExternalReference address) {
    133   return raw_assembler_->ExternalConstant(address);
    134 }
    135 
    136 Node* CodeAssembler::Float64Constant(double value) {
    137   return raw_assembler_->Float64Constant(value);
    138 }
    139 
    140 Node* CodeAssembler::NaNConstant() {
    141   return LoadRoot(Heap::kNanValueRootIndex);
    142 }
    143 
    144 bool CodeAssembler::ToInt32Constant(Node* node, int32_t& out_value) {
    145   Int64Matcher m(node);
    146   if (m.HasValue() &&
    147       m.IsInRange(std::numeric_limits<int32_t>::min(),
    148                   std::numeric_limits<int32_t>::max())) {
    149     out_value = static_cast<int32_t>(m.Value());
    150     return true;
    151   }
    152 
    153   return false;
    154 }
    155 
    156 bool CodeAssembler::ToInt64Constant(Node* node, int64_t& out_value) {
    157   Int64Matcher m(node);
    158   if (m.HasValue()) out_value = m.Value();
    159   return m.HasValue();
    160 }
    161 
    162 bool CodeAssembler::ToSmiConstant(Node* node, Smi*& out_value) {
    163   if (node->opcode() == IrOpcode::kBitcastWordToTaggedSigned) {
    164     node = node->InputAt(0);
    165   } else {
    166     return false;
    167   }
    168   IntPtrMatcher m(node);
    169   if (m.HasValue()) {
    170     out_value = Smi::cast(bit_cast<Object*>(m.Value()));
    171     return true;
    172   }
    173   return false;
    174 }
    175 
    176 bool CodeAssembler::ToIntPtrConstant(Node* node, intptr_t& out_value) {
    177   IntPtrMatcher m(node);
    178   if (m.HasValue()) out_value = m.Value();
    179   return m.HasValue();
    180 }
    181 
    182 Node* CodeAssembler::Parameter(int value) {
    183   return raw_assembler_->Parameter(value);
    184 }
    185 
    186 void CodeAssembler::Return(Node* value) {
    187   return raw_assembler_->Return(value);
    188 }
    189 
    190 void CodeAssembler::PopAndReturn(Node* pop, Node* value) {
    191   return raw_assembler_->PopAndReturn(pop, value);
    192 }
    193 
    194 void CodeAssembler::DebugBreak() { raw_assembler_->DebugBreak(); }
    195 
    196 void CodeAssembler::Comment(const char* format, ...) {
    197   if (!FLAG_code_comments) return;
    198   char buffer[4 * KB];
    199   StringBuilder builder(buffer, arraysize(buffer));
    200   va_list arguments;
    201   va_start(arguments, format);
    202   builder.AddFormattedList(format, arguments);
    203   va_end(arguments);
    204 
    205   // Copy the string before recording it in the assembler to avoid
    206   // issues when the stack allocated buffer goes out of scope.
    207   const int prefix_len = 2;
    208   int length = builder.position() + 1;
    209   char* copy = reinterpret_cast<char*>(malloc(length + prefix_len));
    210   MemCopy(copy + prefix_len, builder.Finalize(), length);
    211   copy[0] = ';';
    212   copy[1] = ' ';
    213   raw_assembler_->Comment(copy);
    214 }
    215 
    216 void CodeAssembler::Bind(CodeAssembler::Label* label) { return label->Bind(); }
    217 
    218 Node* CodeAssembler::LoadFramePointer() {
    219   return raw_assembler_->LoadFramePointer();
    220 }
    221 
    222 Node* CodeAssembler::LoadParentFramePointer() {
    223   return raw_assembler_->LoadParentFramePointer();
    224 }
    225 
    226 Node* CodeAssembler::LoadStackPointer() {
    227   return raw_assembler_->LoadStackPointer();
    228 }
    229 
    230 #define DEFINE_CODE_ASSEMBLER_BINARY_OP(name)   \
    231   Node* CodeAssembler::name(Node* a, Node* b) { \
    232     return raw_assembler_->name(a, b);          \
    233   }
    234 CODE_ASSEMBLER_BINARY_OP_LIST(DEFINE_CODE_ASSEMBLER_BINARY_OP)
    235 #undef DEFINE_CODE_ASSEMBLER_BINARY_OP
    236 
    237 Node* CodeAssembler::WordShl(Node* value, int shift) {
    238   return (shift != 0) ? raw_assembler_->WordShl(value, IntPtrConstant(shift))
    239                       : value;
    240 }
    241 
    242 Node* CodeAssembler::WordShr(Node* value, int shift) {
    243   return (shift != 0) ? raw_assembler_->WordShr(value, IntPtrConstant(shift))
    244                       : value;
    245 }
    246 
    247 Node* CodeAssembler::Word32Shr(Node* value, int shift) {
    248   return (shift != 0) ? raw_assembler_->Word32Shr(value, Int32Constant(shift))
    249                       : value;
    250 }
    251 
    252 Node* CodeAssembler::ChangeUint32ToWord(Node* value) {
    253   if (raw_assembler_->machine()->Is64()) {
    254     value = raw_assembler_->ChangeUint32ToUint64(value);
    255   }
    256   return value;
    257 }
    258 
    259 Node* CodeAssembler::ChangeInt32ToIntPtr(Node* value) {
    260   if (raw_assembler_->machine()->Is64()) {
    261     value = raw_assembler_->ChangeInt32ToInt64(value);
    262   }
    263   return value;
    264 }
    265 
    266 Node* CodeAssembler::RoundIntPtrToFloat64(Node* value) {
    267   if (raw_assembler_->machine()->Is64()) {
    268     return raw_assembler_->RoundInt64ToFloat64(value);
    269   }
    270   return raw_assembler_->ChangeInt32ToFloat64(value);
    271 }
    272 
    273 #define DEFINE_CODE_ASSEMBLER_UNARY_OP(name) \
    274   Node* CodeAssembler::name(Node* a) { return raw_assembler_->name(a); }
    275 CODE_ASSEMBLER_UNARY_OP_LIST(DEFINE_CODE_ASSEMBLER_UNARY_OP)
    276 #undef DEFINE_CODE_ASSEMBLER_UNARY_OP
    277 
    278 Node* CodeAssembler::Load(MachineType rep, Node* base) {
    279   return raw_assembler_->Load(rep, base);
    280 }
    281 
    282 Node* CodeAssembler::Load(MachineType rep, Node* base, Node* index) {
    283   return raw_assembler_->Load(rep, base, index);
    284 }
    285 
    286 Node* CodeAssembler::AtomicLoad(MachineType rep, Node* base, Node* index) {
    287   return raw_assembler_->AtomicLoad(rep, base, index);
    288 }
    289 
    290 Node* CodeAssembler::LoadRoot(Heap::RootListIndex root_index) {
    291   if (isolate()->heap()->RootCanBeTreatedAsConstant(root_index)) {
    292     Handle<Object> root = isolate()->heap()->root_handle(root_index);
    293     if (root->IsSmi()) {
    294       return SmiConstant(Smi::cast(*root));
    295     } else {
    296       return HeapConstant(Handle<HeapObject>::cast(root));
    297     }
    298   }
    299 
    300   Node* roots_array_start =
    301       ExternalConstant(ExternalReference::roots_array_start(isolate()));
    302   return Load(MachineType::AnyTagged(), roots_array_start,
    303               IntPtrConstant(root_index * kPointerSize));
    304 }
    305 
    306 Node* CodeAssembler::Store(MachineRepresentation rep, Node* base, Node* value) {
    307   return raw_assembler_->Store(rep, base, value, kFullWriteBarrier);
    308 }
    309 
    310 Node* CodeAssembler::Store(MachineRepresentation rep, Node* base, Node* index,
    311                            Node* value) {
    312   return raw_assembler_->Store(rep, base, index, value, kFullWriteBarrier);
    313 }
    314 
    315 Node* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base,
    316                                          Node* value) {
    317   return raw_assembler_->Store(rep, base, value, kNoWriteBarrier);
    318 }
    319 
    320 Node* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base,
    321                                          Node* index, Node* value) {
    322   return raw_assembler_->Store(rep, base, index, value, kNoWriteBarrier);
    323 }
    324 
    325 Node* CodeAssembler::AtomicStore(MachineRepresentation rep, Node* base,
    326                                  Node* index, Node* value) {
    327   return raw_assembler_->AtomicStore(rep, base, index, value);
    328 }
    329 
    330 Node* CodeAssembler::StoreRoot(Heap::RootListIndex root_index, Node* value) {
    331   DCHECK(Heap::RootCanBeWrittenAfterInitialization(root_index));
    332   Node* roots_array_start =
    333       ExternalConstant(ExternalReference::roots_array_start(isolate()));
    334   return StoreNoWriteBarrier(MachineRepresentation::kTagged, roots_array_start,
    335                              IntPtrConstant(root_index * kPointerSize), value);
    336 }
    337 
    338 Node* CodeAssembler::Retain(Node* value) {
    339   return raw_assembler_->Retain(value);
    340 }
    341 
    342 Node* CodeAssembler::Projection(int index, Node* value) {
    343   return raw_assembler_->Projection(index, value);
    344 }
    345 
    346 void CodeAssembler::GotoIfException(Node* node, Label* if_exception,
    347                                     Variable* exception_var) {
    348   Label success(this), exception(this, Label::kDeferred);
    349   success.MergeVariables();
    350   exception.MergeVariables();
    351   DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
    352 
    353   raw_assembler_->Continuations(node, success.label_, exception.label_);
    354 
    355   Bind(&exception);
    356   const Operator* op = raw_assembler_->common()->IfException();
    357   Node* exception_value = raw_assembler_->AddNode(op, node, node);
    358   if (exception_var != nullptr) {
    359     exception_var->Bind(exception_value);
    360   }
    361   Goto(if_exception);
    362 
    363   Bind(&success);
    364 }
    365 
    366 Node* CodeAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
    367                            Node** args) {
    368   CallPrologue();
    369   Node* return_value = raw_assembler_->CallN(descriptor, code_target, args);
    370   CallEpilogue();
    371   return return_value;
    372 }
    373 
    374 Node* CodeAssembler::TailCallN(CallDescriptor* descriptor, Node* code_target,
    375                                Node** args) {
    376   return raw_assembler_->TailCallN(descriptor, code_target, args);
    377 }
    378 
    379 Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id,
    380                                  Node* context) {
    381   CallPrologue();
    382   Node* return_value = raw_assembler_->CallRuntime0(function_id, context);
    383   CallEpilogue();
    384   return return_value;
    385 }
    386 
    387 Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
    388                                  Node* arg1) {
    389   CallPrologue();
    390   Node* return_value = raw_assembler_->CallRuntime1(function_id, arg1, context);
    391   CallEpilogue();
    392   return return_value;
    393 }
    394 
    395 Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
    396                                  Node* arg1, Node* arg2) {
    397   CallPrologue();
    398   Node* return_value =
    399       raw_assembler_->CallRuntime2(function_id, arg1, arg2, context);
    400   CallEpilogue();
    401   return return_value;
    402 }
    403 
    404 Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
    405                                  Node* arg1, Node* arg2, Node* arg3) {
    406   CallPrologue();
    407   Node* return_value =
    408       raw_assembler_->CallRuntime3(function_id, arg1, arg2, arg3, context);
    409   CallEpilogue();
    410   return return_value;
    411 }
    412 
    413 Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
    414                                  Node* arg1, Node* arg2, Node* arg3,
    415                                  Node* arg4) {
    416   CallPrologue();
    417   Node* return_value = raw_assembler_->CallRuntime4(function_id, arg1, arg2,
    418                                                     arg3, arg4, context);
    419   CallEpilogue();
    420   return return_value;
    421 }
    422 
    423 Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
    424                                  Node* arg1, Node* arg2, Node* arg3, Node* arg4,
    425                                  Node* arg5) {
    426   CallPrologue();
    427   Node* return_value = raw_assembler_->CallRuntime5(function_id, arg1, arg2,
    428                                                     arg3, arg4, arg5, context);
    429   CallEpilogue();
    430   return return_value;
    431 }
    432 
    433 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
    434                                      Node* context) {
    435   return raw_assembler_->TailCallRuntime0(function_id, context);
    436 }
    437 
    438 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
    439                                      Node* context, Node* arg1) {
    440   return raw_assembler_->TailCallRuntime1(function_id, arg1, context);
    441 }
    442 
    443 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
    444                                      Node* context, Node* arg1, Node* arg2) {
    445   return raw_assembler_->TailCallRuntime2(function_id, arg1, arg2, context);
    446 }
    447 
    448 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
    449                                      Node* context, Node* arg1, Node* arg2,
    450                                      Node* arg3) {
    451   return raw_assembler_->TailCallRuntime3(function_id, arg1, arg2, arg3,
    452                                           context);
    453 }
    454 
    455 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
    456                                      Node* context, Node* arg1, Node* arg2,
    457                                      Node* arg3, Node* arg4) {
    458   return raw_assembler_->TailCallRuntime4(function_id, arg1, arg2, arg3, arg4,
    459                                           context);
    460 }
    461 
    462 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
    463                                      Node* context, Node* arg1, Node* arg2,
    464                                      Node* arg3, Node* arg4, Node* arg5) {
    465   return raw_assembler_->TailCallRuntime5(function_id, arg1, arg2, arg3, arg4,
    466                                           arg5, context);
    467 }
    468 
    469 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
    470                                      Node* context, Node* arg1, Node* arg2,
    471                                      Node* arg3, Node* arg4, Node* arg5,
    472                                      Node* arg6) {
    473   return raw_assembler_->TailCallRuntime6(function_id, arg1, arg2, arg3, arg4,
    474                                           arg5, arg6, context);
    475 }
    476 
    477 Node* CodeAssembler::CallStub(Callable const& callable, Node* context,
    478                               Node* arg1, size_t result_size) {
    479   Node* target = HeapConstant(callable.code());
    480   return CallStub(callable.descriptor(), target, context, arg1, result_size);
    481 }
    482 
    483 Node* CodeAssembler::CallStub(Callable const& callable, Node* context,
    484                               Node* arg1, Node* arg2, size_t result_size) {
    485   Node* target = HeapConstant(callable.code());
    486   return CallStub(callable.descriptor(), target, context, arg1, arg2,
    487                   result_size);
    488 }
    489 
    490 Node* CodeAssembler::CallStub(Callable const& callable, Node* context,
    491                               Node* arg1, Node* arg2, Node* arg3,
    492                               size_t result_size) {
    493   Node* target = HeapConstant(callable.code());
    494   return CallStub(callable.descriptor(), target, context, arg1, arg2, arg3,
    495                   result_size);
    496 }
    497 
    498 Node* CodeAssembler::CallStub(Callable const& callable, Node* context,
    499                               Node* arg1, Node* arg2, Node* arg3, Node* arg4,
    500                               size_t result_size) {
    501   Node* target = HeapConstant(callable.code());
    502   return CallStub(callable.descriptor(), target, context, arg1, arg2, arg3,
    503                   arg4, result_size);
    504 }
    505 
    506 Node* CodeAssembler::CallStubN(Callable const& callable, Node** args,
    507                                size_t result_size) {
    508   Node* target = HeapConstant(callable.code());
    509   return CallStubN(callable.descriptor(), target, args, result_size);
    510 }
    511 
    512 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
    513                               Node* target, Node* context, size_t result_size) {
    514   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    515       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    516       CallDescriptor::kNoFlags, Operator::kNoProperties,
    517       MachineType::AnyTagged(), result_size);
    518 
    519   Node** args = zone()->NewArray<Node*>(1);
    520   args[0] = context;
    521 
    522   return CallN(call_descriptor, target, args);
    523 }
    524 
    525 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
    526                               Node* target, Node* context, Node* arg1,
    527                               size_t result_size) {
    528   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    529       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    530       CallDescriptor::kNoFlags, Operator::kNoProperties,
    531       MachineType::AnyTagged(), result_size);
    532 
    533   Node** args = zone()->NewArray<Node*>(2);
    534   args[0] = arg1;
    535   args[1] = context;
    536 
    537   return CallN(call_descriptor, target, args);
    538 }
    539 
    540 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
    541                               Node* target, Node* context, Node* arg1,
    542                               Node* arg2, size_t result_size) {
    543   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    544       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    545       CallDescriptor::kNoFlags, Operator::kNoProperties,
    546       MachineType::AnyTagged(), result_size);
    547 
    548   Node** args = zone()->NewArray<Node*>(3);
    549   args[0] = arg1;
    550   args[1] = arg2;
    551   args[2] = context;
    552 
    553   return CallN(call_descriptor, target, args);
    554 }
    555 
    556 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
    557                               Node* target, Node* context, Node* arg1,
    558                               Node* arg2, Node* arg3, size_t result_size) {
    559   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    560       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    561       CallDescriptor::kNoFlags, Operator::kNoProperties,
    562       MachineType::AnyTagged(), result_size);
    563 
    564   Node** args = zone()->NewArray<Node*>(4);
    565   args[0] = arg1;
    566   args[1] = arg2;
    567   args[2] = arg3;
    568   args[3] = context;
    569 
    570   return CallN(call_descriptor, target, args);
    571 }
    572 
    573 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
    574                               Node* target, Node* context, Node* arg1,
    575                               Node* arg2, Node* arg3, Node* arg4,
    576                               size_t result_size) {
    577   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    578       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    579       CallDescriptor::kNoFlags, Operator::kNoProperties,
    580       MachineType::AnyTagged(), result_size);
    581 
    582   Node** args = zone()->NewArray<Node*>(5);
    583   args[0] = arg1;
    584   args[1] = arg2;
    585   args[2] = arg3;
    586   args[3] = arg4;
    587   args[4] = context;
    588 
    589   return CallN(call_descriptor, target, args);
    590 }
    591 
    592 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
    593                               Node* target, Node* context, Node* arg1,
    594                               Node* arg2, Node* arg3, Node* arg4, Node* arg5,
    595                               size_t result_size) {
    596   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    597       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    598       CallDescriptor::kNoFlags, Operator::kNoProperties,
    599       MachineType::AnyTagged(), result_size);
    600 
    601   Node** args = zone()->NewArray<Node*>(6);
    602   args[0] = arg1;
    603   args[1] = arg2;
    604   args[2] = arg3;
    605   args[3] = arg4;
    606   args[4] = arg5;
    607   args[5] = context;
    608 
    609   return CallN(call_descriptor, target, args);
    610 }
    611 
    612 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
    613                               Node* target, Node* context, const Arg& arg1,
    614                               const Arg& arg2, size_t result_size) {
    615   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    616       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    617       CallDescriptor::kNoFlags, Operator::kNoProperties,
    618       MachineType::AnyTagged(), result_size);
    619 
    620   const int kArgsCount = 3;
    621   Node** args = zone()->NewArray<Node*>(kArgsCount);
    622   DCHECK((std::fill(&args[0], &args[kArgsCount], nullptr), true));
    623   args[arg1.index] = arg1.value;
    624   args[arg2.index] = arg2.value;
    625   args[kArgsCount - 1] = context;
    626   DCHECK_EQ(0, std::count(&args[0], &args[kArgsCount], nullptr));
    627 
    628   return CallN(call_descriptor, target, args);
    629 }
    630 
    631 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
    632                               Node* target, Node* context, const Arg& arg1,
    633                               const Arg& arg2, const Arg& arg3,
    634                               size_t result_size) {
    635   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    636       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    637       CallDescriptor::kNoFlags, Operator::kNoProperties,
    638       MachineType::AnyTagged(), result_size);
    639 
    640   const int kArgsCount = 4;
    641   Node** args = zone()->NewArray<Node*>(kArgsCount);
    642   DCHECK((std::fill(&args[0], &args[kArgsCount], nullptr), true));
    643   args[arg1.index] = arg1.value;
    644   args[arg2.index] = arg2.value;
    645   args[arg3.index] = arg3.value;
    646   args[kArgsCount - 1] = context;
    647   DCHECK_EQ(0, std::count(&args[0], &args[kArgsCount], nullptr));
    648 
    649   return CallN(call_descriptor, target, args);
    650 }
    651 
    652 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
    653                               Node* target, Node* context, const Arg& arg1,
    654                               const Arg& arg2, const Arg& arg3, const Arg& arg4,
    655                               size_t result_size) {
    656   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    657       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    658       CallDescriptor::kNoFlags, Operator::kNoProperties,
    659       MachineType::AnyTagged(), result_size);
    660 
    661   const int kArgsCount = 5;
    662   Node** args = zone()->NewArray<Node*>(kArgsCount);
    663   DCHECK((std::fill(&args[0], &args[kArgsCount], nullptr), true));
    664   args[arg1.index] = arg1.value;
    665   args[arg2.index] = arg2.value;
    666   args[arg3.index] = arg3.value;
    667   args[arg4.index] = arg4.value;
    668   args[kArgsCount - 1] = context;
    669   DCHECK_EQ(0, std::count(&args[0], &args[kArgsCount], nullptr));
    670 
    671   return CallN(call_descriptor, target, args);
    672 }
    673 
    674 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
    675                               Node* target, Node* context, const Arg& arg1,
    676                               const Arg& arg2, const Arg& arg3, const Arg& arg4,
    677                               const Arg& arg5, size_t result_size) {
    678   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    679       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    680       CallDescriptor::kNoFlags, Operator::kNoProperties,
    681       MachineType::AnyTagged(), result_size);
    682 
    683   const int kArgsCount = 6;
    684   Node** args = zone()->NewArray<Node*>(kArgsCount);
    685   DCHECK((std::fill(&args[0], &args[kArgsCount], nullptr), true));
    686   args[arg1.index] = arg1.value;
    687   args[arg2.index] = arg2.value;
    688   args[arg3.index] = arg3.value;
    689   args[arg4.index] = arg4.value;
    690   args[arg5.index] = arg5.value;
    691   args[kArgsCount - 1] = context;
    692   DCHECK_EQ(0, std::count(&args[0], &args[kArgsCount], nullptr));
    693 
    694   return CallN(call_descriptor, target, args);
    695 }
    696 
    697 Node* CodeAssembler::CallStubN(const CallInterfaceDescriptor& descriptor,
    698                                int js_parameter_count, Node* target,
    699                                Node** args, size_t result_size) {
    700   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    701       isolate(), zone(), descriptor,
    702       descriptor.GetStackParameterCount() + js_parameter_count,
    703       CallDescriptor::kNoFlags, Operator::kNoProperties,
    704       MachineType::AnyTagged(), result_size);
    705 
    706   return CallN(call_descriptor, target, args);
    707 }
    708 
    709 Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
    710                                   Node* arg1, size_t result_size) {
    711   Node* target = HeapConstant(callable.code());
    712   return TailCallStub(callable.descriptor(), target, context, arg1,
    713                       result_size);
    714 }
    715 
    716 Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
    717                                   Node* arg1, Node* arg2, size_t result_size) {
    718   Node* target = HeapConstant(callable.code());
    719   return TailCallStub(callable.descriptor(), target, context, arg1, arg2,
    720                       result_size);
    721 }
    722 
    723 Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
    724                                   Node* arg1, Node* arg2, Node* arg3,
    725                                   size_t result_size) {
    726   Node* target = HeapConstant(callable.code());
    727   return TailCallStub(callable.descriptor(), target, context, arg1, arg2, arg3,
    728                       result_size);
    729 }
    730 
    731 Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
    732                                   Node* arg1, Node* arg2, Node* arg3,
    733                                   Node* arg4, size_t result_size) {
    734   Node* target = HeapConstant(callable.code());
    735   return TailCallStub(callable.descriptor(), target, context, arg1, arg2, arg3,
    736                       arg4, result_size);
    737 }
    738 
    739 Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
    740                                   Node* arg1, Node* arg2, Node* arg3,
    741                                   Node* arg4, Node* arg5, size_t result_size) {
    742   Node* target = HeapConstant(callable.code());
    743   return TailCallStub(callable.descriptor(), target, context, arg1, arg2, arg3,
    744                       arg4, arg5, result_size);
    745 }
    746 
    747 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
    748                                   Node* target, Node* context, Node* arg1,
    749                                   size_t result_size) {
    750   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    751       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    752       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
    753       MachineType::AnyTagged(), result_size);
    754 
    755   Node** args = zone()->NewArray<Node*>(2);
    756   args[0] = arg1;
    757   args[1] = context;
    758 
    759   return raw_assembler_->TailCallN(call_descriptor, target, args);
    760 }
    761 
    762 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
    763                                   Node* target, Node* context, Node* arg1,
    764                                   Node* arg2, size_t result_size) {
    765   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    766       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    767       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
    768       MachineType::AnyTagged(), result_size);
    769 
    770   Node** args = zone()->NewArray<Node*>(3);
    771   args[0] = arg1;
    772   args[1] = arg2;
    773   args[2] = context;
    774 
    775   return raw_assembler_->TailCallN(call_descriptor, target, args);
    776 }
    777 
    778 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
    779                                   Node* target, Node* context, Node* arg1,
    780                                   Node* arg2, Node* arg3, size_t result_size) {
    781   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    782       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    783       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
    784       MachineType::AnyTagged(), result_size);
    785 
    786   Node** args = zone()->NewArray<Node*>(4);
    787   args[0] = arg1;
    788   args[1] = arg2;
    789   args[2] = arg3;
    790   args[3] = context;
    791 
    792   return raw_assembler_->TailCallN(call_descriptor, target, args);
    793 }
    794 
    795 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
    796                                   Node* target, Node* context, Node* arg1,
    797                                   Node* arg2, Node* arg3, Node* arg4,
    798                                   size_t result_size) {
    799   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    800       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    801       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
    802       MachineType::AnyTagged(), result_size);
    803 
    804   Node** args = zone()->NewArray<Node*>(5);
    805   args[0] = arg1;
    806   args[1] = arg2;
    807   args[2] = arg3;
    808   args[3] = arg4;
    809   args[4] = context;
    810 
    811   return raw_assembler_->TailCallN(call_descriptor, target, args);
    812 }
    813 
    814 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
    815                                   Node* target, Node* context, Node* arg1,
    816                                   Node* arg2, Node* arg3, Node* arg4,
    817                                   Node* arg5, size_t result_size) {
    818   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    819       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    820       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
    821       MachineType::AnyTagged(), result_size);
    822 
    823   Node** args = zone()->NewArray<Node*>(6);
    824   args[0] = arg1;
    825   args[1] = arg2;
    826   args[2] = arg3;
    827   args[3] = arg4;
    828   args[4] = arg5;
    829   args[5] = context;
    830 
    831   return raw_assembler_->TailCallN(call_descriptor, target, args);
    832 }
    833 
    834 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
    835                                   Node* target, Node* context, Node* arg1,
    836                                   Node* arg2, Node* arg3, Node* arg4,
    837                                   Node* arg5, Node* arg6, size_t result_size) {
    838   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    839       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    840       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
    841       MachineType::AnyTagged(), result_size);
    842 
    843   Node** args = zone()->NewArray<Node*>(7);
    844   args[0] = arg1;
    845   args[1] = arg2;
    846   args[2] = arg3;
    847   args[3] = arg4;
    848   args[4] = arg5;
    849   args[5] = arg6;
    850   args[6] = context;
    851 
    852   return raw_assembler_->TailCallN(call_descriptor, target, args);
    853 }
    854 
    855 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
    856                                   Node* target, Node* context, const Arg& arg1,
    857                                   const Arg& arg2, const Arg& arg3,
    858                                   const Arg& arg4, size_t result_size) {
    859   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    860       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    861       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
    862       MachineType::AnyTagged(), result_size);
    863 
    864   const int kArgsCount = 5;
    865   Node** args = zone()->NewArray<Node*>(kArgsCount);
    866   DCHECK((std::fill(&args[0], &args[kArgsCount], nullptr), true));
    867   args[arg1.index] = arg1.value;
    868   args[arg2.index] = arg2.value;
    869   args[arg3.index] = arg3.value;
    870   args[arg4.index] = arg4.value;
    871   args[kArgsCount - 1] = context;
    872   DCHECK_EQ(0, std::count(&args[0], &args[kArgsCount], nullptr));
    873 
    874   return raw_assembler_->TailCallN(call_descriptor, target, args);
    875 }
    876 
    877 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
    878                                   Node* target, Node* context, const Arg& arg1,
    879                                   const Arg& arg2, const Arg& arg3,
    880                                   const Arg& arg4, const Arg& arg5,
    881                                   size_t result_size) {
    882   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    883       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    884       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
    885       MachineType::AnyTagged(), result_size);
    886 
    887   const int kArgsCount = 6;
    888   Node** args = zone()->NewArray<Node*>(kArgsCount);
    889   DCHECK((std::fill(&args[0], &args[kArgsCount], nullptr), true));
    890   args[arg1.index] = arg1.value;
    891   args[arg2.index] = arg2.value;
    892   args[arg3.index] = arg3.value;
    893   args[arg4.index] = arg4.value;
    894   args[arg5.index] = arg5.value;
    895   args[kArgsCount - 1] = context;
    896   DCHECK_EQ(0, std::count(&args[0], &args[kArgsCount], nullptr));
    897 
    898   return raw_assembler_->TailCallN(call_descriptor, target, args);
    899 }
    900 
    901 Node* CodeAssembler::TailCallBytecodeDispatch(
    902     const CallInterfaceDescriptor& interface_descriptor,
    903     Node* code_target_address, Node** args) {
    904   CallDescriptor* descriptor = Linkage::GetBytecodeDispatchCallDescriptor(
    905       isolate(), zone(), interface_descriptor,
    906       interface_descriptor.GetStackParameterCount());
    907   return raw_assembler_->TailCallN(descriptor, code_target_address, args);
    908 }
    909 
    910 Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
    911                             Node* function, Node* receiver,
    912                             size_t result_size) {
    913   const int argc = 0;
    914   Node* target = HeapConstant(callable.code());
    915 
    916   Node** args = zone()->NewArray<Node*>(argc + 4);
    917   args[0] = function;
    918   args[1] = Int32Constant(argc);
    919   args[2] = receiver;
    920   args[3] = context;
    921 
    922   return CallStubN(callable.descriptor(), argc + 1, target, args, result_size);
    923 }
    924 
    925 Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
    926                             Node* function, Node* receiver, Node* arg1,
    927                             size_t result_size) {
    928   const int argc = 1;
    929   Node* target = HeapConstant(callable.code());
    930 
    931   Node** args = zone()->NewArray<Node*>(argc + 4);
    932   args[0] = function;
    933   args[1] = Int32Constant(argc);
    934   args[2] = receiver;
    935   args[3] = arg1;
    936   args[4] = context;
    937 
    938   return CallStubN(callable.descriptor(), argc + 1, target, args, result_size);
    939 }
    940 
    941 Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
    942                             Node* function, Node* receiver, Node* arg1,
    943                             Node* arg2, size_t result_size) {
    944   const int argc = 2;
    945   Node* target = HeapConstant(callable.code());
    946 
    947   Node** args = zone()->NewArray<Node*>(argc + 4);
    948   args[0] = function;
    949   args[1] = Int32Constant(argc);
    950   args[2] = receiver;
    951   args[3] = arg1;
    952   args[4] = arg2;
    953   args[5] = context;
    954 
    955   return CallStubN(callable.descriptor(), argc + 1, target, args, result_size);
    956 }
    957 
    958 Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
    959                             Node* function, Node* receiver, Node* arg1,
    960                             Node* arg2, Node* arg3, size_t result_size) {
    961   const int argc = 3;
    962   Node* target = HeapConstant(callable.code());
    963 
    964   Node** args = zone()->NewArray<Node*>(argc + 4);
    965   args[0] = function;
    966   args[1] = Int32Constant(argc);
    967   args[2] = receiver;
    968   args[3] = arg1;
    969   args[4] = arg2;
    970   args[5] = arg3;
    971   args[6] = context;
    972 
    973   return CallStubN(callable.descriptor(), argc + 1, target, args, result_size);
    974 }
    975 
    976 Node* CodeAssembler::CallCFunction2(MachineType return_type,
    977                                     MachineType arg0_type,
    978                                     MachineType arg1_type, Node* function,
    979                                     Node* arg0, Node* arg1) {
    980   return raw_assembler_->CallCFunction2(return_type, arg0_type, arg1_type,
    981                                         function, arg0, arg1);
    982 }
    983 
    984 void CodeAssembler::Goto(CodeAssembler::Label* label) {
    985   label->MergeVariables();
    986   raw_assembler_->Goto(label->label_);
    987 }
    988 
    989 void CodeAssembler::GotoIf(Node* condition, Label* true_label) {
    990   Label false_label(this);
    991   Branch(condition, true_label, &false_label);
    992   Bind(&false_label);
    993 }
    994 
    995 void CodeAssembler::GotoUnless(Node* condition, Label* false_label) {
    996   Label true_label(this);
    997   Branch(condition, &true_label, false_label);
    998   Bind(&true_label);
    999 }
   1000 
   1001 void CodeAssembler::Branch(Node* condition, CodeAssembler::Label* true_label,
   1002                            CodeAssembler::Label* false_label) {
   1003   true_label->MergeVariables();
   1004   false_label->MergeVariables();
   1005   return raw_assembler_->Branch(condition, true_label->label_,
   1006                                 false_label->label_);
   1007 }
   1008 
   1009 void CodeAssembler::Switch(Node* index, Label* default_label,
   1010                            const int32_t* case_values, Label** case_labels,
   1011                            size_t case_count) {
   1012   RawMachineLabel** labels =
   1013       new (zone()->New(sizeof(RawMachineLabel*) * case_count))
   1014           RawMachineLabel*[case_count];
   1015   for (size_t i = 0; i < case_count; ++i) {
   1016     labels[i] = case_labels[i]->label_;
   1017     case_labels[i]->MergeVariables();
   1018     default_label->MergeVariables();
   1019   }
   1020   return raw_assembler_->Switch(index, default_label->label_, case_values,
   1021                                 labels, case_count);
   1022 }
   1023 
   1024 Node* CodeAssembler::Select(Node* condition, Node* true_value,
   1025                             Node* false_value, MachineRepresentation rep) {
   1026   Variable value(this, rep);
   1027   Label vtrue(this), vfalse(this), end(this);
   1028   Branch(condition, &vtrue, &vfalse);
   1029 
   1030   Bind(&vtrue);
   1031   {
   1032     value.Bind(true_value);
   1033     Goto(&end);
   1034   }
   1035   Bind(&vfalse);
   1036   {
   1037     value.Bind(false_value);
   1038     Goto(&end);
   1039   }
   1040 
   1041   Bind(&end);
   1042   return value.value();
   1043 }
   1044 
   1045 // RawMachineAssembler delegate helpers:
   1046 Isolate* CodeAssembler::isolate() const { return raw_assembler_->isolate(); }
   1047 
   1048 Factory* CodeAssembler::factory() const { return isolate()->factory(); }
   1049 
   1050 Zone* CodeAssembler::zone() const { return raw_assembler_->zone(); }
   1051 
   1052 // The core implementation of Variable is stored through an indirection so
   1053 // that it can outlive the often block-scoped Variable declarations. This is
   1054 // needed to ensure that variable binding and merging through phis can
   1055 // properly be verified.
   1056 class CodeAssembler::Variable::Impl : public ZoneObject {
   1057  public:
   1058   explicit Impl(MachineRepresentation rep) : value_(nullptr), rep_(rep) {}
   1059   Node* value_;
   1060   MachineRepresentation rep_;
   1061 };
   1062 
   1063 CodeAssembler::Variable::Variable(CodeAssembler* assembler,
   1064                                   MachineRepresentation rep)
   1065     : impl_(new (assembler->zone()) Impl(rep)), assembler_(assembler) {
   1066   assembler->variables_.insert(impl_);
   1067 }
   1068 
   1069 CodeAssembler::Variable::~Variable() { assembler_->variables_.erase(impl_); }
   1070 
   1071 void CodeAssembler::Variable::Bind(Node* value) { impl_->value_ = value; }
   1072 
   1073 Node* CodeAssembler::Variable::value() const {
   1074   DCHECK_NOT_NULL(impl_->value_);
   1075   return impl_->value_;
   1076 }
   1077 
   1078 MachineRepresentation CodeAssembler::Variable::rep() const {
   1079   return impl_->rep_;
   1080 }
   1081 
   1082 bool CodeAssembler::Variable::IsBound() const {
   1083   return impl_->value_ != nullptr;
   1084 }
   1085 
   1086 CodeAssembler::Label::Label(CodeAssembler* assembler, size_t vars_count,
   1087                             Variable** vars, CodeAssembler::Label::Type type)
   1088     : bound_(false), merge_count_(0), assembler_(assembler), label_(nullptr) {
   1089   void* buffer = assembler->zone()->New(sizeof(RawMachineLabel));
   1090   label_ = new (buffer)
   1091       RawMachineLabel(type == kDeferred ? RawMachineLabel::kDeferred
   1092                                         : RawMachineLabel::kNonDeferred);
   1093   for (size_t i = 0; i < vars_count; ++i) {
   1094     variable_phis_[vars[i]->impl_] = nullptr;
   1095   }
   1096 }
   1097 
   1098 void CodeAssembler::Label::MergeVariables() {
   1099   ++merge_count_;
   1100   for (auto var : assembler_->variables_) {
   1101     size_t count = 0;
   1102     Node* node = var->value_;
   1103     if (node != nullptr) {
   1104       auto i = variable_merges_.find(var);
   1105       if (i != variable_merges_.end()) {
   1106         i->second.push_back(node);
   1107         count = i->second.size();
   1108       } else {
   1109         count = 1;
   1110         variable_merges_[var] = std::vector<Node*>(1, node);
   1111       }
   1112     }
   1113     // If the following asserts, then you've jumped to a label without a bound
   1114     // variable along that path that expects to merge its value into a phi.
   1115     DCHECK(variable_phis_.find(var) == variable_phis_.end() ||
   1116            count == merge_count_);
   1117     USE(count);
   1118 
   1119     // If the label is already bound, we already know the set of variables to
   1120     // merge and phi nodes have already been created.
   1121     if (bound_) {
   1122       auto phi = variable_phis_.find(var);
   1123       if (phi != variable_phis_.end()) {
   1124         DCHECK_NOT_NULL(phi->second);
   1125         assembler_->raw_assembler_->AppendPhiInput(phi->second, node);
   1126       } else {
   1127         auto i = variable_merges_.find(var);
   1128         if (i != variable_merges_.end()) {
   1129           // If the following assert fires, then you've declared a variable that
   1130           // has the same bound value along all paths up until the point you
   1131           // bound this label, but then later merged a path with a new value for
   1132           // the variable after the label bind (it's not possible to add phis to
   1133           // the bound label after the fact, just make sure to list the variable
   1134           // in the label's constructor's list of merged variables).
   1135           DCHECK(find_if(i->second.begin(), i->second.end(),
   1136                          [node](Node* e) -> bool { return node != e; }) ==
   1137                  i->second.end());
   1138         }
   1139       }
   1140     }
   1141   }
   1142 }
   1143 
   1144 void CodeAssembler::Label::Bind() {
   1145   DCHECK(!bound_);
   1146   assembler_->raw_assembler_->Bind(label_);
   1147 
   1148   // Make sure that all variables that have changed along any path up to this
   1149   // point are marked as merge variables.
   1150   for (auto var : assembler_->variables_) {
   1151     Node* shared_value = nullptr;
   1152     auto i = variable_merges_.find(var);
   1153     if (i != variable_merges_.end()) {
   1154       for (auto value : i->second) {
   1155         DCHECK(value != nullptr);
   1156         if (value != shared_value) {
   1157           if (shared_value == nullptr) {
   1158             shared_value = value;
   1159           } else {
   1160             variable_phis_[var] = nullptr;
   1161           }
   1162         }
   1163       }
   1164     }
   1165   }
   1166 
   1167   for (auto var : variable_phis_) {
   1168     CodeAssembler::Variable::Impl* var_impl = var.first;
   1169     auto i = variable_merges_.find(var_impl);
   1170     // If the following assert fires, then a variable that has been marked as
   1171     // being merged at the label--either by explicitly marking it so in the
   1172     // label constructor or by having seen different bound values at branches
   1173     // into the label--doesn't have a bound value along all of the paths that
   1174     // have been merged into the label up to this point.
   1175     DCHECK(i != variable_merges_.end() && i->second.size() == merge_count_);
   1176     Node* phi = assembler_->raw_assembler_->Phi(
   1177         var.first->rep_, static_cast<int>(merge_count_), &(i->second[0]));
   1178     variable_phis_[var_impl] = phi;
   1179   }
   1180 
   1181   // Bind all variables to a merge phi, the common value along all paths or
   1182   // null.
   1183   for (auto var : assembler_->variables_) {
   1184     auto i = variable_phis_.find(var);
   1185     if (i != variable_phis_.end()) {
   1186       var->value_ = i->second;
   1187     } else {
   1188       auto j = variable_merges_.find(var);
   1189       if (j != variable_merges_.end() && j->second.size() == merge_count_) {
   1190         var->value_ = j->second.back();
   1191       } else {
   1192         var->value_ = nullptr;
   1193       }
   1194     }
   1195   }
   1196 
   1197   bound_ = true;
   1198 }
   1199 
   1200 }  // namespace compiler
   1201 }  // namespace internal
   1202 }  // namespace v8
   1203