Home | History | Annotate | Download | only in compiler
      1 // Copyright 2017 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/js-type-hint-lowering.h"
      6 
      7 #include "src/compiler/js-graph.h"
      8 #include "src/compiler/operator-properties.h"
      9 #include "src/compiler/simplified-operator.h"
     10 #include "src/feedback-vector.h"
     11 #include "src/type-hints.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 namespace compiler {
     16 
     17 class JSSpeculativeBinopBuilder final {
     18  public:
     19   JSSpeculativeBinopBuilder(JSTypeHintLowering* lowering, const Operator* op,
     20                             Node* left, Node* right, Node* effect,
     21                             Node* control, FeedbackSlot slot)
     22       : lowering_(lowering),
     23         op_(op),
     24         left_(left),
     25         right_(right),
     26         effect_(effect),
     27         control_(control),
     28         slot_(slot) {}
     29 
     30   BinaryOperationHint GetBinaryOperationHint() {
     31     DCHECK_EQ(FeedbackSlotKind::kBinaryOp, feedback_vector()->GetKind(slot_));
     32     BinaryOpICNexus nexus(feedback_vector(), slot_);
     33     return nexus.GetBinaryOperationFeedback();
     34   }
     35 
     36   bool GetBinaryNumberOperationHint(NumberOperationHint* hint) {
     37     switch (GetBinaryOperationHint()) {
     38       case BinaryOperationHint::kSignedSmall:
     39         *hint = NumberOperationHint::kSignedSmall;
     40         return true;
     41       case BinaryOperationHint::kSigned32:
     42         *hint = NumberOperationHint::kSigned32;
     43         return true;
     44       case BinaryOperationHint::kNumberOrOddball:
     45         *hint = NumberOperationHint::kNumberOrOddball;
     46         return true;
     47       case BinaryOperationHint::kAny:
     48       case BinaryOperationHint::kNone:
     49       case BinaryOperationHint::kString:
     50         break;
     51     }
     52     return false;
     53   }
     54 
     55   const Operator* SpeculativeNumberOp(NumberOperationHint hint) {
     56     switch (op_->opcode()) {
     57       case IrOpcode::kJSAdd:
     58         return simplified()->SpeculativeNumberAdd(hint);
     59       case IrOpcode::kJSSubtract:
     60         return simplified()->SpeculativeNumberSubtract(hint);
     61       case IrOpcode::kJSMultiply:
     62         return simplified()->SpeculativeNumberMultiply(hint);
     63       case IrOpcode::kJSDivide:
     64         return simplified()->SpeculativeNumberDivide(hint);
     65       case IrOpcode::kJSModulus:
     66         return simplified()->SpeculativeNumberModulus(hint);
     67       case IrOpcode::kJSBitwiseAnd:
     68         return simplified()->SpeculativeNumberBitwiseAnd(hint);
     69       case IrOpcode::kJSBitwiseOr:
     70         return simplified()->SpeculativeNumberBitwiseOr(hint);
     71       case IrOpcode::kJSBitwiseXor:
     72         return simplified()->SpeculativeNumberBitwiseXor(hint);
     73       case IrOpcode::kJSShiftLeft:
     74         return simplified()->SpeculativeNumberShiftLeft(hint);
     75       case IrOpcode::kJSShiftRight:
     76         return simplified()->SpeculativeNumberShiftRight(hint);
     77       case IrOpcode::kJSShiftRightLogical:
     78         return simplified()->SpeculativeNumberShiftRightLogical(hint);
     79       default:
     80         break;
     81     }
     82     UNREACHABLE();
     83     return nullptr;
     84   }
     85 
     86   Node* BuildSpeculativeOperator(const Operator* op) {
     87     DCHECK_EQ(2, op->ValueInputCount());
     88     DCHECK_EQ(1, op->EffectInputCount());
     89     DCHECK_EQ(1, op->ControlInputCount());
     90     DCHECK_EQ(false, OperatorProperties::HasFrameStateInput(op));
     91     DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
     92     DCHECK_EQ(1, op->EffectOutputCount());
     93     DCHECK_EQ(0, op->ControlOutputCount());
     94     return graph()->NewNode(op, left_, right_, effect_, control_);
     95   }
     96 
     97   JSGraph* jsgraph() const { return lowering_->jsgraph(); }
     98   Graph* graph() const { return jsgraph()->graph(); }
     99   JSOperatorBuilder* javascript() { return jsgraph()->javascript(); }
    100   SimplifiedOperatorBuilder* simplified() { return jsgraph()->simplified(); }
    101   CommonOperatorBuilder* common() { return jsgraph()->common(); }
    102   const Handle<FeedbackVector>& feedback_vector() const {
    103     return lowering_->feedback_vector();
    104   }
    105 
    106  private:
    107   JSTypeHintLowering* lowering_;
    108   const Operator* op_;
    109   Node* left_;
    110   Node* right_;
    111   Node* effect_;
    112   Node* control_;
    113   FeedbackSlot slot_;
    114 };
    115 
    116 JSTypeHintLowering::JSTypeHintLowering(JSGraph* jsgraph,
    117                                        Handle<FeedbackVector> feedback_vector)
    118     : jsgraph_(jsgraph), feedback_vector_(feedback_vector) {}
    119 
    120 Reduction JSTypeHintLowering::ReduceBinaryOperation(const Operator* op,
    121                                                     Node* left, Node* right,
    122                                                     Node* effect, Node* control,
    123                                                     FeedbackSlot slot) {
    124   switch (op->opcode()) {
    125     case IrOpcode::kJSBitwiseOr:
    126     case IrOpcode::kJSBitwiseXor:
    127     case IrOpcode::kJSBitwiseAnd:
    128     case IrOpcode::kJSShiftLeft:
    129     case IrOpcode::kJSShiftRight:
    130     case IrOpcode::kJSShiftRightLogical:
    131     case IrOpcode::kJSAdd:
    132     case IrOpcode::kJSSubtract:
    133     case IrOpcode::kJSMultiply:
    134     case IrOpcode::kJSDivide:
    135     case IrOpcode::kJSModulus: {
    136       JSSpeculativeBinopBuilder b(this, op, left, right, effect, control, slot);
    137       NumberOperationHint hint;
    138       if (b.GetBinaryNumberOperationHint(&hint)) {
    139         Node* node = b.BuildSpeculativeOperator(b.SpeculativeNumberOp(hint));
    140         return Reduction(node);
    141       }
    142       break;
    143     }
    144     default:
    145       UNREACHABLE();
    146       break;
    147   }
    148   return Reduction();
    149 }
    150 
    151 }  // namespace compiler
    152 }  // namespace internal
    153 }  // namespace v8
    154