| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2013 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 #ifndef V8_COMPILER_COMMON_OPERATOR_H_ |
| 6 #define V8_COMPILER_COMMON_OPERATOR_H_ |
| 7 |
| 8 #include "src/v8.h" |
| 9 |
| 10 #include "src/assembler.h" |
| 11 #include "src/compiler/linkage.h" |
| 12 #include "src/compiler/opcodes.h" |
| 13 #include "src/compiler/operator.h" |
| 14 #include "src/unique.h" |
| 15 |
| 16 namespace v8 { |
| 17 namespace internal { |
| 18 |
| 19 class OStream; |
| 20 |
| 21 namespace compiler { |
| 22 |
| 23 class ControlOperator: public Operator1<int> { |
| 24 public: |
| 25 ControlOperator(IrOpcode::Value opcode, |
| 26 uint16_t properties, |
| 27 int inputs, |
| 28 int outputs, |
| 29 int controls, |
| 30 const char* mnemonic) |
| 31 : Operator1(opcode, properties, inputs, outputs, mnemonic, controls) {} |
| 32 |
| 33 virtual OStream& PrintParameter(OStream& os) const { return os; } // NOLINT |
| 34 int ControlInputCount() const { return parameter(); } |
| 35 }; |
| 36 |
| 37 class CallOperator: public Operator1<CallDescriptor*> { |
| 38 public: |
| 39 CallOperator(CallDescriptor* descriptor, const char* mnemonic) |
| 40 : Operator1(IrOpcode::kCall, descriptor->properties(), |
| 41 descriptor->InputCount(), descriptor->ReturnCount(), mnemonic, |
| 42 descriptor) {} |
| 43 |
| 44 virtual OStream& PrintParameter(OStream& os) const { // NOLINT |
| 45 return os << "[" << *parameter() << "]"; |
| 46 } |
| 47 }; |
| 48 |
| 49 class FrameStateDescriptor { |
| 50 public: |
| 51 explicit FrameStateDescriptor(BailoutId bailout_id) |
| 52 : bailout_id_(bailout_id) {} |
| 53 |
| 54 BailoutId bailout_id() const { return bailout_id_; } |
| 55 |
| 56 private: |
| 57 BailoutId bailout_id_; |
| 58 }; |
| 59 |
| 60 // Interface for building common operators that can be used at any level of IR, |
| 61 // including JavaScript, mid-level, and low-level. |
| 62 // TODO(titzer): Move the mnemonics into SimpleOperator and Operator1 classes. |
| 63 class CommonOperatorBuilder { |
| 64 public: |
| 65 explicit CommonOperatorBuilder(Zone* zone) : zone_(zone) { } |
| 66 |
| 67 #define CONTROL_OP(name, inputs, controls) \ |
| 68 return new (zone_) ControlOperator(IrOpcode::k##name, Operator::kFoldable, \ |
| 69 inputs, 0, controls, #name); |
| 70 |
| 71 Operator* Start() { CONTROL_OP(Start, 0, 0); } |
| 72 Operator* Dead() { CONTROL_OP(Dead, 0, 0); } |
| 73 Operator* End() { CONTROL_OP(End, 0, 1); } |
| 74 Operator* Branch() { CONTROL_OP(Branch, 1, 1); } |
| 75 Operator* IfTrue() { CONTROL_OP(IfTrue, 0, 1); } |
| 76 Operator* IfFalse() { CONTROL_OP(IfFalse, 0, 1); } |
| 77 Operator* Throw() { CONTROL_OP(Throw, 1, 1); } |
| 78 Operator* LazyDeoptimization() { CONTROL_OP(LazyDeoptimization, 0, 1); } |
| 79 Operator* Continuation() { CONTROL_OP(Continuation, 0, 1); } |
| 80 |
| 81 Operator* Deoptimize() { |
| 82 return new (zone_) |
| 83 ControlOperator(IrOpcode::kDeoptimize, 0, 1, 0, 1, "Deoptimize"); |
| 84 } |
| 85 |
| 86 Operator* Return() { |
| 87 return new(zone_) ControlOperator(IrOpcode::kReturn, 0, 1, 0, 1, "Return"); |
| 88 } |
| 89 |
| 90 Operator* Merge(int controls) { |
| 91 return new(zone_) ControlOperator(IrOpcode::kMerge, |
| 92 Operator::kFoldable, 0, 0, controls, "Merge"); |
| 93 } |
| 94 |
| 95 Operator* Loop(int controls) { |
| 96 return new(zone_) ControlOperator(IrOpcode::kLoop, |
| 97 Operator::kFoldable, 0, 0, controls, "Loop"); |
| 98 } |
| 99 |
| 100 Operator* Parameter(int index) { |
| 101 return new (zone_) Operator1<int>(IrOpcode::kParameter, Operator::kPure, 0, |
| 102 1, "Parameter", index); |
| 103 } |
| 104 Operator* Int32Constant(int32_t value) { |
| 105 return new (zone_) Operator1<int>(IrOpcode::kInt32Constant, Operator::kPure, |
| 106 0, 1, "Int32Constant", value); |
| 107 } |
| 108 Operator* Int64Constant(int64_t value) { |
| 109 return new(zone_) Operator1<int64_t>(IrOpcode::kInt64Constant, |
| 110 Operator::kPure, |
| 111 0, 1, "Int64Constant", value); |
| 112 } |
| 113 Operator* Float64Constant(double value) { |
| 114 return new(zone_) Operator1<double>(IrOpcode::kFloat64Constant, |
| 115 Operator::kPure, |
| 116 0, 1, "Float64Constant", value); |
| 117 } |
| 118 Operator* ExternalConstant(ExternalReference value) { |
| 119 return new(zone_) Operator1<ExternalReference>(IrOpcode::kExternalConstant, |
| 120 Operator::kPure, |
| 121 0, 1, "ExternalConstant", value); |
| 122 } |
| 123 Operator* NumberConstant(double value) { |
| 124 return new(zone_) Operator1<double>(IrOpcode::kNumberConstant, |
| 125 Operator::kPure, |
| 126 0, 1, "NumberConstant", value); |
| 127 } |
| 128 Operator* HeapConstant(PrintableUnique<Object> value) { |
| 129 return new(zone_) Operator1<PrintableUnique<Object> >( |
| 130 IrOpcode::kHeapConstant, |
| 131 Operator::kPure, |
| 132 0, 1, "HeapConstant", value); |
| 133 } |
| 134 Operator* Phi(int arguments) { |
| 135 ASSERT(arguments > 0); // Disallow empty phis. |
| 136 return new (zone_) Operator1<int>(IrOpcode::kPhi, Operator::kPure, |
| 137 arguments, 1, "Phi", arguments); |
| 138 } |
| 139 Operator* EffectPhi(int arguments) { |
| 140 ASSERT(arguments > 0); // Disallow empty phis. |
| 141 return new (zone_) Operator1<int>(IrOpcode::kEffectPhi, Operator::kPure, 0, |
| 142 0, "EffectPhi", arguments); |
| 143 } |
| 144 Operator* FrameState(const FrameStateDescriptor& descriptor) { |
| 145 return new (zone_) Operator1<FrameStateDescriptor>( |
| 146 IrOpcode::kFrameState, Operator::kPure, 0, 1, "FrameState", descriptor); |
| 147 } |
| 148 Operator* Call(CallDescriptor* descriptor) { |
| 149 return new(zone_) CallOperator(descriptor, "Call"); |
| 150 } |
| 151 Operator* Projection(int index) { |
| 152 return new (zone_) Operator1<int>(IrOpcode::kProjection, Operator::kPure, 1, |
| 153 1, "Projection", index); |
| 154 } |
| 155 |
| 156 private: |
| 157 Zone* zone_; |
| 158 }; |
| 159 |
| 160 |
| 161 template <typename T> |
| 162 struct CommonOperatorTraits { |
| 163 static inline bool Equals(T a, T b); |
| 164 static inline bool HasValue(Operator* op); |
| 165 static inline T ValueOf(Operator* op); |
| 166 }; |
| 167 |
| 168 template <> |
| 169 struct CommonOperatorTraits<int32_t> { |
| 170 static inline bool Equals(int32_t a, int32_t b) { |
| 171 return a == b; |
| 172 } |
| 173 static inline bool HasValue(Operator* op) { |
| 174 return op->opcode() == IrOpcode::kInt32Constant || |
| 175 op->opcode() == IrOpcode::kNumberConstant; |
| 176 } |
| 177 static inline int32_t ValueOf(Operator* op) { |
| 178 if (op->opcode() == IrOpcode::kNumberConstant) { |
| 179 // TODO(titzer): cache the converted int32 value in NumberConstant. |
| 180 return FastD2I(reinterpret_cast<Operator1<double>*>(op)->parameter()); |
| 181 } |
| 182 CHECK_EQ(IrOpcode::kInt32Constant, op->opcode()); |
| 183 return static_cast<Operator1<int32_t>*>(op)->parameter(); |
| 184 } |
| 185 }; |
| 186 |
| 187 template <> |
| 188 struct CommonOperatorTraits<uint32_t> { |
| 189 static inline bool Equals(uint32_t a, uint32_t b) { |
| 190 return a == b; |
| 191 } |
| 192 static inline bool HasValue(Operator* op) { |
| 193 return CommonOperatorTraits<int32_t>::HasValue(op); |
| 194 } |
| 195 static inline uint32_t ValueOf(Operator* op) { |
| 196 if (op->opcode() == IrOpcode::kNumberConstant) { |
| 197 // TODO(titzer): cache the converted uint32 value in NumberConstant. |
| 198 return FastD2UI(reinterpret_cast<Operator1<double>*>(op)->parameter()); |
| 199 } |
| 200 return static_cast<uint32_t>(CommonOperatorTraits<int32_t>::ValueOf(op)); |
| 201 } |
| 202 }; |
| 203 |
| 204 template <> |
| 205 struct CommonOperatorTraits<int64_t> { |
| 206 static inline bool Equals(int64_t a, int64_t b) { |
| 207 return a == b; |
| 208 } |
| 209 static inline bool HasValue(Operator* op) { |
| 210 return op->opcode() == IrOpcode::kInt32Constant || |
| 211 op->opcode() == IrOpcode::kInt64Constant || |
| 212 op->opcode() == IrOpcode::kNumberConstant; |
| 213 } |
| 214 static inline int64_t ValueOf(Operator* op) { |
| 215 if (op->opcode() == IrOpcode::kInt32Constant) { |
| 216 return static_cast<int64_t>(CommonOperatorTraits<int32_t>::ValueOf(op)); |
| 217 } |
| 218 CHECK_EQ(IrOpcode::kInt64Constant, op->opcode()); |
| 219 return static_cast<Operator1<int64_t>*>(op)->parameter(); |
| 220 } |
| 221 }; |
| 222 |
| 223 template <> |
| 224 struct CommonOperatorTraits<uint64_t> { |
| 225 static inline bool Equals(uint64_t a, uint64_t b) { |
| 226 return a == b; |
| 227 } |
| 228 static inline bool HasValue(Operator* op) { |
| 229 return CommonOperatorTraits<int64_t>::HasValue(op); |
| 230 } |
| 231 static inline uint64_t ValueOf(Operator* op) { |
| 232 return static_cast<uint64_t>(CommonOperatorTraits<int64_t>::ValueOf(op)); |
| 233 } |
| 234 }; |
| 235 |
| 236 template <> |
| 237 struct CommonOperatorTraits<double> { |
| 238 static inline bool Equals(double a, double b) { |
| 239 return DoubleRepresentation(a).bits == DoubleRepresentation(b).bits; |
| 240 } |
| 241 static inline bool HasValue(Operator* op) { |
| 242 return op->opcode() == IrOpcode::kFloat64Constant || |
| 243 op->opcode() == IrOpcode::kInt32Constant || |
| 244 op->opcode() == IrOpcode::kNumberConstant; |
| 245 } |
| 246 static inline double ValueOf(Operator* op) { |
| 247 if (op->opcode() == IrOpcode::kFloat64Constant || |
| 248 op->opcode() == IrOpcode::kNumberConstant) { |
| 249 return reinterpret_cast<Operator1<double>*>(op)->parameter(); |
| 250 } |
| 251 return static_cast<double>(CommonOperatorTraits<int32_t>::ValueOf(op)); |
| 252 } |
| 253 }; |
| 254 |
| 255 template <> |
| 256 struct CommonOperatorTraits<ExternalReference> { |
| 257 static inline bool Equals(ExternalReference a, ExternalReference b) { |
| 258 return a == b; |
| 259 } |
| 260 static inline bool HasValue(Operator* op) { |
| 261 return op->opcode() == IrOpcode::kExternalConstant; |
| 262 } |
| 263 static inline ExternalReference ValueOf(Operator* op) { |
| 264 CHECK_EQ(IrOpcode::kExternalConstant, op->opcode()); |
| 265 return static_cast<Operator1<ExternalReference>*>(op)->parameter(); |
| 266 } |
| 267 }; |
| 268 |
| 269 template <typename T> |
| 270 struct CommonOperatorTraits<PrintableUnique<T> > { |
| 271 static inline bool HasValue(Operator* op) { |
| 272 return op->opcode() == IrOpcode::kHeapConstant; |
| 273 } |
| 274 static inline PrintableUnique<T> ValueOf(Operator* op) { |
| 275 CHECK_EQ(IrOpcode::kHeapConstant, op->opcode()); |
| 276 return static_cast<Operator1<PrintableUnique<T> >*>(op)->parameter(); |
| 277 } |
| 278 }; |
| 279 |
| 280 template <typename T> |
| 281 struct CommonOperatorTraits<Handle<T> > { |
| 282 static inline bool HasValue(Operator* op) { |
| 283 return CommonOperatorTraits<PrintableUnique<T> >::HasValue(op); |
| 284 } |
| 285 static inline Handle<T> ValueOf(Operator* op) { |
| 286 return CommonOperatorTraits<PrintableUnique<T> >::ValueOf(op).handle(); |
| 287 } |
| 288 }; |
| 289 |
| 290 |
| 291 template <typename T> |
| 292 inline T ValueOf(Operator* op) { |
| 293 return CommonOperatorTraits<T>::ValueOf(op); |
| 294 } |
| 295 |
| 296 } } } // namespace v8::internal::compiler |
| 297 |
| 298 #endif // V8_COMPILER_COMMON_OPERATOR_H_ |
| OLD | NEW |