Home | History | Annotate | Download | only in compiler
      1 // Copyright 2014 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/raw-machine-assembler.h"
      6 
      7 #include "src/code-factory.h"
      8 #include "src/compiler/node-properties.h"
      9 #include "src/compiler/pipeline.h"
     10 #include "src/compiler/scheduler.h"
     11 
     12 namespace v8 {
     13 namespace internal {
     14 namespace compiler {
     15 
     16 RawMachineAssembler::RawMachineAssembler(Isolate* isolate, Graph* graph,
     17                                          CallDescriptor* call_descriptor,
     18                                          MachineRepresentation word,
     19                                          MachineOperatorBuilder::Flags flags)
     20     : isolate_(isolate),
     21       graph_(graph),
     22       schedule_(new (zone()) Schedule(zone())),
     23       machine_(zone(), word, flags),
     24       common_(zone()),
     25       call_descriptor_(call_descriptor),
     26       parameters_(parameter_count(), zone()),
     27       current_block_(schedule()->start()) {
     28   int param_count = static_cast<int>(parameter_count());
     29   // Add an extra input for the JSFunction parameter to the start node.
     30   graph->SetStart(graph->NewNode(common_.Start(param_count + 1)));
     31   for (size_t i = 0; i < parameter_count(); ++i) {
     32     parameters_[i] =
     33         AddNode(common()->Parameter(static_cast<int>(i)), graph->start());
     34   }
     35   graph->SetEnd(graph->NewNode(common_.End(0)));
     36 }
     37 
     38 
     39 Schedule* RawMachineAssembler::Export() {
     40   // Compute the correct codegen order.
     41   DCHECK(schedule_->rpo_order()->empty());
     42   Scheduler::ComputeSpecialRPO(zone(), schedule_);
     43   // Invalidate RawMachineAssembler.
     44   Schedule* schedule = schedule_;
     45   schedule_ = nullptr;
     46   return schedule;
     47 }
     48 
     49 
     50 Node* RawMachineAssembler::Parameter(size_t index) {
     51   DCHECK(index < parameter_count());
     52   return parameters_[index];
     53 }
     54 
     55 
     56 void RawMachineAssembler::Goto(RawMachineLabel* label) {
     57   DCHECK(current_block_ != schedule()->end());
     58   schedule()->AddGoto(CurrentBlock(), Use(label));
     59   current_block_ = nullptr;
     60 }
     61 
     62 
     63 void RawMachineAssembler::Branch(Node* condition, RawMachineLabel* true_val,
     64                                  RawMachineLabel* false_val) {
     65   DCHECK(current_block_ != schedule()->end());
     66   Node* branch = AddNode(common()->Branch(), condition);
     67   schedule()->AddBranch(CurrentBlock(), branch, Use(true_val), Use(false_val));
     68   current_block_ = nullptr;
     69 }
     70 
     71 
     72 void RawMachineAssembler::Switch(Node* index, RawMachineLabel* default_label,
     73                                  int32_t* case_values,
     74                                  RawMachineLabel** case_labels,
     75                                  size_t case_count) {
     76   DCHECK_NE(schedule()->end(), current_block_);
     77   size_t succ_count = case_count + 1;
     78   Node* switch_node = AddNode(common()->Switch(succ_count), index);
     79   BasicBlock** succ_blocks = zone()->NewArray<BasicBlock*>(succ_count);
     80   for (size_t index = 0; index < case_count; ++index) {
     81     int32_t case_value = case_values[index];
     82     BasicBlock* case_block = Use(case_labels[index]);
     83     Node* case_node =
     84         graph()->NewNode(common()->IfValue(case_value), switch_node);
     85     schedule()->AddNode(case_block, case_node);
     86     succ_blocks[index] = case_block;
     87   }
     88   BasicBlock* default_block = Use(default_label);
     89   Node* default_node = graph()->NewNode(common()->IfDefault(), switch_node);
     90   schedule()->AddNode(default_block, default_node);
     91   succ_blocks[case_count] = default_block;
     92   schedule()->AddSwitch(CurrentBlock(), switch_node, succ_blocks, succ_count);
     93   current_block_ = nullptr;
     94 }
     95 
     96 
     97 void RawMachineAssembler::Return(Node* value) {
     98   Node* ret = MakeNode(common()->Return(), 1, &value);
     99   NodeProperties::MergeControlToEnd(graph(), common(), ret);
    100   schedule()->AddReturn(CurrentBlock(), ret);
    101   current_block_ = nullptr;
    102 }
    103 
    104 
    105 void RawMachineAssembler::Return(Node* v1, Node* v2) {
    106   Node* values[] = {v1, v2};
    107   Node* ret = MakeNode(common()->Return(2), 2, values);
    108   NodeProperties::MergeControlToEnd(graph(), common(), ret);
    109   schedule()->AddReturn(CurrentBlock(), ret);
    110   current_block_ = nullptr;
    111 }
    112 
    113 
    114 void RawMachineAssembler::Return(Node* v1, Node* v2, Node* v3) {
    115   Node* values[] = {v1, v2, v3};
    116   Node* ret = MakeNode(common()->Return(3), 3, values);
    117   NodeProperties::MergeControlToEnd(graph(), common(), ret);
    118   schedule()->AddReturn(CurrentBlock(), ret);
    119   current_block_ = nullptr;
    120 }
    121 
    122 
    123 Node* RawMachineAssembler::CallN(CallDescriptor* desc, Node* function,
    124                                  Node** args) {
    125   int param_count =
    126       static_cast<int>(desc->GetMachineSignature()->parameter_count());
    127   int input_count = param_count + 1;
    128   Node** buffer = zone()->NewArray<Node*>(input_count);
    129   int index = 0;
    130   buffer[index++] = function;
    131   for (int i = 0; i < param_count; i++) {
    132     buffer[index++] = args[i];
    133   }
    134   return AddNode(common()->Call(desc), input_count, buffer);
    135 }
    136 
    137 
    138 Node* RawMachineAssembler::CallNWithFrameState(CallDescriptor* desc,
    139                                                Node* function, Node** args,
    140                                                Node* frame_state) {
    141   DCHECK(desc->NeedsFrameState());
    142   int param_count =
    143       static_cast<int>(desc->GetMachineSignature()->parameter_count());
    144   int input_count = param_count + 2;
    145   Node** buffer = zone()->NewArray<Node*>(input_count);
    146   int index = 0;
    147   buffer[index++] = function;
    148   for (int i = 0; i < param_count; i++) {
    149     buffer[index++] = args[i];
    150   }
    151   buffer[index++] = frame_state;
    152   return AddNode(common()->Call(desc), input_count, buffer);
    153 }
    154 
    155 
    156 Node* RawMachineAssembler::CallRuntime1(Runtime::FunctionId function,
    157                                         Node* arg1, Node* context) {
    158   CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
    159       zone(), function, 1, Operator::kNoProperties, CallDescriptor::kNoFlags);
    160   int return_count = static_cast<int>(descriptor->ReturnCount());
    161 
    162   Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
    163   Node* ref = AddNode(
    164       common()->ExternalConstant(ExternalReference(function, isolate())));
    165   Node* arity = Int32Constant(1);
    166 
    167   return AddNode(common()->Call(descriptor), centry, arg1, ref, arity, context);
    168 }
    169 
    170 
    171 Node* RawMachineAssembler::CallRuntime2(Runtime::FunctionId function,
    172                                         Node* arg1, Node* arg2, Node* context) {
    173   CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
    174       zone(), function, 2, Operator::kNoProperties, CallDescriptor::kNoFlags);
    175   int return_count = static_cast<int>(descriptor->ReturnCount());
    176 
    177   Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
    178   Node* ref = AddNode(
    179       common()->ExternalConstant(ExternalReference(function, isolate())));
    180   Node* arity = Int32Constant(2);
    181 
    182   return AddNode(common()->Call(descriptor), centry, arg1, arg2, ref, arity,
    183                  context);
    184 }
    185 
    186 
    187 Node* RawMachineAssembler::CallRuntime4(Runtime::FunctionId function,
    188                                         Node* arg1, Node* arg2, Node* arg3,
    189                                         Node* arg4, Node* context) {
    190   CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
    191       zone(), function, 4, Operator::kNoProperties, CallDescriptor::kNoFlags);
    192   int return_count = static_cast<int>(descriptor->ReturnCount());
    193 
    194   Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
    195   Node* ref = AddNode(
    196       common()->ExternalConstant(ExternalReference(function, isolate())));
    197   Node* arity = Int32Constant(4);
    198 
    199   return AddNode(common()->Call(descriptor), centry, arg1, arg2, arg3, arg4,
    200                  ref, arity, context);
    201 }
    202 
    203 
    204 Node* RawMachineAssembler::TailCallN(CallDescriptor* desc, Node* function,
    205                                      Node** args) {
    206   int param_count =
    207       static_cast<int>(desc->GetMachineSignature()->parameter_count());
    208   int input_count = param_count + 1;
    209   Node** buffer = zone()->NewArray<Node*>(input_count);
    210   int index = 0;
    211   buffer[index++] = function;
    212   for (int i = 0; i < param_count; i++) {
    213     buffer[index++] = args[i];
    214   }
    215   Node* tail_call = MakeNode(common()->TailCall(desc), input_count, buffer);
    216   NodeProperties::MergeControlToEnd(graph(), common(), tail_call);
    217   schedule()->AddTailCall(CurrentBlock(), tail_call);
    218   current_block_ = nullptr;
    219   return tail_call;
    220 }
    221 
    222 
    223 Node* RawMachineAssembler::TailCallRuntime1(Runtime::FunctionId function,
    224                                             Node* arg1, Node* context) {
    225   const int kArity = 1;
    226   CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
    227       zone(), function, kArity, Operator::kNoProperties,
    228       CallDescriptor::kSupportsTailCalls);
    229   int return_count = static_cast<int>(desc->ReturnCount());
    230 
    231   Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
    232   Node* ref = AddNode(
    233       common()->ExternalConstant(ExternalReference(function, isolate())));
    234   Node* arity = Int32Constant(kArity);
    235 
    236   Node* nodes[] = {centry, arg1, ref, arity, context};
    237   Node* tail_call = MakeNode(common()->TailCall(desc), arraysize(nodes), nodes);
    238 
    239   NodeProperties::MergeControlToEnd(graph(), common(), tail_call);
    240   schedule()->AddTailCall(CurrentBlock(), tail_call);
    241   current_block_ = nullptr;
    242   return tail_call;
    243 }
    244 
    245 
    246 Node* RawMachineAssembler::TailCallRuntime2(Runtime::FunctionId function,
    247                                             Node* arg1, Node* arg2,
    248                                             Node* context) {
    249   const int kArity = 2;
    250   CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
    251       zone(), function, kArity, Operator::kNoProperties,
    252       CallDescriptor::kSupportsTailCalls);
    253   int return_count = static_cast<int>(desc->ReturnCount());
    254 
    255   Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
    256   Node* ref = AddNode(
    257       common()->ExternalConstant(ExternalReference(function, isolate())));
    258   Node* arity = Int32Constant(kArity);
    259 
    260   Node* nodes[] = {centry, arg1, arg2, ref, arity, context};
    261   Node* tail_call = MakeNode(common()->TailCall(desc), arraysize(nodes), nodes);
    262 
    263   NodeProperties::MergeControlToEnd(graph(), common(), tail_call);
    264   schedule()->AddTailCall(CurrentBlock(), tail_call);
    265   current_block_ = nullptr;
    266   return tail_call;
    267 }
    268 
    269 
    270 Node* RawMachineAssembler::CallCFunction0(MachineType return_type,
    271                                           Node* function) {
    272   MachineSignature::Builder builder(zone(), 1, 0);
    273   builder.AddReturn(return_type);
    274   const CallDescriptor* descriptor =
    275       Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
    276 
    277   return AddNode(common()->Call(descriptor), function);
    278 }
    279 
    280 
    281 Node* RawMachineAssembler::CallCFunction1(MachineType return_type,
    282                                           MachineType arg0_type, Node* function,
    283                                           Node* arg0) {
    284   MachineSignature::Builder builder(zone(), 1, 1);
    285   builder.AddReturn(return_type);
    286   builder.AddParam(arg0_type);
    287   const CallDescriptor* descriptor =
    288       Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
    289 
    290   return AddNode(common()->Call(descriptor), function, arg0);
    291 }
    292 
    293 
    294 Node* RawMachineAssembler::CallCFunction2(MachineType return_type,
    295                                           MachineType arg0_type,
    296                                           MachineType arg1_type, Node* function,
    297                                           Node* arg0, Node* arg1) {
    298   MachineSignature::Builder builder(zone(), 1, 2);
    299   builder.AddReturn(return_type);
    300   builder.AddParam(arg0_type);
    301   builder.AddParam(arg1_type);
    302   const CallDescriptor* descriptor =
    303       Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
    304 
    305   return AddNode(common()->Call(descriptor), function, arg0, arg1);
    306 }
    307 
    308 
    309 Node* RawMachineAssembler::CallCFunction8(
    310     MachineType return_type, MachineType arg0_type, MachineType arg1_type,
    311     MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
    312     MachineType arg5_type, MachineType arg6_type, MachineType arg7_type,
    313     Node* function, Node* arg0, Node* arg1, Node* arg2, Node* arg3, Node* arg4,
    314     Node* arg5, Node* arg6, Node* arg7) {
    315   MachineSignature::Builder builder(zone(), 1, 8);
    316   builder.AddReturn(return_type);
    317   builder.AddParam(arg0_type);
    318   builder.AddParam(arg1_type);
    319   builder.AddParam(arg2_type);
    320   builder.AddParam(arg3_type);
    321   builder.AddParam(arg4_type);
    322   builder.AddParam(arg5_type);
    323   builder.AddParam(arg6_type);
    324   builder.AddParam(arg7_type);
    325   Node* args[] = {function, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7};
    326   const CallDescriptor* descriptor =
    327       Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
    328   return AddNode(common()->Call(descriptor), arraysize(args), args);
    329 }
    330 
    331 
    332 void RawMachineAssembler::Bind(RawMachineLabel* label) {
    333   DCHECK(current_block_ == nullptr);
    334   DCHECK(!label->bound_);
    335   label->bound_ = true;
    336   current_block_ = EnsureBlock(label);
    337 }
    338 
    339 
    340 BasicBlock* RawMachineAssembler::Use(RawMachineLabel* label) {
    341   label->used_ = true;
    342   return EnsureBlock(label);
    343 }
    344 
    345 
    346 BasicBlock* RawMachineAssembler::EnsureBlock(RawMachineLabel* label) {
    347   if (label->block_ == nullptr) label->block_ = schedule()->NewBasicBlock();
    348   return label->block_;
    349 }
    350 
    351 
    352 BasicBlock* RawMachineAssembler::CurrentBlock() {
    353   DCHECK(current_block_);
    354   return current_block_;
    355 }
    356 
    357 
    358 Node* RawMachineAssembler::AddNode(const Operator* op, int input_count,
    359                                    Node** inputs) {
    360   DCHECK_NOT_NULL(schedule_);
    361   DCHECK_NOT_NULL(current_block_);
    362   Node* node = MakeNode(op, input_count, inputs);
    363   schedule()->AddNode(CurrentBlock(), node);
    364   return node;
    365 }
    366 
    367 
    368 Node* RawMachineAssembler::MakeNode(const Operator* op, int input_count,
    369                                     Node** inputs) {
    370   // The raw machine assembler nodes do not have effect and control inputs,
    371   // so we disable checking input counts here.
    372   return graph()->NewNodeUnchecked(op, input_count, inputs);
    373 }
    374 
    375 
    376 RawMachineLabel::RawMachineLabel()
    377     : block_(nullptr), used_(false), bound_(false) {}
    378 
    379 
    380 RawMachineLabel::~RawMachineLabel() { DCHECK(bound_ || !used_); }
    381 
    382 }  // namespace compiler
    383 }  // namespace internal
    384 }  // namespace v8
    385