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/graph-assembler.h"
      6 
      7 #include "src/code-factory.h"
      8 #include "src/compiler/linkage.h"
      9 #include "src/objects-inl.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 namespace compiler {
     14 
     15 GraphAssembler::GraphAssembler(JSGraph* jsgraph, Node* effect, Node* control,
     16                                Zone* zone)
     17     : temp_zone_(zone),
     18       jsgraph_(jsgraph),
     19       current_effect_(effect),
     20       current_control_(control) {}
     21 
     22 Node* GraphAssembler::IntPtrConstant(intptr_t value) {
     23   return jsgraph()->IntPtrConstant(value);
     24 }
     25 
     26 Node* GraphAssembler::Int32Constant(int32_t value) {
     27   return jsgraph()->Int32Constant(value);
     28 }
     29 
     30 Node* GraphAssembler::UniqueInt32Constant(int32_t value) {
     31   return graph()->NewNode(common()->Int32Constant(value));
     32 }
     33 
     34 Node* GraphAssembler::SmiConstant(int32_t value) {
     35   return jsgraph()->SmiConstant(value);
     36 }
     37 
     38 Node* GraphAssembler::Uint32Constant(int32_t value) {
     39   return jsgraph()->Uint32Constant(value);
     40 }
     41 
     42 Node* GraphAssembler::Float64Constant(double value) {
     43   return jsgraph()->Float64Constant(value);
     44 }
     45 
     46 Node* GraphAssembler::HeapConstant(Handle<HeapObject> object) {
     47   return jsgraph()->HeapConstant(object);
     48 }
     49 
     50 
     51 Node* GraphAssembler::ExternalConstant(ExternalReference ref) {
     52   return jsgraph()->ExternalConstant(ref);
     53 }
     54 
     55 Node* GraphAssembler::CEntryStubConstant(int result_size) {
     56   return jsgraph()->CEntryStubConstant(result_size);
     57 }
     58 
     59 #define SINGLETON_CONST_DEF(Name) \
     60   Node* GraphAssembler::Name() { return jsgraph()->Name(); }
     61 JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_DEF)
     62 #undef SINGLETON_CONST_DEF
     63 
     64 #define PURE_UNOP_DEF(Name)                            \
     65   Node* GraphAssembler::Name(Node* input) {            \
     66     return graph()->NewNode(machine()->Name(), input); \
     67   }
     68 PURE_ASSEMBLER_MACH_UNOP_LIST(PURE_UNOP_DEF)
     69 #undef PURE_UNOP_DEF
     70 
     71 #define PURE_BINOP_DEF(Name)                                 \
     72   Node* GraphAssembler::Name(Node* left, Node* right) {      \
     73     return graph()->NewNode(machine()->Name(), left, right); \
     74   }
     75 PURE_ASSEMBLER_MACH_BINOP_LIST(PURE_BINOP_DEF)
     76 #undef PURE_BINOP_DEF
     77 
     78 #define CHECKED_BINOP_DEF(Name)                                                \
     79   Node* GraphAssembler::Name(Node* left, Node* right) {                        \
     80     return graph()->NewNode(machine()->Name(), left, right, current_control_); \
     81   }
     82 CHECKED_ASSEMBLER_MACH_BINOP_LIST(CHECKED_BINOP_DEF)
     83 #undef CHECKED_BINOP_DEF
     84 
     85 Node* GraphAssembler::Float64RoundDown(Node* value) {
     86   if (machine()->Float64RoundDown().IsSupported()) {
     87     return graph()->NewNode(machine()->Float64RoundDown().op(), value);
     88   }
     89   return nullptr;
     90 }
     91 
     92 Node* GraphAssembler::Projection(int index, Node* value) {
     93   return graph()->NewNode(common()->Projection(index), value, current_control_);
     94 }
     95 
     96 Node* GraphAssembler::Allocate(PretenureFlag pretenure, Node* size) {
     97   return current_effect_ =
     98              graph()->NewNode(simplified()->Allocate(NOT_TENURED), size,
     99                               current_effect_, current_control_);
    100 }
    101 
    102 Node* GraphAssembler::LoadField(FieldAccess const& access, Node* object) {
    103   return current_effect_ =
    104              graph()->NewNode(simplified()->LoadField(access), object,
    105                               current_effect_, current_control_);
    106 }
    107 
    108 Node* GraphAssembler::LoadElement(ElementAccess const& access, Node* object,
    109                                   Node* index) {
    110   return current_effect_ =
    111              graph()->NewNode(simplified()->LoadElement(access), object, index,
    112                               current_effect_, current_control_);
    113 }
    114 
    115 Node* GraphAssembler::StoreField(FieldAccess const& access, Node* object,
    116                                  Node* value) {
    117   return current_effect_ =
    118              graph()->NewNode(simplified()->StoreField(access), object, value,
    119                               current_effect_, current_control_);
    120 }
    121 
    122 Node* GraphAssembler::StoreElement(ElementAccess const& access, Node* object,
    123                                    Node* index, Node* value) {
    124   return current_effect_ =
    125              graph()->NewNode(simplified()->StoreElement(access), object, index,
    126                               value, current_effect_, current_control_);
    127 }
    128 
    129 Node* GraphAssembler::Store(StoreRepresentation rep, Node* object, Node* offset,
    130                             Node* value) {
    131   return current_effect_ =
    132              graph()->NewNode(machine()->Store(rep), object, offset, value,
    133                               current_effect_, current_control_);
    134 }
    135 
    136 Node* GraphAssembler::Load(MachineType rep, Node* object, Node* offset) {
    137   return current_effect_ =
    138              graph()->NewNode(machine()->Load(rep), object, offset,
    139                               current_effect_, current_control_);
    140 }
    141 
    142 Node* GraphAssembler::Retain(Node* buffer) {
    143   return current_effect_ =
    144              graph()->NewNode(common()->Retain(), buffer, current_effect_);
    145 }
    146 
    147 Node* GraphAssembler::UnsafePointerAdd(Node* base, Node* external) {
    148   return current_effect_ =
    149              graph()->NewNode(machine()->UnsafePointerAdd(), base, external,
    150                               current_effect_, current_control_);
    151 }
    152 
    153 Node* GraphAssembler::ToNumber(Node* value) {
    154   return current_effect_ =
    155              graph()->NewNode(ToNumberOperator(), ToNumberBuiltinConstant(),
    156                               value, NoContextConstant(), current_effect_);
    157 }
    158 
    159 Node* GraphAssembler::DeoptimizeIf(DeoptimizeReason reason, Node* condition,
    160                                    Node* frame_state) {
    161   return current_control_ = current_effect_ = graph()->NewNode(
    162              common()->DeoptimizeIf(DeoptimizeKind::kEager, reason), condition,
    163              frame_state, current_effect_, current_control_);
    164 }
    165 
    166 Node* GraphAssembler::DeoptimizeUnless(DeoptimizeKind kind,
    167                                        DeoptimizeReason reason, Node* condition,
    168                                        Node* frame_state) {
    169   return current_control_ = current_effect_ = graph()->NewNode(
    170              common()->DeoptimizeUnless(kind, reason), condition, frame_state,
    171              current_effect_, current_control_);
    172 }
    173 
    174 Node* GraphAssembler::DeoptimizeUnless(DeoptimizeReason reason, Node* condition,
    175                                        Node* frame_state) {
    176   return DeoptimizeUnless(DeoptimizeKind::kEager, reason, condition,
    177                           frame_state);
    178 }
    179 
    180 void GraphAssembler::Branch(Node* condition,
    181                             GraphAssemblerStaticLabel<1>* if_true,
    182                             GraphAssemblerStaticLabel<1>* if_false) {
    183   DCHECK_NOT_NULL(current_control_);
    184 
    185   BranchHint hint = BranchHint::kNone;
    186   if (if_true->IsDeferred() != if_false->IsDeferred()) {
    187     hint = if_false->IsDeferred() ? BranchHint::kTrue : BranchHint::kFalse;
    188   }
    189 
    190   Node* branch =
    191       graph()->NewNode(common()->Branch(hint), condition, current_control_);
    192 
    193   current_control_ = graph()->NewNode(common()->IfTrue(), branch);
    194   MergeState(if_true);
    195 
    196   current_control_ = graph()->NewNode(common()->IfFalse(), branch);
    197   MergeState(if_false);
    198 
    199   current_control_ = nullptr;
    200   current_effect_ = nullptr;
    201 }
    202 
    203 // Extractors (should be only used when destructing the assembler.
    204 Node* GraphAssembler::ExtractCurrentControl() {
    205   Node* result = current_control_;
    206   current_control_ = nullptr;
    207   return result;
    208 }
    209 
    210 Node* GraphAssembler::ExtractCurrentEffect() {
    211   Node* result = current_effect_;
    212   current_effect_ = nullptr;
    213   return result;
    214 }
    215 
    216 void GraphAssembler::Reset(Node* effect, Node* control) {
    217   current_effect_ = effect;
    218   current_control_ = control;
    219 }
    220 
    221 Operator const* GraphAssembler::ToNumberOperator() {
    222   if (!to_number_operator_.is_set()) {
    223     Callable callable = CodeFactory::ToNumber(jsgraph()->isolate());
    224     CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    225     CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    226         jsgraph()->isolate(), graph()->zone(), callable.descriptor(), 0, flags,
    227         Operator::kEliminatable);
    228     to_number_operator_.set(common()->Call(desc));
    229   }
    230   return to_number_operator_.get();
    231 }
    232 
    233 Node* GraphAssemblerLabel::PhiAt(size_t index) {
    234   DCHECK(IsBound());
    235   return GetBindingsPtrFor(index)[0];
    236 }
    237 
    238 GraphAssemblerLabel::GraphAssemblerLabel(GraphAssemblerLabelType is_deferred,
    239                                          size_t merge_count, size_t var_count,
    240                                          MachineRepresentation* representations,
    241                                          Zone* zone)
    242     : is_deferred_(is_deferred == GraphAssemblerLabelType::kDeferred),
    243       max_merge_count_(merge_count),
    244       var_count_(var_count) {
    245   effects_ = zone->NewArray<Node*>(MaxMergeCount() + 1);
    246   for (size_t i = 0; i < MaxMergeCount() + 1; i++) {
    247     effects_[i] = nullptr;
    248   }
    249 
    250   controls_ = zone->NewArray<Node*>(MaxMergeCount());
    251   for (size_t i = 0; i < MaxMergeCount(); i++) {
    252     controls_[i] = nullptr;
    253   }
    254 
    255   size_t num_bindings = (MaxMergeCount() + 1) * PhiCount() + 1;
    256   bindings_ = zone->NewArray<Node*>(num_bindings);
    257   for (size_t i = 0; i < num_bindings; i++) {
    258     bindings_[i] = nullptr;
    259   }
    260 
    261   representations_ = zone->NewArray<MachineRepresentation>(PhiCount() + 1);
    262   for (size_t i = 0; i < PhiCount(); i++) {
    263     representations_[i] = representations[i];
    264   }
    265 }
    266 
    267 GraphAssemblerLabel::~GraphAssemblerLabel() {
    268   DCHECK(IsBound() || MergedCount() == 0);
    269 }
    270 
    271 Node** GraphAssemblerLabel::GetBindingsPtrFor(size_t phi_index) {
    272   DCHECK_LT(phi_index, PhiCount());
    273   return &bindings_[phi_index * (MaxMergeCount() + 1)];
    274 }
    275 
    276 void GraphAssemblerLabel::SetBinding(size_t phi_index, size_t merge_index,
    277                                      Node* binding) {
    278   DCHECK_LT(phi_index, PhiCount());
    279   DCHECK_LT(merge_index, MaxMergeCount());
    280   bindings_[phi_index * (MaxMergeCount() + 1) + merge_index] = binding;
    281 }
    282 
    283 MachineRepresentation GraphAssemblerLabel::GetRepresentationFor(
    284     size_t phi_index) {
    285   DCHECK_LT(phi_index, PhiCount());
    286   return representations_[phi_index];
    287 }
    288 
    289 Node** GraphAssemblerLabel::GetControlsPtr() { return controls_; }
    290 
    291 Node** GraphAssemblerLabel::GetEffectsPtr() { return effects_; }
    292 
    293 }  // namespace compiler
    294 }  // namespace internal
    295 }  // namespace v8
    296