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/common-operator.h"
      6 
      7 #include "src/assembler.h"
      8 #include "src/base/lazy-instance.h"
      9 #include "src/compiler/linkage.h"
     10 #include "src/unique.h"
     11 #include "src/zone.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 namespace compiler {
     16 
     17 namespace {
     18 
     19 // TODO(turbofan): Use size_t instead of int here.
     20 class ControlOperator : public Operator1<int> {
     21  public:
     22   ControlOperator(IrOpcode::Value opcode, Properties properties, int inputs,
     23                   int outputs, int controls, const char* mnemonic)
     24       : Operator1<int>(opcode, properties, inputs, outputs, mnemonic,
     25                        controls) {}
     26 
     27   virtual OStream& PrintParameter(OStream& os) const FINAL { return os; }
     28 };
     29 
     30 }  // namespace
     31 
     32 
     33 // Specialization for static parameters of type {ExternalReference}.
     34 template <>
     35 struct StaticParameterTraits<ExternalReference> {
     36   static OStream& PrintTo(OStream& os, ExternalReference reference) {
     37     os << reference.address();
     38     // TODO(bmeurer): Move to operator<<(os, ExternalReference)
     39     const Runtime::Function* function =
     40         Runtime::FunctionForEntry(reference.address());
     41     if (function) {
     42       os << " <" << function->name << ".entry>";
     43     }
     44     return os;
     45   }
     46   static int HashCode(ExternalReference reference) {
     47     return bit_cast<int>(static_cast<uint32_t>(
     48         reinterpret_cast<uintptr_t>(reference.address())));
     49   }
     50   static bool Equals(ExternalReference lhs, ExternalReference rhs) {
     51     return lhs == rhs;
     52   }
     53 };
     54 
     55 
     56 #define SHARED_OP_LIST(V)               \
     57   V(Dead, Operator::kFoldable, 0, 0)    \
     58   V(End, Operator::kFoldable, 0, 1)     \
     59   V(Branch, Operator::kFoldable, 1, 1)  \
     60   V(IfTrue, Operator::kFoldable, 0, 1)  \
     61   V(IfFalse, Operator::kFoldable, 0, 1) \
     62   V(Throw, Operator::kFoldable, 1, 1)   \
     63   V(Return, Operator::kNoProperties, 1, 1)
     64 
     65 
     66 struct CommonOperatorBuilderImpl FINAL {
     67 #define SHARED(Name, properties, value_input_count, control_input_count)       \
     68   struct Name##Operator FINAL : public ControlOperator {                       \
     69     Name##Operator()                                                           \
     70         : ControlOperator(IrOpcode::k##Name, properties, value_input_count, 0, \
     71                           control_input_count, #Name) {}                       \
     72   };                                                                           \
     73   Name##Operator k##Name##Operator;
     74   SHARED_OP_LIST(SHARED)
     75 #undef SHARED
     76 
     77   struct ControlEffectOperator FINAL : public SimpleOperator {
     78     ControlEffectOperator()
     79         : SimpleOperator(IrOpcode::kControlEffect, Operator::kPure, 0, 0,
     80                          "ControlEffect") {}
     81   };
     82   ControlEffectOperator kControlEffectOperator;
     83 };
     84 
     85 
     86 static base::LazyInstance<CommonOperatorBuilderImpl>::type kImpl =
     87     LAZY_INSTANCE_INITIALIZER;
     88 
     89 
     90 CommonOperatorBuilder::CommonOperatorBuilder(Zone* zone)
     91     : impl_(kImpl.Get()), zone_(zone) {}
     92 
     93 
     94 #define SHARED(Name, properties, value_input_count, control_input_count) \
     95   const Operator* CommonOperatorBuilder::Name() {                        \
     96     return &impl_.k##Name##Operator;                                     \
     97   }
     98 SHARED_OP_LIST(SHARED)
     99 #undef SHARED
    100 
    101 
    102 const Operator* CommonOperatorBuilder::Start(int num_formal_parameters) {
    103   // Outputs are formal parameters, plus context, receiver, and JSFunction.
    104   const int value_output_count = num_formal_parameters + 3;
    105   return new (zone()) ControlOperator(IrOpcode::kStart, Operator::kFoldable, 0,
    106                                       value_output_count, 0, "Start");
    107 }
    108 
    109 
    110 const Operator* CommonOperatorBuilder::Merge(int controls) {
    111   return new (zone()) ControlOperator(IrOpcode::kMerge, Operator::kFoldable, 0,
    112                                       0, controls, "Merge");
    113 }
    114 
    115 
    116 const Operator* CommonOperatorBuilder::Loop(int controls) {
    117   return new (zone()) ControlOperator(IrOpcode::kLoop, Operator::kFoldable, 0,
    118                                       0, controls, "Loop");
    119 }
    120 
    121 
    122 const Operator* CommonOperatorBuilder::Parameter(int index) {
    123   return new (zone()) Operator1<int>(IrOpcode::kParameter, Operator::kPure, 1,
    124                                      1, "Parameter", index);
    125 }
    126 
    127 
    128 const Operator* CommonOperatorBuilder::Int32Constant(int32_t value) {
    129   return new (zone()) Operator1<int32_t>(
    130       IrOpcode::kInt32Constant, Operator::kPure, 0, 1, "Int32Constant", value);
    131 }
    132 
    133 
    134 const Operator* CommonOperatorBuilder::Int64Constant(int64_t value) {
    135   return new (zone()) Operator1<int64_t>(
    136       IrOpcode::kInt64Constant, Operator::kPure, 0, 1, "Int64Constant", value);
    137 }
    138 
    139 
    140 const Operator* CommonOperatorBuilder::Float32Constant(volatile float value) {
    141   return new (zone())
    142       Operator1<float>(IrOpcode::kFloat32Constant, Operator::kPure, 0, 1,
    143                        "Float32Constant", value);
    144 }
    145 
    146 
    147 const Operator* CommonOperatorBuilder::Float64Constant(volatile double value) {
    148   return new (zone())
    149       Operator1<double>(IrOpcode::kFloat64Constant, Operator::kPure, 0, 1,
    150                         "Float64Constant", value);
    151 }
    152 
    153 
    154 const Operator* CommonOperatorBuilder::ExternalConstant(
    155     const ExternalReference& value) {
    156   return new (zone())
    157       Operator1<ExternalReference>(IrOpcode::kExternalConstant, Operator::kPure,
    158                                    0, 1, "ExternalConstant", value);
    159 }
    160 
    161 
    162 const Operator* CommonOperatorBuilder::NumberConstant(volatile double value) {
    163   return new (zone())
    164       Operator1<double>(IrOpcode::kNumberConstant, Operator::kPure, 0, 1,
    165                         "NumberConstant", value);
    166 }
    167 
    168 
    169 const Operator* CommonOperatorBuilder::HeapConstant(
    170     const Unique<Object>& value) {
    171   return new (zone()) Operator1<Unique<Object> >(
    172       IrOpcode::kHeapConstant, Operator::kPure, 0, 1, "HeapConstant", value);
    173 }
    174 
    175 
    176 const Operator* CommonOperatorBuilder::Phi(MachineType type, int arguments) {
    177   DCHECK(arguments > 0);  // Disallow empty phis.
    178   return new (zone()) Operator1<MachineType>(IrOpcode::kPhi, Operator::kPure,
    179                                              arguments, 1, "Phi", type);
    180 }
    181 
    182 
    183 const Operator* CommonOperatorBuilder::EffectPhi(int arguments) {
    184   DCHECK(arguments > 0);  // Disallow empty phis.
    185   return new (zone()) Operator1<int>(IrOpcode::kEffectPhi, Operator::kPure, 0,
    186                                      0, "EffectPhi", arguments);
    187 }
    188 
    189 
    190 const Operator* CommonOperatorBuilder::ControlEffect() {
    191   return &impl_.kControlEffectOperator;
    192 }
    193 
    194 
    195 const Operator* CommonOperatorBuilder::ValueEffect(int arguments) {
    196   DCHECK(arguments > 0);  // Disallow empty value effects.
    197   return new (zone()) SimpleOperator(IrOpcode::kValueEffect, Operator::kPure,
    198                                      arguments, 0, "ValueEffect");
    199 }
    200 
    201 
    202 const Operator* CommonOperatorBuilder::Finish(int arguments) {
    203   DCHECK(arguments > 0);  // Disallow empty finishes.
    204   return new (zone()) Operator1<int>(IrOpcode::kFinish, Operator::kPure, 1, 1,
    205                                      "Finish", arguments);
    206 }
    207 
    208 
    209 const Operator* CommonOperatorBuilder::StateValues(int arguments) {
    210   return new (zone()) Operator1<int>(IrOpcode::kStateValues, Operator::kPure,
    211                                      arguments, 1, "StateValues", arguments);
    212 }
    213 
    214 
    215 const Operator* CommonOperatorBuilder::FrameState(
    216     FrameStateType type, BailoutId bailout_id,
    217     OutputFrameStateCombine state_combine, MaybeHandle<JSFunction> jsfunction) {
    218   return new (zone()) Operator1<FrameStateCallInfo>(
    219       IrOpcode::kFrameState, Operator::kPure, 4, 1, "FrameState",
    220       FrameStateCallInfo(type, bailout_id, state_combine, jsfunction));
    221 }
    222 
    223 
    224 const Operator* CommonOperatorBuilder::Call(const CallDescriptor* descriptor) {
    225   class CallOperator FINAL : public Operator1<const CallDescriptor*> {
    226    public:
    227     // TODO(titzer): Operator still uses int, whereas CallDescriptor uses
    228     // size_t.
    229     CallOperator(const CallDescriptor* descriptor, const char* mnemonic)
    230         : Operator1<const CallDescriptor*>(
    231               IrOpcode::kCall, descriptor->properties(),
    232               static_cast<int>(descriptor->InputCount() +
    233                                descriptor->FrameStateCount()),
    234               static_cast<int>(descriptor->ReturnCount()), mnemonic,
    235               descriptor) {}
    236 
    237     virtual OStream& PrintParameter(OStream& os) const OVERRIDE {
    238       return os << "[" << *parameter() << "]";
    239     }
    240   };
    241   return new (zone()) CallOperator(descriptor, "Call");
    242 }
    243 
    244 
    245 const Operator* CommonOperatorBuilder::Projection(size_t index) {
    246   return new (zone()) Operator1<size_t>(IrOpcode::kProjection, Operator::kPure,
    247                                         1, 1, "Projection", index);
    248 }
    249 
    250 }  // namespace compiler
    251 }  // namespace internal
    252 }  // namespace v8
    253