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 Node* RawMachineAssembler::RelocatableIntPtrConstant(intptr_t value,
     39                                                      RelocInfo::Mode rmode) {
     40   return kPointerSize == 8
     41              ? RelocatableInt64Constant(value, rmode)
     42              : RelocatableInt32Constant(static_cast<int>(value), rmode);
     43 }
     44 
     45 Schedule* RawMachineAssembler::Export() {
     46   // Compute the correct codegen order.
     47   DCHECK(schedule_->rpo_order()->empty());
     48   OFStream os(stdout);
     49   if (FLAG_trace_turbo_scheduler) {
     50     PrintF("--- RAW SCHEDULE -------------------------------------------\n");
     51     os << *schedule_;
     52   }
     53   schedule_->EnsureCFGWellFormedness();
     54   schedule_->PropagateDeferredMark();
     55   if (FLAG_trace_turbo_scheduler) {
     56     PrintF("--- EDGE SPLIT AND PROPAGATED DEFERRED SCHEDULE ------------\n");
     57     os << *schedule_;
     58   }
     59   Scheduler::ComputeSpecialRPO(zone(), schedule_);
     60   // Invalidate RawMachineAssembler.
     61   Schedule* schedule = schedule_;
     62   schedule_ = nullptr;
     63   return schedule;
     64 }
     65 
     66 
     67 Node* RawMachineAssembler::Parameter(size_t index) {
     68   DCHECK(index < parameter_count());
     69   return parameters_[index];
     70 }
     71 
     72 
     73 void RawMachineAssembler::Goto(RawMachineLabel* label) {
     74   DCHECK(current_block_ != schedule()->end());
     75   schedule()->AddGoto(CurrentBlock(), Use(label));
     76   current_block_ = nullptr;
     77 }
     78 
     79 
     80 void RawMachineAssembler::Branch(Node* condition, RawMachineLabel* true_val,
     81                                  RawMachineLabel* false_val) {
     82   DCHECK(current_block_ != schedule()->end());
     83   Node* branch = MakeNode(common()->Branch(), 1, &condition);
     84   schedule()->AddBranch(CurrentBlock(), branch, Use(true_val), Use(false_val));
     85   current_block_ = nullptr;
     86 }
     87 
     88 
     89 void RawMachineAssembler::Switch(Node* index, RawMachineLabel* default_label,
     90                                  int32_t* case_values,
     91                                  RawMachineLabel** case_labels,
     92                                  size_t case_count) {
     93   DCHECK_NE(schedule()->end(), current_block_);
     94   size_t succ_count = case_count + 1;
     95   Node* switch_node = AddNode(common()->Switch(succ_count), index);
     96   BasicBlock** succ_blocks = zone()->NewArray<BasicBlock*>(succ_count);
     97   for (size_t index = 0; index < case_count; ++index) {
     98     int32_t case_value = case_values[index];
     99     BasicBlock* case_block = schedule()->NewBasicBlock();
    100     Node* case_node =
    101         graph()->NewNode(common()->IfValue(case_value), switch_node);
    102     schedule()->AddNode(case_block, case_node);
    103     schedule()->AddGoto(case_block, Use(case_labels[index]));
    104     succ_blocks[index] = case_block;
    105   }
    106   BasicBlock* default_block = schedule()->NewBasicBlock();
    107   Node* default_node = graph()->NewNode(common()->IfDefault(), switch_node);
    108   schedule()->AddNode(default_block, default_node);
    109   schedule()->AddGoto(default_block, Use(default_label));
    110   succ_blocks[case_count] = default_block;
    111   schedule()->AddSwitch(CurrentBlock(), switch_node, succ_blocks, succ_count);
    112   current_block_ = nullptr;
    113 }
    114 
    115 
    116 void RawMachineAssembler::Return(Node* value) {
    117   Node* ret = MakeNode(common()->Return(), 1, &value);
    118   schedule()->AddReturn(CurrentBlock(), ret);
    119   current_block_ = nullptr;
    120 }
    121 
    122 
    123 void RawMachineAssembler::Return(Node* v1, Node* v2) {
    124   Node* values[] = {v1, v2};
    125   Node* ret = MakeNode(common()->Return(2), 2, values);
    126   schedule()->AddReturn(CurrentBlock(), ret);
    127   current_block_ = nullptr;
    128 }
    129 
    130 
    131 void RawMachineAssembler::Return(Node* v1, Node* v2, Node* v3) {
    132   Node* values[] = {v1, v2, v3};
    133   Node* ret = MakeNode(common()->Return(3), 3, values);
    134   schedule()->AddReturn(CurrentBlock(), ret);
    135   current_block_ = nullptr;
    136 }
    137 
    138 void RawMachineAssembler::DebugBreak() { AddNode(machine()->DebugBreak()); }
    139 
    140 void RawMachineAssembler::Comment(const char* msg) {
    141   AddNode(machine()->Comment(msg));
    142 }
    143 
    144 Node* RawMachineAssembler::CallN(CallDescriptor* desc, Node* function,
    145                                  Node** args) {
    146   int param_count =
    147       static_cast<int>(desc->GetMachineSignature()->parameter_count());
    148   int input_count = param_count + 1;
    149   Node** buffer = zone()->NewArray<Node*>(input_count);
    150   int index = 0;
    151   buffer[index++] = function;
    152   for (int i = 0; i < param_count; i++) {
    153     buffer[index++] = args[i];
    154   }
    155   return AddNode(common()->Call(desc), input_count, buffer);
    156 }
    157 
    158 
    159 Node* RawMachineAssembler::CallNWithFrameState(CallDescriptor* desc,
    160                                                Node* function, Node** args,
    161                                                Node* frame_state) {
    162   DCHECK(desc->NeedsFrameState());
    163   int param_count =
    164       static_cast<int>(desc->GetMachineSignature()->parameter_count());
    165   int input_count = param_count + 2;
    166   Node** buffer = zone()->NewArray<Node*>(input_count);
    167   int index = 0;
    168   buffer[index++] = function;
    169   for (int i = 0; i < param_count; i++) {
    170     buffer[index++] = args[i];
    171   }
    172   buffer[index++] = frame_state;
    173   return AddNode(common()->Call(desc), input_count, buffer);
    174 }
    175 
    176 Node* RawMachineAssembler::CallRuntime0(Runtime::FunctionId function,
    177                                         Node* context) {
    178   CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
    179       zone(), function, 0, Operator::kNoProperties, CallDescriptor::kNoFlags);
    180   int return_count = static_cast<int>(descriptor->ReturnCount());
    181 
    182   Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
    183   Node* ref = AddNode(
    184       common()->ExternalConstant(ExternalReference(function, isolate())));
    185   Node* arity = Int32Constant(0);
    186 
    187   return AddNode(common()->Call(descriptor), centry, ref, arity, context);
    188 }
    189 
    190 Node* RawMachineAssembler::CallRuntime1(Runtime::FunctionId function,
    191                                         Node* arg1, Node* context) {
    192   CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
    193       zone(), function, 1, Operator::kNoProperties, CallDescriptor::kNoFlags);
    194   int return_count = static_cast<int>(descriptor->ReturnCount());
    195 
    196   Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
    197   Node* ref = AddNode(
    198       common()->ExternalConstant(ExternalReference(function, isolate())));
    199   Node* arity = Int32Constant(1);
    200 
    201   return AddNode(common()->Call(descriptor), centry, arg1, ref, arity, context);
    202 }
    203 
    204 
    205 Node* RawMachineAssembler::CallRuntime2(Runtime::FunctionId function,
    206                                         Node* arg1, Node* arg2, Node* context) {
    207   CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
    208       zone(), function, 2, Operator::kNoProperties, CallDescriptor::kNoFlags);
    209   int return_count = static_cast<int>(descriptor->ReturnCount());
    210 
    211   Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
    212   Node* ref = AddNode(
    213       common()->ExternalConstant(ExternalReference(function, isolate())));
    214   Node* arity = Int32Constant(2);
    215 
    216   return AddNode(common()->Call(descriptor), centry, arg1, arg2, ref, arity,
    217                  context);
    218 }
    219 
    220 Node* RawMachineAssembler::CallRuntime3(Runtime::FunctionId function,
    221                                         Node* arg1, Node* arg2, Node* arg3,
    222                                         Node* context) {
    223   CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
    224       zone(), function, 3, Operator::kNoProperties, CallDescriptor::kNoFlags);
    225   int return_count = static_cast<int>(descriptor->ReturnCount());
    226 
    227   Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
    228   Node* ref = AddNode(
    229       common()->ExternalConstant(ExternalReference(function, isolate())));
    230   Node* arity = Int32Constant(3);
    231 
    232   return AddNode(common()->Call(descriptor), centry, arg1, arg2, arg3, ref,
    233                  arity, context);
    234 }
    235 
    236 Node* RawMachineAssembler::CallRuntime4(Runtime::FunctionId function,
    237                                         Node* arg1, Node* arg2, Node* arg3,
    238                                         Node* arg4, Node* context) {
    239   CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
    240       zone(), function, 4, Operator::kNoProperties, CallDescriptor::kNoFlags);
    241   int return_count = static_cast<int>(descriptor->ReturnCount());
    242 
    243   Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
    244   Node* ref = AddNode(
    245       common()->ExternalConstant(ExternalReference(function, isolate())));
    246   Node* arity = Int32Constant(4);
    247 
    248   return AddNode(common()->Call(descriptor), centry, arg1, arg2, arg3, arg4,
    249                  ref, arity, context);
    250 }
    251 
    252 
    253 Node* RawMachineAssembler::TailCallN(CallDescriptor* desc, Node* function,
    254                                      Node** args) {
    255   int param_count =
    256       static_cast<int>(desc->GetMachineSignature()->parameter_count());
    257   int input_count = param_count + 1;
    258   Node** buffer = zone()->NewArray<Node*>(input_count);
    259   int index = 0;
    260   buffer[index++] = function;
    261   for (int i = 0; i < param_count; i++) {
    262     buffer[index++] = args[i];
    263   }
    264   Node* tail_call = MakeNode(common()->TailCall(desc), input_count, buffer);
    265   schedule()->AddTailCall(CurrentBlock(), tail_call);
    266   current_block_ = nullptr;
    267   return tail_call;
    268 }
    269 
    270 Node* RawMachineAssembler::TailCallRuntime0(Runtime::FunctionId function,
    271                                             Node* context) {
    272   const int kArity = 0;
    273   CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
    274       zone(), function, kArity, Operator::kNoProperties,
    275       CallDescriptor::kSupportsTailCalls);
    276   int return_count = static_cast<int>(desc->ReturnCount());
    277 
    278   Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
    279   Node* ref = AddNode(
    280       common()->ExternalConstant(ExternalReference(function, isolate())));
    281   Node* arity = Int32Constant(kArity);
    282 
    283   Node* nodes[] = {centry, ref, arity, context};
    284   Node* tail_call = MakeNode(common()->TailCall(desc), arraysize(nodes), nodes);
    285 
    286   schedule()->AddTailCall(CurrentBlock(), tail_call);
    287   current_block_ = nullptr;
    288   return tail_call;
    289 }
    290 
    291 Node* RawMachineAssembler::TailCallRuntime1(Runtime::FunctionId function,
    292                                             Node* arg1, Node* context) {
    293   const int kArity = 1;
    294   CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
    295       zone(), function, kArity, Operator::kNoProperties,
    296       CallDescriptor::kSupportsTailCalls);
    297   int return_count = static_cast<int>(desc->ReturnCount());
    298 
    299   Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
    300   Node* ref = AddNode(
    301       common()->ExternalConstant(ExternalReference(function, isolate())));
    302   Node* arity = Int32Constant(kArity);
    303 
    304   Node* nodes[] = {centry, arg1, ref, arity, context};
    305   Node* tail_call = MakeNode(common()->TailCall(desc), arraysize(nodes), nodes);
    306 
    307   schedule()->AddTailCall(CurrentBlock(), tail_call);
    308   current_block_ = nullptr;
    309   return tail_call;
    310 }
    311 
    312 
    313 Node* RawMachineAssembler::TailCallRuntime2(Runtime::FunctionId function,
    314                                             Node* arg1, Node* arg2,
    315                                             Node* context) {
    316   const int kArity = 2;
    317   CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
    318       zone(), function, kArity, Operator::kNoProperties,
    319       CallDescriptor::kSupportsTailCalls);
    320   int return_count = static_cast<int>(desc->ReturnCount());
    321 
    322   Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
    323   Node* ref = AddNode(
    324       common()->ExternalConstant(ExternalReference(function, isolate())));
    325   Node* arity = Int32Constant(kArity);
    326 
    327   Node* nodes[] = {centry, arg1, arg2, ref, arity, context};
    328   Node* tail_call = MakeNode(common()->TailCall(desc), arraysize(nodes), nodes);
    329 
    330   schedule()->AddTailCall(CurrentBlock(), tail_call);
    331   current_block_ = nullptr;
    332   return tail_call;
    333 }
    334 
    335 Node* RawMachineAssembler::TailCallRuntime3(Runtime::FunctionId function,
    336                                             Node* arg1, Node* arg2, Node* arg3,
    337                                             Node* context) {
    338   const int kArity = 3;
    339   CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
    340       zone(), function, kArity, Operator::kNoProperties,
    341       CallDescriptor::kSupportsTailCalls);
    342   int return_count = static_cast<int>(desc->ReturnCount());
    343 
    344   Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
    345   Node* ref = AddNode(
    346       common()->ExternalConstant(ExternalReference(function, isolate())));
    347   Node* arity = Int32Constant(kArity);
    348 
    349   Node* nodes[] = {centry, arg1, arg2, arg3, ref, arity, context};
    350   Node* tail_call = MakeNode(common()->TailCall(desc), arraysize(nodes), nodes);
    351 
    352   schedule()->AddTailCall(CurrentBlock(), tail_call);
    353   current_block_ = nullptr;
    354   return tail_call;
    355 }
    356 
    357 Node* RawMachineAssembler::TailCallRuntime4(Runtime::FunctionId function,
    358                                             Node* arg1, Node* arg2, Node* arg3,
    359                                             Node* arg4, Node* context) {
    360   const int kArity = 4;
    361   CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
    362       zone(), function, kArity, Operator::kNoProperties,
    363       CallDescriptor::kSupportsTailCalls);
    364   int return_count = static_cast<int>(desc->ReturnCount());
    365 
    366   Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
    367   Node* ref = AddNode(
    368       common()->ExternalConstant(ExternalReference(function, isolate())));
    369   Node* arity = Int32Constant(kArity);
    370 
    371   Node* nodes[] = {centry, arg1, arg2, arg3, arg4, ref, arity, context};
    372   Node* tail_call = MakeNode(common()->TailCall(desc), arraysize(nodes), nodes);
    373 
    374   schedule()->AddTailCall(CurrentBlock(), tail_call);
    375   current_block_ = nullptr;
    376   return tail_call;
    377 }
    378 
    379 Node* RawMachineAssembler::CallCFunction0(MachineType return_type,
    380                                           Node* function) {
    381   MachineSignature::Builder builder(zone(), 1, 0);
    382   builder.AddReturn(return_type);
    383   const CallDescriptor* descriptor =
    384       Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
    385 
    386   return AddNode(common()->Call(descriptor), function);
    387 }
    388 
    389 
    390 Node* RawMachineAssembler::CallCFunction1(MachineType return_type,
    391                                           MachineType arg0_type, Node* function,
    392                                           Node* arg0) {
    393   MachineSignature::Builder builder(zone(), 1, 1);
    394   builder.AddReturn(return_type);
    395   builder.AddParam(arg0_type);
    396   const CallDescriptor* descriptor =
    397       Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
    398 
    399   return AddNode(common()->Call(descriptor), function, arg0);
    400 }
    401 
    402 
    403 Node* RawMachineAssembler::CallCFunction2(MachineType return_type,
    404                                           MachineType arg0_type,
    405                                           MachineType arg1_type, Node* function,
    406                                           Node* arg0, Node* arg1) {
    407   MachineSignature::Builder builder(zone(), 1, 2);
    408   builder.AddReturn(return_type);
    409   builder.AddParam(arg0_type);
    410   builder.AddParam(arg1_type);
    411   const CallDescriptor* descriptor =
    412       Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
    413 
    414   return AddNode(common()->Call(descriptor), function, arg0, arg1);
    415 }
    416 
    417 
    418 Node* RawMachineAssembler::CallCFunction8(
    419     MachineType return_type, MachineType arg0_type, MachineType arg1_type,
    420     MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
    421     MachineType arg5_type, MachineType arg6_type, MachineType arg7_type,
    422     Node* function, Node* arg0, Node* arg1, Node* arg2, Node* arg3, Node* arg4,
    423     Node* arg5, Node* arg6, Node* arg7) {
    424   MachineSignature::Builder builder(zone(), 1, 8);
    425   builder.AddReturn(return_type);
    426   builder.AddParam(arg0_type);
    427   builder.AddParam(arg1_type);
    428   builder.AddParam(arg2_type);
    429   builder.AddParam(arg3_type);
    430   builder.AddParam(arg4_type);
    431   builder.AddParam(arg5_type);
    432   builder.AddParam(arg6_type);
    433   builder.AddParam(arg7_type);
    434   Node* args[] = {function, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7};
    435   const CallDescriptor* descriptor =
    436       Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
    437   return AddNode(common()->Call(descriptor), arraysize(args), args);
    438 }
    439 
    440 
    441 void RawMachineAssembler::Bind(RawMachineLabel* label) {
    442   DCHECK(current_block_ == nullptr);
    443   DCHECK(!label->bound_);
    444   label->bound_ = true;
    445   current_block_ = EnsureBlock(label);
    446   current_block_->set_deferred(label->deferred_);
    447 }
    448 
    449 
    450 BasicBlock* RawMachineAssembler::Use(RawMachineLabel* label) {
    451   label->used_ = true;
    452   return EnsureBlock(label);
    453 }
    454 
    455 
    456 BasicBlock* RawMachineAssembler::EnsureBlock(RawMachineLabel* label) {
    457   if (label->block_ == nullptr) label->block_ = schedule()->NewBasicBlock();
    458   return label->block_;
    459 }
    460 
    461 
    462 BasicBlock* RawMachineAssembler::CurrentBlock() {
    463   DCHECK(current_block_);
    464   return current_block_;
    465 }
    466 
    467 Node* RawMachineAssembler::Phi(MachineRepresentation rep, int input_count,
    468                                Node* const* inputs) {
    469   Node** buffer = new (zone()->New(sizeof(Node*) * (input_count + 1)))
    470       Node*[input_count + 1];
    471   std::copy(inputs, inputs + input_count, buffer);
    472   buffer[input_count] = graph()->start();
    473   return AddNode(common()->Phi(rep, input_count), input_count + 1, buffer);
    474 }
    475 
    476 void RawMachineAssembler::AppendPhiInput(Node* phi, Node* new_input) {
    477   const Operator* op = phi->op();
    478   const Operator* new_op = common()->ResizeMergeOrPhi(op, phi->InputCount());
    479   phi->InsertInput(zone(), phi->InputCount() - 1, new_input);
    480   NodeProperties::ChangeOp(phi, new_op);
    481 }
    482 
    483 Node* RawMachineAssembler::AddNode(const Operator* op, int input_count,
    484                                    Node* const* inputs) {
    485   DCHECK_NOT_NULL(schedule_);
    486   DCHECK_NOT_NULL(current_block_);
    487   Node* node = MakeNode(op, input_count, inputs);
    488   schedule()->AddNode(CurrentBlock(), node);
    489   return node;
    490 }
    491 
    492 Node* RawMachineAssembler::MakeNode(const Operator* op, int input_count,
    493                                     Node* const* inputs) {
    494   // The raw machine assembler nodes do not have effect and control inputs,
    495   // so we disable checking input counts here.
    496   return graph()->NewNodeUnchecked(op, input_count, inputs);
    497 }
    498 
    499 RawMachineLabel::~RawMachineLabel() { DCHECK(bound_ || !used_); }
    500 
    501 }  // namespace compiler
    502 }  // namespace internal
    503 }  // namespace v8
    504