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.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(zone, false, parameter_count,
     45                                                  CallDescriptor::kNoFlags),
     46                     flags, name) {}
     47 
     48 CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone,
     49                              CallDescriptor* call_descriptor, Code::Flags flags,
     50                              const char* name)
     51     : raw_assembler_(new RawMachineAssembler(
     52           isolate, new (zone) Graph(zone), call_descriptor,
     53           MachineType::PointerRepresentation(),
     54           InstructionSelector::SupportedMachineOperatorFlags())),
     55       flags_(flags),
     56       name_(name),
     57       code_generated_(false),
     58       variables_(zone) {}
     59 
     60 CodeAssembler::~CodeAssembler() {}
     61 
     62 void CodeAssembler::CallPrologue() {}
     63 
     64 void CodeAssembler::CallEpilogue() {}
     65 
     66 Handle<Code> CodeAssembler::GenerateCode() {
     67   DCHECK(!code_generated_);
     68 
     69   Schedule* schedule = raw_assembler_->Export();
     70   Handle<Code> code = Pipeline::GenerateCodeForCodeStub(
     71       isolate(), raw_assembler_->call_descriptor(), graph(), schedule, flags_,
     72       name_);
     73 
     74   code_generated_ = true;
     75   return code;
     76 }
     77 
     78 bool CodeAssembler::Is64() const { return raw_assembler_->machine()->Is64(); }
     79 
     80 bool CodeAssembler::IsFloat64RoundUpSupported() const {
     81   return raw_assembler_->machine()->Float64RoundUp().IsSupported();
     82 }
     83 
     84 bool CodeAssembler::IsFloat64RoundDownSupported() const {
     85   return raw_assembler_->machine()->Float64RoundDown().IsSupported();
     86 }
     87 
     88 bool CodeAssembler::IsFloat64RoundTruncateSupported() const {
     89   return raw_assembler_->machine()->Float64RoundTruncate().IsSupported();
     90 }
     91 
     92 Node* CodeAssembler::Int32Constant(int32_t value) {
     93   return raw_assembler_->Int32Constant(value);
     94 }
     95 
     96 Node* CodeAssembler::Int64Constant(int64_t value) {
     97   return raw_assembler_->Int64Constant(value);
     98 }
     99 
    100 Node* CodeAssembler::IntPtrConstant(intptr_t value) {
    101   return raw_assembler_->IntPtrConstant(value);
    102 }
    103 
    104 Node* CodeAssembler::NumberConstant(double value) {
    105   return raw_assembler_->NumberConstant(value);
    106 }
    107 
    108 Node* CodeAssembler::SmiConstant(Smi* value) {
    109   return IntPtrConstant(bit_cast<intptr_t>(value));
    110 }
    111 
    112 Node* CodeAssembler::HeapConstant(Handle<HeapObject> object) {
    113   return raw_assembler_->HeapConstant(object);
    114 }
    115 
    116 Node* CodeAssembler::BooleanConstant(bool value) {
    117   return raw_assembler_->BooleanConstant(value);
    118 }
    119 
    120 Node* CodeAssembler::ExternalConstant(ExternalReference address) {
    121   return raw_assembler_->ExternalConstant(address);
    122 }
    123 
    124 Node* CodeAssembler::Float64Constant(double value) {
    125   return raw_assembler_->Float64Constant(value);
    126 }
    127 
    128 Node* CodeAssembler::NaNConstant() {
    129   return LoadRoot(Heap::kNanValueRootIndex);
    130 }
    131 
    132 bool CodeAssembler::ToInt32Constant(Node* node, int32_t& out_value) {
    133   Int64Matcher m(node);
    134   if (m.HasValue() &&
    135       m.IsInRange(std::numeric_limits<int32_t>::min(),
    136                   std::numeric_limits<int32_t>::max())) {
    137     out_value = static_cast<int32_t>(m.Value());
    138     return true;
    139   }
    140 
    141   return false;
    142 }
    143 
    144 bool CodeAssembler::ToInt64Constant(Node* node, int64_t& out_value) {
    145   Int64Matcher m(node);
    146   if (m.HasValue()) out_value = m.Value();
    147   return m.HasValue();
    148 }
    149 
    150 bool CodeAssembler::ToIntPtrConstant(Node* node, intptr_t& out_value) {
    151   IntPtrMatcher m(node);
    152   if (m.HasValue()) out_value = m.Value();
    153   return m.HasValue();
    154 }
    155 
    156 Node* CodeAssembler::Parameter(int value) {
    157   return raw_assembler_->Parameter(value);
    158 }
    159 
    160 void CodeAssembler::Return(Node* value) {
    161   return raw_assembler_->Return(value);
    162 }
    163 
    164 void CodeAssembler::DebugBreak() { raw_assembler_->DebugBreak(); }
    165 
    166 void CodeAssembler::Comment(const char* format, ...) {
    167   if (!FLAG_code_comments) return;
    168   char buffer[4 * KB];
    169   StringBuilder builder(buffer, arraysize(buffer));
    170   va_list arguments;
    171   va_start(arguments, format);
    172   builder.AddFormattedList(format, arguments);
    173   va_end(arguments);
    174 
    175   // Copy the string before recording it in the assembler to avoid
    176   // issues when the stack allocated buffer goes out of scope.
    177   const int prefix_len = 2;
    178   int length = builder.position() + 1;
    179   char* copy = reinterpret_cast<char*>(malloc(length + prefix_len));
    180   MemCopy(copy + prefix_len, builder.Finalize(), length);
    181   copy[0] = ';';
    182   copy[1] = ' ';
    183   raw_assembler_->Comment(copy);
    184 }
    185 
    186 void CodeAssembler::Bind(CodeAssembler::Label* label) { return label->Bind(); }
    187 
    188 Node* CodeAssembler::LoadFramePointer() {
    189   return raw_assembler_->LoadFramePointer();
    190 }
    191 
    192 Node* CodeAssembler::LoadParentFramePointer() {
    193   return raw_assembler_->LoadParentFramePointer();
    194 }
    195 
    196 Node* CodeAssembler::LoadStackPointer() {
    197   return raw_assembler_->LoadStackPointer();
    198 }
    199 
    200 Node* CodeAssembler::SmiShiftBitsConstant() {
    201   return IntPtrConstant(kSmiShiftSize + kSmiTagSize);
    202 }
    203 
    204 #define DEFINE_CODE_ASSEMBLER_BINARY_OP(name)   \
    205   Node* CodeAssembler::name(Node* a, Node* b) { \
    206     return raw_assembler_->name(a, b);          \
    207   }
    208 CODE_ASSEMBLER_BINARY_OP_LIST(DEFINE_CODE_ASSEMBLER_BINARY_OP)
    209 #undef DEFINE_CODE_ASSEMBLER_BINARY_OP
    210 
    211 Node* CodeAssembler::WordShl(Node* value, int shift) {
    212   return raw_assembler_->WordShl(value, IntPtrConstant(shift));
    213 }
    214 
    215 Node* CodeAssembler::WordShr(Node* value, int shift) {
    216   return raw_assembler_->WordShr(value, IntPtrConstant(shift));
    217 }
    218 
    219 Node* CodeAssembler::ChangeUint32ToWord(Node* value) {
    220   if (raw_assembler_->machine()->Is64()) {
    221     value = raw_assembler_->ChangeUint32ToUint64(value);
    222   }
    223   return value;
    224 }
    225 
    226 Node* CodeAssembler::ChangeInt32ToIntPtr(Node* value) {
    227   if (raw_assembler_->machine()->Is64()) {
    228     value = raw_assembler_->ChangeInt32ToInt64(value);
    229   }
    230   return value;
    231 }
    232 
    233 #define DEFINE_CODE_ASSEMBLER_UNARY_OP(name) \
    234   Node* CodeAssembler::name(Node* a) { return raw_assembler_->name(a); }
    235 CODE_ASSEMBLER_UNARY_OP_LIST(DEFINE_CODE_ASSEMBLER_UNARY_OP)
    236 #undef DEFINE_CODE_ASSEMBLER_UNARY_OP
    237 
    238 Node* CodeAssembler::Load(MachineType rep, Node* base) {
    239   return raw_assembler_->Load(rep, base);
    240 }
    241 
    242 Node* CodeAssembler::Load(MachineType rep, Node* base, Node* index) {
    243   return raw_assembler_->Load(rep, base, index);
    244 }
    245 
    246 Node* CodeAssembler::AtomicLoad(MachineType rep, Node* base, Node* index) {
    247   return raw_assembler_->AtomicLoad(rep, base, index);
    248 }
    249 
    250 Node* CodeAssembler::LoadRoot(Heap::RootListIndex root_index) {
    251   if (isolate()->heap()->RootCanBeTreatedAsConstant(root_index)) {
    252     Handle<Object> root = isolate()->heap()->root_handle(root_index);
    253     if (root->IsSmi()) {
    254       return SmiConstant(Smi::cast(*root));
    255     } else {
    256       return HeapConstant(Handle<HeapObject>::cast(root));
    257     }
    258   }
    259 
    260   Node* roots_array_start =
    261       ExternalConstant(ExternalReference::roots_array_start(isolate()));
    262   return Load(MachineType::AnyTagged(), roots_array_start,
    263               IntPtrConstant(root_index * kPointerSize));
    264 }
    265 
    266 Node* CodeAssembler::Store(MachineRepresentation rep, Node* base, Node* value) {
    267   return raw_assembler_->Store(rep, base, value, kFullWriteBarrier);
    268 }
    269 
    270 Node* CodeAssembler::Store(MachineRepresentation rep, Node* base, Node* index,
    271                            Node* value) {
    272   return raw_assembler_->Store(rep, base, index, value, kFullWriteBarrier);
    273 }
    274 
    275 Node* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base,
    276                                          Node* value) {
    277   return raw_assembler_->Store(rep, base, value, kNoWriteBarrier);
    278 }
    279 
    280 Node* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base,
    281                                          Node* index, Node* value) {
    282   return raw_assembler_->Store(rep, base, index, value, kNoWriteBarrier);
    283 }
    284 
    285 Node* CodeAssembler::AtomicStore(MachineRepresentation rep, Node* base,
    286                                  Node* index, Node* value) {
    287   return raw_assembler_->AtomicStore(rep, base, index, value);
    288 }
    289 
    290 Node* CodeAssembler::StoreRoot(Heap::RootListIndex root_index, Node* value) {
    291   DCHECK(Heap::RootCanBeWrittenAfterInitialization(root_index));
    292   Node* roots_array_start =
    293       ExternalConstant(ExternalReference::roots_array_start(isolate()));
    294   return StoreNoWriteBarrier(MachineRepresentation::kTagged, roots_array_start,
    295                              IntPtrConstant(root_index * kPointerSize), value);
    296 }
    297 
    298 Node* CodeAssembler::Projection(int index, Node* value) {
    299   return raw_assembler_->Projection(index, value);
    300 }
    301 
    302 void CodeAssembler::BranchIf(Node* condition, Label* if_true, Label* if_false) {
    303   Label if_condition_is_true(this), if_condition_is_false(this);
    304   Branch(condition, &if_condition_is_true, &if_condition_is_false);
    305   Bind(&if_condition_is_true);
    306   Goto(if_true);
    307   Bind(&if_condition_is_false);
    308   Goto(if_false);
    309 }
    310 
    311 Node* CodeAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
    312                            Node** args) {
    313   CallPrologue();
    314   Node* return_value = raw_assembler_->CallN(descriptor, code_target, args);
    315   CallEpilogue();
    316   return return_value;
    317 }
    318 
    319 Node* CodeAssembler::TailCallN(CallDescriptor* descriptor, Node* code_target,
    320                                Node** args) {
    321   return raw_assembler_->TailCallN(descriptor, code_target, args);
    322 }
    323 
    324 Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id,
    325                                  Node* context) {
    326   CallPrologue();
    327   Node* return_value = raw_assembler_->CallRuntime0(function_id, context);
    328   CallEpilogue();
    329   return return_value;
    330 }
    331 
    332 Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
    333                                  Node* arg1) {
    334   CallPrologue();
    335   Node* return_value = raw_assembler_->CallRuntime1(function_id, arg1, context);
    336   CallEpilogue();
    337   return return_value;
    338 }
    339 
    340 Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
    341                                  Node* arg1, Node* arg2) {
    342   CallPrologue();
    343   Node* return_value =
    344       raw_assembler_->CallRuntime2(function_id, arg1, arg2, context);
    345   CallEpilogue();
    346   return return_value;
    347 }
    348 
    349 Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
    350                                  Node* arg1, Node* arg2, Node* arg3) {
    351   CallPrologue();
    352   Node* return_value =
    353       raw_assembler_->CallRuntime3(function_id, arg1, arg2, arg3, context);
    354   CallEpilogue();
    355   return return_value;
    356 }
    357 
    358 Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
    359                                  Node* arg1, Node* arg2, Node* arg3,
    360                                  Node* arg4) {
    361   CallPrologue();
    362   Node* return_value = raw_assembler_->CallRuntime4(function_id, arg1, arg2,
    363                                                     arg3, arg4, context);
    364   CallEpilogue();
    365   return return_value;
    366 }
    367 
    368 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
    369                                      Node* context) {
    370   return raw_assembler_->TailCallRuntime0(function_id, context);
    371 }
    372 
    373 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
    374                                      Node* context, Node* arg1) {
    375   return raw_assembler_->TailCallRuntime1(function_id, arg1, context);
    376 }
    377 
    378 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
    379                                      Node* context, Node* arg1, Node* arg2) {
    380   return raw_assembler_->TailCallRuntime2(function_id, arg1, arg2, context);
    381 }
    382 
    383 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
    384                                      Node* context, Node* arg1, Node* arg2,
    385                                      Node* arg3) {
    386   return raw_assembler_->TailCallRuntime3(function_id, arg1, arg2, arg3,
    387                                           context);
    388 }
    389 
    390 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
    391                                      Node* context, Node* arg1, Node* arg2,
    392                                      Node* arg3, Node* arg4) {
    393   return raw_assembler_->TailCallRuntime4(function_id, arg1, arg2, arg3, arg4,
    394                                           context);
    395 }
    396 
    397 Node* CodeAssembler::CallStub(Callable const& callable, Node* context,
    398                               Node* arg1, size_t result_size) {
    399   Node* target = HeapConstant(callable.code());
    400   return CallStub(callable.descriptor(), target, context, arg1, result_size);
    401 }
    402 
    403 Node* CodeAssembler::CallStub(Callable const& callable, Node* context,
    404                               Node* arg1, Node* arg2, size_t result_size) {
    405   Node* target = HeapConstant(callable.code());
    406   return CallStub(callable.descriptor(), target, context, arg1, arg2,
    407                   result_size);
    408 }
    409 
    410 Node* CodeAssembler::CallStub(Callable const& callable, Node* context,
    411                               Node* arg1, Node* arg2, Node* arg3,
    412                               size_t result_size) {
    413   Node* target = HeapConstant(callable.code());
    414   return CallStub(callable.descriptor(), target, context, arg1, arg2, arg3,
    415                   result_size);
    416 }
    417 
    418 Node* CodeAssembler::CallStubN(Callable const& callable, Node** args,
    419                                size_t result_size) {
    420   Node* target = HeapConstant(callable.code());
    421   return CallStubN(callable.descriptor(), target, args, result_size);
    422 }
    423 
    424 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
    425                               Node* target, Node* context, Node* arg1,
    426                               size_t result_size) {
    427   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    428       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    429       CallDescriptor::kNoFlags, Operator::kNoProperties,
    430       MachineType::AnyTagged(), result_size);
    431 
    432   Node** args = zone()->NewArray<Node*>(2);
    433   args[0] = arg1;
    434   args[1] = context;
    435 
    436   return CallN(call_descriptor, target, args);
    437 }
    438 
    439 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
    440                               Node* target, Node* context, Node* arg1,
    441                               Node* arg2, size_t result_size) {
    442   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    443       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    444       CallDescriptor::kNoFlags, Operator::kNoProperties,
    445       MachineType::AnyTagged(), result_size);
    446 
    447   Node** args = zone()->NewArray<Node*>(3);
    448   args[0] = arg1;
    449   args[1] = arg2;
    450   args[2] = context;
    451 
    452   return CallN(call_descriptor, target, args);
    453 }
    454 
    455 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
    456                               Node* target, Node* context, Node* arg1,
    457                               Node* arg2, Node* arg3, size_t result_size) {
    458   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    459       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    460       CallDescriptor::kNoFlags, Operator::kNoProperties,
    461       MachineType::AnyTagged(), result_size);
    462 
    463   Node** args = zone()->NewArray<Node*>(4);
    464   args[0] = arg1;
    465   args[1] = arg2;
    466   args[2] = arg3;
    467   args[3] = context;
    468 
    469   return CallN(call_descriptor, target, args);
    470 }
    471 
    472 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
    473                               Node* target, Node* context, Node* arg1,
    474                               Node* arg2, Node* arg3, Node* arg4,
    475                               size_t result_size) {
    476   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    477       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    478       CallDescriptor::kNoFlags, Operator::kNoProperties,
    479       MachineType::AnyTagged(), result_size);
    480 
    481   Node** args = zone()->NewArray<Node*>(5);
    482   args[0] = arg1;
    483   args[1] = arg2;
    484   args[2] = arg3;
    485   args[3] = arg4;
    486   args[4] = context;
    487 
    488   return CallN(call_descriptor, target, args);
    489 }
    490 
    491 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
    492                               Node* target, Node* context, Node* arg1,
    493                               Node* arg2, Node* arg3, Node* arg4, Node* arg5,
    494                               size_t result_size) {
    495   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    496       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    497       CallDescriptor::kNoFlags, Operator::kNoProperties,
    498       MachineType::AnyTagged(), result_size);
    499 
    500   Node** args = zone()->NewArray<Node*>(6);
    501   args[0] = arg1;
    502   args[1] = arg2;
    503   args[2] = arg3;
    504   args[3] = arg4;
    505   args[4] = arg5;
    506   args[5] = context;
    507 
    508   return CallN(call_descriptor, target, args);
    509 }
    510 
    511 Node* CodeAssembler::CallStubN(const CallInterfaceDescriptor& descriptor,
    512                                Node* target, Node** args, size_t result_size) {
    513   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    514       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    515       CallDescriptor::kNoFlags, Operator::kNoProperties,
    516       MachineType::AnyTagged(), result_size);
    517 
    518   return CallN(call_descriptor, target, args);
    519 }
    520 
    521 Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
    522                                   Node* arg1, Node* arg2, size_t result_size) {
    523   Node* target = HeapConstant(callable.code());
    524   return TailCallStub(callable.descriptor(), target, context, arg1, arg2,
    525                       result_size);
    526 }
    527 
    528 Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
    529                                   Node* arg1, Node* arg2, Node* arg3,
    530                                   size_t result_size) {
    531   Node* target = HeapConstant(callable.code());
    532   return TailCallStub(callable.descriptor(), target, context, arg1, arg2, arg3,
    533                       result_size);
    534 }
    535 
    536 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
    537                                   Node* target, Node* context, Node* arg1,
    538                                   Node* arg2, size_t result_size) {
    539   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    540       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    541       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
    542       MachineType::AnyTagged(), result_size);
    543 
    544   Node** args = zone()->NewArray<Node*>(3);
    545   args[0] = arg1;
    546   args[1] = arg2;
    547   args[2] = context;
    548 
    549   return raw_assembler_->TailCallN(call_descriptor, target, args);
    550 }
    551 
    552 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
    553                                   Node* target, Node* context, Node* arg1,
    554                                   Node* arg2, Node* arg3, size_t result_size) {
    555   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    556       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    557       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
    558       MachineType::AnyTagged(), result_size);
    559 
    560   Node** args = zone()->NewArray<Node*>(4);
    561   args[0] = arg1;
    562   args[1] = arg2;
    563   args[2] = arg3;
    564   args[3] = context;
    565 
    566   return raw_assembler_->TailCallN(call_descriptor, target, args);
    567 }
    568 
    569 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
    570                                   Node* target, Node* context, Node* arg1,
    571                                   Node* arg2, Node* arg3, Node* arg4,
    572                                   size_t result_size) {
    573   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    574       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
    575       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
    576       MachineType::AnyTagged(), result_size);
    577 
    578   Node** args = zone()->NewArray<Node*>(5);
    579   args[0] = arg1;
    580   args[1] = arg2;
    581   args[2] = arg3;
    582   args[3] = arg4;
    583   args[4] = context;
    584 
    585   return raw_assembler_->TailCallN(call_descriptor, target, args);
    586 }
    587 
    588 Node* CodeAssembler::TailCallBytecodeDispatch(
    589     const CallInterfaceDescriptor& interface_descriptor,
    590     Node* code_target_address, Node** args) {
    591   CallDescriptor* descriptor = Linkage::GetBytecodeDispatchCallDescriptor(
    592       isolate(), zone(), interface_descriptor,
    593       interface_descriptor.GetStackParameterCount());
    594   return raw_assembler_->TailCallN(descriptor, code_target_address, args);
    595 }
    596 
    597 Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
    598                             Node* function, Node* receiver,
    599                             size_t result_size) {
    600   const int argc = 0;
    601   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    602       isolate(), zone(), callable.descriptor(), argc + 1,
    603       CallDescriptor::kNoFlags, Operator::kNoProperties,
    604       MachineType::AnyTagged(), result_size);
    605   Node* target = HeapConstant(callable.code());
    606 
    607   Node** args = zone()->NewArray<Node*>(argc + 4);
    608   args[0] = function;
    609   args[1] = Int32Constant(argc);
    610   args[2] = receiver;
    611   args[3] = context;
    612 
    613   return CallN(call_descriptor, target, args);
    614 }
    615 
    616 Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
    617                             Node* function, Node* receiver, Node* arg1,
    618                             size_t result_size) {
    619   const int argc = 1;
    620   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    621       isolate(), zone(), callable.descriptor(), argc + 1,
    622       CallDescriptor::kNoFlags, Operator::kNoProperties,
    623       MachineType::AnyTagged(), result_size);
    624   Node* target = HeapConstant(callable.code());
    625 
    626   Node** args = zone()->NewArray<Node*>(argc + 4);
    627   args[0] = function;
    628   args[1] = Int32Constant(argc);
    629   args[2] = receiver;
    630   args[3] = arg1;
    631   args[4] = context;
    632 
    633   return CallN(call_descriptor, target, args);
    634 }
    635 
    636 Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
    637                             Node* function, Node* receiver, Node* arg1,
    638                             Node* arg2, size_t result_size) {
    639   const int argc = 2;
    640   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    641       isolate(), zone(), callable.descriptor(), argc + 1,
    642       CallDescriptor::kNoFlags, Operator::kNoProperties,
    643       MachineType::AnyTagged(), result_size);
    644   Node* target = HeapConstant(callable.code());
    645 
    646   Node** args = zone()->NewArray<Node*>(argc + 4);
    647   args[0] = function;
    648   args[1] = Int32Constant(argc);
    649   args[2] = receiver;
    650   args[3] = arg1;
    651   args[4] = arg2;
    652   args[5] = context;
    653 
    654   return CallN(call_descriptor, target, args);
    655 }
    656 
    657 void CodeAssembler::Goto(CodeAssembler::Label* label) {
    658   label->MergeVariables();
    659   raw_assembler_->Goto(label->label_);
    660 }
    661 
    662 void CodeAssembler::GotoIf(Node* condition, Label* true_label) {
    663   Label false_label(this);
    664   Branch(condition, true_label, &false_label);
    665   Bind(&false_label);
    666 }
    667 
    668 void CodeAssembler::GotoUnless(Node* condition, Label* false_label) {
    669   Label true_label(this);
    670   Branch(condition, &true_label, false_label);
    671   Bind(&true_label);
    672 }
    673 
    674 void CodeAssembler::Branch(Node* condition, CodeAssembler::Label* true_label,
    675                            CodeAssembler::Label* false_label) {
    676   true_label->MergeVariables();
    677   false_label->MergeVariables();
    678   return raw_assembler_->Branch(condition, true_label->label_,
    679                                 false_label->label_);
    680 }
    681 
    682 void CodeAssembler::Switch(Node* index, Label* default_label,
    683                            int32_t* case_values, Label** case_labels,
    684                            size_t case_count) {
    685   RawMachineLabel** labels =
    686       new (zone()->New(sizeof(RawMachineLabel*) * case_count))
    687           RawMachineLabel*[case_count];
    688   for (size_t i = 0; i < case_count; ++i) {
    689     labels[i] = case_labels[i]->label_;
    690     case_labels[i]->MergeVariables();
    691     default_label->MergeVariables();
    692   }
    693   return raw_assembler_->Switch(index, default_label->label_, case_values,
    694                                 labels, case_count);
    695 }
    696 
    697 // RawMachineAssembler delegate helpers:
    698 Isolate* CodeAssembler::isolate() const { return raw_assembler_->isolate(); }
    699 
    700 Factory* CodeAssembler::factory() const { return isolate()->factory(); }
    701 
    702 Graph* CodeAssembler::graph() const { return raw_assembler_->graph(); }
    703 
    704 Zone* CodeAssembler::zone() const { return raw_assembler_->zone(); }
    705 
    706 // The core implementation of Variable is stored through an indirection so
    707 // that it can outlive the often block-scoped Variable declarations. This is
    708 // needed to ensure that variable binding and merging through phis can
    709 // properly be verified.
    710 class CodeAssembler::Variable::Impl : public ZoneObject {
    711  public:
    712   explicit Impl(MachineRepresentation rep) : value_(nullptr), rep_(rep) {}
    713   Node* value_;
    714   MachineRepresentation rep_;
    715 };
    716 
    717 CodeAssembler::Variable::Variable(CodeAssembler* assembler,
    718                                   MachineRepresentation rep)
    719     : impl_(new (assembler->zone()) Impl(rep)), assembler_(assembler) {
    720   assembler->variables_.insert(impl_);
    721 }
    722 
    723 CodeAssembler::Variable::~Variable() { assembler_->variables_.erase(impl_); }
    724 
    725 void CodeAssembler::Variable::Bind(Node* value) { impl_->value_ = value; }
    726 
    727 Node* CodeAssembler::Variable::value() const {
    728   DCHECK_NOT_NULL(impl_->value_);
    729   return impl_->value_;
    730 }
    731 
    732 MachineRepresentation CodeAssembler::Variable::rep() const {
    733   return impl_->rep_;
    734 }
    735 
    736 bool CodeAssembler::Variable::IsBound() const {
    737   return impl_->value_ != nullptr;
    738 }
    739 
    740 CodeAssembler::Label::Label(CodeAssembler* assembler, int merged_value_count,
    741                             CodeAssembler::Variable** merged_variables,
    742                             CodeAssembler::Label::Type type)
    743     : bound_(false), merge_count_(0), assembler_(assembler), label_(nullptr) {
    744   void* buffer = assembler->zone()->New(sizeof(RawMachineLabel));
    745   label_ = new (buffer)
    746       RawMachineLabel(type == kDeferred ? RawMachineLabel::kDeferred
    747                                         : RawMachineLabel::kNonDeferred);
    748   for (int i = 0; i < merged_value_count; ++i) {
    749     variable_phis_[merged_variables[i]->impl_] = nullptr;
    750   }
    751 }
    752 
    753 void CodeAssembler::Label::MergeVariables() {
    754   ++merge_count_;
    755   for (auto var : assembler_->variables_) {
    756     size_t count = 0;
    757     Node* node = var->value_;
    758     if (node != nullptr) {
    759       auto i = variable_merges_.find(var);
    760       if (i != variable_merges_.end()) {
    761         i->second.push_back(node);
    762         count = i->second.size();
    763       } else {
    764         count = 1;
    765         variable_merges_[var] = std::vector<Node*>(1, node);
    766       }
    767     }
    768     // If the following asserts, then you've jumped to a label without a bound
    769     // variable along that path that expects to merge its value into a phi.
    770     DCHECK(variable_phis_.find(var) == variable_phis_.end() ||
    771            count == merge_count_);
    772     USE(count);
    773 
    774     // If the label is already bound, we already know the set of variables to
    775     // merge and phi nodes have already been created.
    776     if (bound_) {
    777       auto phi = variable_phis_.find(var);
    778       if (phi != variable_phis_.end()) {
    779         DCHECK_NOT_NULL(phi->second);
    780         assembler_->raw_assembler_->AppendPhiInput(phi->second, node);
    781       } else {
    782         auto i = variable_merges_.find(var);
    783         if (i != variable_merges_.end()) {
    784           // If the following assert fires, then you've declared a variable that
    785           // has the same bound value along all paths up until the point you
    786           // bound this label, but then later merged a path with a new value for
    787           // the variable after the label bind (it's not possible to add phis to
    788           // the bound label after the fact, just make sure to list the variable
    789           // in the label's constructor's list of merged variables).
    790           DCHECK(find_if(i->second.begin(), i->second.end(),
    791                          [node](Node* e) -> bool { return node != e; }) ==
    792                  i->second.end());
    793         }
    794       }
    795     }
    796   }
    797 }
    798 
    799 void CodeAssembler::Label::Bind() {
    800   DCHECK(!bound_);
    801   assembler_->raw_assembler_->Bind(label_);
    802 
    803   // Make sure that all variables that have changed along any path up to this
    804   // point are marked as merge variables.
    805   for (auto var : assembler_->variables_) {
    806     Node* shared_value = nullptr;
    807     auto i = variable_merges_.find(var);
    808     if (i != variable_merges_.end()) {
    809       for (auto value : i->second) {
    810         DCHECK(value != nullptr);
    811         if (value != shared_value) {
    812           if (shared_value == nullptr) {
    813             shared_value = value;
    814           } else {
    815             variable_phis_[var] = nullptr;
    816           }
    817         }
    818       }
    819     }
    820   }
    821 
    822   for (auto var : variable_phis_) {
    823     CodeAssembler::Variable::Impl* var_impl = var.first;
    824     auto i = variable_merges_.find(var_impl);
    825     // If the following assert fires, then a variable that has been marked as
    826     // being merged at the label--either by explicitly marking it so in the
    827     // label constructor or by having seen different bound values at branches
    828     // into the label--doesn't have a bound value along all of the paths that
    829     // have been merged into the label up to this point.
    830     DCHECK(i != variable_merges_.end() && i->second.size() == merge_count_);
    831     Node* phi = assembler_->raw_assembler_->Phi(
    832         var.first->rep_, static_cast<int>(merge_count_), &(i->second[0]));
    833     variable_phis_[var_impl] = phi;
    834   }
    835 
    836   // Bind all variables to a merge phi, the common value along all paths or
    837   // null.
    838   for (auto var : assembler_->variables_) {
    839     auto i = variable_phis_.find(var);
    840     if (i != variable_phis_.end()) {
    841       var->value_ = i->second;
    842     } else {
    843       auto j = variable_merges_.find(var);
    844       if (j != variable_merges_.end() && j->second.size() == merge_count_) {
    845         var->value_ = j->second.back();
    846       } else {
    847         var->value_ = nullptr;
    848       }
    849     }
    850   }
    851 
    852   bound_ = true;
    853 }
    854 
    855 }  // namespace compiler
    856 }  // namespace internal
    857 }  // namespace v8
    858