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/code-factory.h"
      6 #include "src/compiler/pipeline.h"
      7 #include "src/compiler/raw-machine-assembler.h"
      8 #include "src/compiler/scheduler.h"
      9 
     10 namespace v8 {
     11 namespace internal {
     12 namespace compiler {
     13 
     14 RawMachineAssembler::RawMachineAssembler(Graph* graph,
     15                                          MachineSignature* machine_sig,
     16                                          MachineType word)
     17     : GraphBuilder(graph),
     18       schedule_(new (zone()) Schedule(zone())),
     19       machine_(word),
     20       common_(zone()),
     21       machine_sig_(machine_sig),
     22       call_descriptor_(
     23           Linkage::GetSimplifiedCDescriptor(graph->zone(), machine_sig)),
     24       parameters_(NULL),
     25       exit_label_(schedule()->end()),
     26       current_block_(schedule()->start()) {
     27   int param_count = static_cast<int>(parameter_count());
     28   Node* s = graph->NewNode(common_.Start(param_count));
     29   graph->SetStart(s);
     30   if (parameter_count() == 0) return;
     31   parameters_ = zone()->NewArray<Node*>(param_count);
     32   for (size_t i = 0; i < parameter_count(); ++i) {
     33     parameters_[i] =
     34         NewNode(common()->Parameter(static_cast<int>(i)), graph->start());
     35   }
     36 }
     37 
     38 
     39 Schedule* RawMachineAssembler::Export() {
     40   // Compute the correct codegen order.
     41   DCHECK(schedule_->rpo_order()->empty());
     42   Scheduler::ComputeSpecialRPO(schedule_);
     43   // Invalidate MachineAssembler.
     44   Schedule* schedule = schedule_;
     45   schedule_ = NULL;
     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 RawMachineAssembler::Label* RawMachineAssembler::Exit() {
     57   exit_label_.used_ = true;
     58   return &exit_label_;
     59 }
     60 
     61 
     62 void RawMachineAssembler::Goto(Label* label) {
     63   DCHECK(current_block_ != schedule()->end());
     64   schedule()->AddGoto(CurrentBlock(), Use(label));
     65   current_block_ = NULL;
     66 }
     67 
     68 
     69 void RawMachineAssembler::Branch(Node* condition, Label* true_val,
     70                                  Label* false_val) {
     71   DCHECK(current_block_ != schedule()->end());
     72   Node* branch = NewNode(common()->Branch(), condition);
     73   schedule()->AddBranch(CurrentBlock(), branch, Use(true_val), Use(false_val));
     74   current_block_ = NULL;
     75 }
     76 
     77 
     78 void RawMachineAssembler::Return(Node* value) {
     79   schedule()->AddReturn(CurrentBlock(), value);
     80   current_block_ = NULL;
     81 }
     82 
     83 
     84 Node* RawMachineAssembler::CallFunctionStub0(Node* function, Node* receiver,
     85                                              Node* context, Node* frame_state,
     86                                              CallFunctionFlags flags) {
     87   Callable callable = CodeFactory::CallFunction(isolate(), 0, flags);
     88   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
     89       callable.descriptor(), 1, CallDescriptor::kNeedsFrameState, zone());
     90   Node* stub_code = HeapConstant(callable.code());
     91   Node* call = graph()->NewNode(common()->Call(desc), stub_code, function,
     92                                 receiver, context, frame_state);
     93   schedule()->AddNode(CurrentBlock(), call);
     94   return call;
     95 }
     96 
     97 
     98 Node* RawMachineAssembler::CallJS0(Node* function, Node* receiver,
     99                                    Node* context, Node* frame_state) {
    100   CallDescriptor* descriptor = Linkage::GetJSCallDescriptor(1, zone());
    101   Node* call = graph()->NewNode(common()->Call(descriptor), function, receiver,
    102                                 context, frame_state);
    103   schedule()->AddNode(CurrentBlock(), call);
    104   return call;
    105 }
    106 
    107 
    108 Node* RawMachineAssembler::CallRuntime1(Runtime::FunctionId function,
    109                                         Node* arg0, Node* context,
    110                                         Node* frame_state) {
    111   CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
    112       function, 1, Operator::kNoProperties, zone());
    113 
    114   Node* centry = HeapConstant(CEntryStub(isolate(), 1).GetCode());
    115   Node* ref = NewNode(
    116       common()->ExternalConstant(ExternalReference(function, isolate())));
    117   Node* arity = Int32Constant(1);
    118 
    119   Node* call = graph()->NewNode(common()->Call(descriptor), centry, arg0, ref,
    120                                 arity, context, frame_state);
    121   schedule()->AddNode(CurrentBlock(), call);
    122   return call;
    123 }
    124 
    125 
    126 void RawMachineAssembler::Bind(Label* label) {
    127   DCHECK(current_block_ == NULL);
    128   DCHECK(!label->bound_);
    129   label->bound_ = true;
    130   current_block_ = EnsureBlock(label);
    131 }
    132 
    133 
    134 BasicBlock* RawMachineAssembler::Use(Label* label) {
    135   label->used_ = true;
    136   return EnsureBlock(label);
    137 }
    138 
    139 
    140 BasicBlock* RawMachineAssembler::EnsureBlock(Label* label) {
    141   if (label->block_ == NULL) label->block_ = schedule()->NewBasicBlock();
    142   return label->block_;
    143 }
    144 
    145 
    146 BasicBlock* RawMachineAssembler::CurrentBlock() {
    147   DCHECK(current_block_);
    148   return current_block_;
    149 }
    150 
    151 
    152 Node* RawMachineAssembler::MakeNode(const Operator* op, int input_count,
    153                                     Node** inputs) {
    154   DCHECK(ScheduleValid());
    155   DCHECK(current_block_ != NULL);
    156   Node* node = graph()->NewNode(op, input_count, inputs);
    157   BasicBlock* block = op->opcode() == IrOpcode::kParameter ? schedule()->start()
    158                                                            : CurrentBlock();
    159   schedule()->AddNode(block, node);
    160   return node;
    161 }
    162 
    163 }  // namespace compiler
    164 }  // namespace internal
    165 }  // namespace v8
    166