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/common-operator.h"
      6 #include "src/compiler/graph.h"
      7 #include "src/compiler/js-operator.h"
      8 #include "src/compiler/linkage.h"
      9 #include "src/compiler/node-properties.h"
     10 #include "src/compiler/operator-properties.h"
     11 #include "src/compiler/verifier.h"
     12 #include "src/handles-inl.h"
     13 
     14 namespace v8 {
     15 namespace internal {
     16 namespace compiler {
     17 
     18 // static
     19 int NodeProperties::PastValueIndex(Node* node) {
     20   return FirstValueIndex(node) + node->op()->ValueInputCount();
     21 }
     22 
     23 
     24 // static
     25 int NodeProperties::PastContextIndex(Node* node) {
     26   return FirstContextIndex(node) +
     27          OperatorProperties::GetContextInputCount(node->op());
     28 }
     29 
     30 
     31 // static
     32 int NodeProperties::PastFrameStateIndex(Node* node) {
     33   return FirstFrameStateIndex(node) +
     34          OperatorProperties::GetFrameStateInputCount(node->op());
     35 }
     36 
     37 
     38 // static
     39 int NodeProperties::PastEffectIndex(Node* node) {
     40   return FirstEffectIndex(node) + node->op()->EffectInputCount();
     41 }
     42 
     43 
     44 // static
     45 int NodeProperties::PastControlIndex(Node* node) {
     46   return FirstControlIndex(node) + node->op()->ControlInputCount();
     47 }
     48 
     49 
     50 // static
     51 Node* NodeProperties::GetValueInput(Node* node, int index) {
     52   DCHECK(0 <= index && index < node->op()->ValueInputCount());
     53   return node->InputAt(FirstValueIndex(node) + index);
     54 }
     55 
     56 
     57 // static
     58 Node* NodeProperties::GetContextInput(Node* node) {
     59   DCHECK(OperatorProperties::HasContextInput(node->op()));
     60   return node->InputAt(FirstContextIndex(node));
     61 }
     62 
     63 
     64 // static
     65 Node* NodeProperties::GetFrameStateInput(Node* node) {
     66   DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
     67   return node->InputAt(FirstFrameStateIndex(node));
     68 }
     69 
     70 
     71 // static
     72 Node* NodeProperties::GetEffectInput(Node* node, int index) {
     73   DCHECK(0 <= index && index < node->op()->EffectInputCount());
     74   return node->InputAt(FirstEffectIndex(node) + index);
     75 }
     76 
     77 
     78 // static
     79 Node* NodeProperties::GetControlInput(Node* node, int index) {
     80   DCHECK(0 <= index && index < node->op()->ControlInputCount());
     81   return node->InputAt(FirstControlIndex(node) + index);
     82 }
     83 
     84 
     85 // static
     86 bool NodeProperties::IsValueEdge(Edge edge) {
     87   Node* const node = edge.from();
     88   return IsInputRange(edge, FirstValueIndex(node),
     89                       node->op()->ValueInputCount());
     90 }
     91 
     92 
     93 // static
     94 bool NodeProperties::IsContextEdge(Edge edge) {
     95   Node* const node = edge.from();
     96   return IsInputRange(edge, FirstContextIndex(node),
     97                       OperatorProperties::GetContextInputCount(node->op()));
     98 }
     99 
    100 
    101 // static
    102 bool NodeProperties::IsFrameStateEdge(Edge edge) {
    103   Node* const node = edge.from();
    104   return IsInputRange(edge, FirstFrameStateIndex(node),
    105                       OperatorProperties::GetFrameStateInputCount(node->op()));
    106 }
    107 
    108 
    109 // static
    110 bool NodeProperties::IsEffectEdge(Edge edge) {
    111   Node* const node = edge.from();
    112   return IsInputRange(edge, FirstEffectIndex(node),
    113                       node->op()->EffectInputCount());
    114 }
    115 
    116 
    117 // static
    118 bool NodeProperties::IsControlEdge(Edge edge) {
    119   Node* const node = edge.from();
    120   return IsInputRange(edge, FirstControlIndex(node),
    121                       node->op()->ControlInputCount());
    122 }
    123 
    124 
    125 // static
    126 bool NodeProperties::IsExceptionalCall(Node* node) {
    127   if (node->op()->HasProperty(Operator::kNoThrow)) return false;
    128   for (Edge const edge : node->use_edges()) {
    129     if (!NodeProperties::IsControlEdge(edge)) continue;
    130     if (edge.from()->opcode() == IrOpcode::kIfException) return true;
    131   }
    132   return false;
    133 }
    134 
    135 
    136 // static
    137 void NodeProperties::ReplaceValueInput(Node* node, Node* value, int index) {
    138   DCHECK(index < node->op()->ValueInputCount());
    139   node->ReplaceInput(FirstValueIndex(node) + index, value);
    140 }
    141 
    142 
    143 // static
    144 void NodeProperties::ReplaceValueInputs(Node* node, Node* value) {
    145   int value_input_count = node->op()->ValueInputCount();
    146   DCHECK_LE(1, value_input_count);
    147   node->ReplaceInput(0, value);
    148   while (--value_input_count > 0) {
    149     node->RemoveInput(value_input_count);
    150   }
    151 }
    152 
    153 
    154 // static
    155 void NodeProperties::ReplaceContextInput(Node* node, Node* context) {
    156   node->ReplaceInput(FirstContextIndex(node), context);
    157 }
    158 
    159 
    160 // static
    161 void NodeProperties::ReplaceControlInput(Node* node, Node* control, int index) {
    162   DCHECK(index < node->op()->ControlInputCount());
    163   node->ReplaceInput(FirstControlIndex(node) + index, control);
    164 }
    165 
    166 
    167 // static
    168 void NodeProperties::ReplaceEffectInput(Node* node, Node* effect, int index) {
    169   DCHECK(index < node->op()->EffectInputCount());
    170   return node->ReplaceInput(FirstEffectIndex(node) + index, effect);
    171 }
    172 
    173 
    174 // static
    175 void NodeProperties::ReplaceFrameStateInput(Node* node, Node* frame_state) {
    176   DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
    177   node->ReplaceInput(FirstFrameStateIndex(node), frame_state);
    178 }
    179 
    180 
    181 // static
    182 void NodeProperties::RemoveNonValueInputs(Node* node) {
    183   node->TrimInputCount(node->op()->ValueInputCount());
    184 }
    185 
    186 
    187 // static
    188 void NodeProperties::RemoveValueInputs(Node* node) {
    189   int value_input_count = node->op()->ValueInputCount();
    190   while (--value_input_count >= 0) {
    191     node->RemoveInput(value_input_count);
    192   }
    193 }
    194 
    195 
    196 void NodeProperties::MergeControlToEnd(Graph* graph,
    197                                        CommonOperatorBuilder* common,
    198                                        Node* node) {
    199   graph->end()->AppendInput(graph->zone(), node);
    200   graph->end()->set_op(common->End(graph->end()->InputCount()));
    201 }
    202 
    203 
    204 // static
    205 void NodeProperties::ReplaceUses(Node* node, Node* value, Node* effect,
    206                                  Node* success, Node* exception) {
    207   // Requires distinguishing between value, effect and control edges.
    208   for (Edge edge : node->use_edges()) {
    209     if (IsControlEdge(edge)) {
    210       if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
    211         DCHECK_NOT_NULL(success);
    212         edge.UpdateTo(success);
    213       } else if (edge.from()->opcode() == IrOpcode::kIfException) {
    214         DCHECK_NOT_NULL(exception);
    215         edge.UpdateTo(exception);
    216       } else {
    217         DCHECK_NOT_NULL(success);
    218         edge.UpdateTo(success);
    219       }
    220     } else if (IsEffectEdge(edge)) {
    221       DCHECK_NOT_NULL(effect);
    222       edge.UpdateTo(effect);
    223     } else {
    224       DCHECK_NOT_NULL(value);
    225       edge.UpdateTo(value);
    226     }
    227   }
    228 }
    229 
    230 
    231 // static
    232 void NodeProperties::ChangeOp(Node* node, const Operator* new_op) {
    233   node->set_op(new_op);
    234   Verifier::VerifyNode(node);
    235 }
    236 
    237 
    238 // static
    239 Node* NodeProperties::FindFrameStateBefore(Node* node) {
    240   Node* effect = NodeProperties::GetEffectInput(node);
    241   while (effect->opcode() != IrOpcode::kCheckpoint) {
    242     if (effect->opcode() == IrOpcode::kDead) return effect;
    243     DCHECK_EQ(1, effect->op()->EffectInputCount());
    244     effect = NodeProperties::GetEffectInput(effect);
    245   }
    246   Node* frame_state = GetFrameStateInput(effect);
    247   return frame_state;
    248 }
    249 
    250 // static
    251 Node* NodeProperties::FindProjection(Node* node, size_t projection_index) {
    252   for (auto use : node->uses()) {
    253     if (use->opcode() == IrOpcode::kProjection &&
    254         ProjectionIndexOf(use->op()) == projection_index) {
    255       return use;
    256     }
    257   }
    258   return nullptr;
    259 }
    260 
    261 
    262 // static
    263 void NodeProperties::CollectControlProjections(Node* node, Node** projections,
    264                                                size_t projection_count) {
    265 #ifdef DEBUG
    266   DCHECK_LE(static_cast<int>(projection_count), node->UseCount());
    267   std::memset(projections, 0, sizeof(*projections) * projection_count);
    268 #endif
    269   size_t if_value_index = 0;
    270   for (Edge const edge : node->use_edges()) {
    271     if (!IsControlEdge(edge)) continue;
    272     Node* use = edge.from();
    273     size_t index;
    274     switch (use->opcode()) {
    275       case IrOpcode::kIfTrue:
    276         DCHECK_EQ(IrOpcode::kBranch, node->opcode());
    277         index = 0;
    278         break;
    279       case IrOpcode::kIfFalse:
    280         DCHECK_EQ(IrOpcode::kBranch, node->opcode());
    281         index = 1;
    282         break;
    283       case IrOpcode::kIfSuccess:
    284         DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
    285         index = 0;
    286         break;
    287       case IrOpcode::kIfException:
    288         DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
    289         index = 1;
    290         break;
    291       case IrOpcode::kIfValue:
    292         DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
    293         index = if_value_index++;
    294         break;
    295       case IrOpcode::kIfDefault:
    296         DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
    297         index = projection_count - 1;
    298         break;
    299       default:
    300         continue;
    301     }
    302     DCHECK_LT(if_value_index, projection_count);
    303     DCHECK_LT(index, projection_count);
    304     DCHECK_NULL(projections[index]);
    305     projections[index] = use;
    306   }
    307 #ifdef DEBUG
    308   for (size_t index = 0; index < projection_count; ++index) {
    309     DCHECK_NOT_NULL(projections[index]);
    310   }
    311 #endif
    312 }
    313 
    314 
    315 // static
    316 MaybeHandle<Context> NodeProperties::GetSpecializationContext(
    317     Node* node, MaybeHandle<Context> context) {
    318   switch (node->opcode()) {
    319     case IrOpcode::kHeapConstant:
    320       return Handle<Context>::cast(OpParameter<Handle<HeapObject>>(node));
    321     case IrOpcode::kParameter: {
    322       Node* const start = NodeProperties::GetValueInput(node, 0);
    323       DCHECK_EQ(IrOpcode::kStart, start->opcode());
    324       int const index = ParameterIndexOf(node->op());
    325       // The context is always the last parameter to a JavaScript function, and
    326       // {Parameter} indices start at -1, so value outputs of {Start} look like
    327       // this: closure, receiver, param0, ..., paramN, context.
    328       if (index == start->op()->ValueOutputCount() - 2) {
    329         return context;
    330       }
    331       break;
    332     }
    333     default:
    334       break;
    335   }
    336   return MaybeHandle<Context>();
    337 }
    338 
    339 
    340 // static
    341 Type* NodeProperties::GetTypeOrAny(Node* node) {
    342   return IsTyped(node) ? node->type() : Type::Any();
    343 }
    344 
    345 
    346 // static
    347 bool NodeProperties::AllValueInputsAreTyped(Node* node) {
    348   int input_count = node->op()->ValueInputCount();
    349   for (int index = 0; index < input_count; ++index) {
    350     if (!IsTyped(GetValueInput(node, index))) return false;
    351   }
    352   return true;
    353 }
    354 
    355 
    356 // static
    357 bool NodeProperties::IsInputRange(Edge edge, int first, int num) {
    358   if (num == 0) return false;
    359   int const index = edge.index();
    360   return first <= index && index < first + num;
    361 }
    362 
    363 }  // namespace compiler
    364 }  // namespace internal
    365 }  // namespace v8
    366