| Index: src/compiler/common-operator.h
|
| diff --git a/src/compiler/common-operator.h b/src/compiler/common-operator.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f7f365d4439ba1d27e352437ccff86d20c56d9cd
|
| --- /dev/null
|
| +++ b/src/compiler/common-operator.h
|
| @@ -0,0 +1,285 @@
|
| +// Copyright 2013 the V8 project authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef V8_COMPILER_COMMON_OPERATOR_H_
|
| +#define V8_COMPILER_COMMON_OPERATOR_H_
|
| +
|
| +#include "src/v8.h"
|
| +
|
| +#include "src/assembler.h"
|
| +#include "src/compiler/linkage.h"
|
| +#include "src/compiler/opcodes.h"
|
| +#include "src/compiler/operator.h"
|
| +#include "src/unique.h"
|
| +
|
| +namespace v8 {
|
| +namespace internal {
|
| +
|
| +class OStream;
|
| +
|
| +namespace compiler {
|
| +
|
| +class ControlOperator : public Operator1<int> {
|
| + public:
|
| + ControlOperator(IrOpcode::Value opcode, uint16_t properties, int inputs,
|
| + int outputs, int controls, const char* mnemonic)
|
| + : Operator1(opcode, properties, inputs, outputs, mnemonic, controls) {}
|
| +
|
| + virtual OStream& PrintParameter(OStream& os) const { return os; } // NOLINT
|
| + int ControlInputCount() const { return parameter(); }
|
| +};
|
| +
|
| +class CallOperator : public Operator1<CallDescriptor*> {
|
| + public:
|
| + CallOperator(CallDescriptor* descriptor, const char* mnemonic)
|
| + : Operator1(IrOpcode::kCall, descriptor->properties(),
|
| + descriptor->InputCount(), descriptor->ReturnCount(), mnemonic,
|
| + descriptor) {}
|
| +
|
| + virtual OStream& PrintParameter(OStream& os) const { // NOLINT
|
| + return os << "[" << *parameter() << "]";
|
| + }
|
| +};
|
| +
|
| +class FrameStateDescriptor {
|
| + public:
|
| + explicit FrameStateDescriptor(BailoutId bailout_id)
|
| + : bailout_id_(bailout_id) {}
|
| +
|
| + BailoutId bailout_id() const { return bailout_id_; }
|
| +
|
| + private:
|
| + BailoutId bailout_id_;
|
| +};
|
| +
|
| +// Interface for building common operators that can be used at any level of IR,
|
| +// including JavaScript, mid-level, and low-level.
|
| +// TODO(titzer): Move the mnemonics into SimpleOperator and Operator1 classes.
|
| +class CommonOperatorBuilder {
|
| + public:
|
| + explicit CommonOperatorBuilder(Zone* zone) : zone_(zone) {}
|
| +
|
| +#define CONTROL_OP(name, inputs, controls) \
|
| + return new (zone_) ControlOperator(IrOpcode::k##name, Operator::kFoldable, \
|
| + inputs, 0, controls, #name);
|
| +
|
| + Operator* Start() { CONTROL_OP(Start, 0, 0); }
|
| + Operator* Dead() { CONTROL_OP(Dead, 0, 0); }
|
| + Operator* End() { CONTROL_OP(End, 0, 1); }
|
| + Operator* Branch() { CONTROL_OP(Branch, 1, 1); }
|
| + Operator* IfTrue() { CONTROL_OP(IfTrue, 0, 1); }
|
| + Operator* IfFalse() { CONTROL_OP(IfFalse, 0, 1); }
|
| + Operator* Throw() { CONTROL_OP(Throw, 1, 1); }
|
| + Operator* LazyDeoptimization() { CONTROL_OP(LazyDeoptimization, 0, 1); }
|
| + Operator* Continuation() { CONTROL_OP(Continuation, 0, 1); }
|
| +
|
| + Operator* Deoptimize() {
|
| + return new (zone_)
|
| + ControlOperator(IrOpcode::kDeoptimize, 0, 1, 0, 1, "Deoptimize");
|
| + }
|
| +
|
| + Operator* Return() {
|
| + return new (zone_) ControlOperator(IrOpcode::kReturn, 0, 1, 0, 1, "Return");
|
| + }
|
| +
|
| + Operator* Merge(int controls) {
|
| + return new (zone_) ControlOperator(IrOpcode::kMerge, Operator::kFoldable, 0,
|
| + 0, controls, "Merge");
|
| + }
|
| +
|
| + Operator* Loop(int controls) {
|
| + return new (zone_) ControlOperator(IrOpcode::kLoop, Operator::kFoldable, 0,
|
| + 0, controls, "Loop");
|
| + }
|
| +
|
| + Operator* Parameter(int index) {
|
| + return new (zone_) Operator1<int>(IrOpcode::kParameter, Operator::kPure, 0,
|
| + 1, "Parameter", index);
|
| + }
|
| + Operator* Int32Constant(int32_t value) {
|
| + return new (zone_) Operator1<int>(IrOpcode::kInt32Constant, Operator::kPure,
|
| + 0, 1, "Int32Constant", value);
|
| + }
|
| + Operator* Int64Constant(int64_t value) {
|
| + return new (zone_)
|
| + Operator1<int64_t>(IrOpcode::kInt64Constant, Operator::kPure, 0, 1,
|
| + "Int64Constant", value);
|
| + }
|
| + Operator* Float64Constant(double value) {
|
| + return new (zone_)
|
| + Operator1<double>(IrOpcode::kFloat64Constant, Operator::kPure, 0, 1,
|
| + "Float64Constant", value);
|
| + }
|
| + Operator* ExternalConstant(ExternalReference value) {
|
| + return new (zone_) Operator1<ExternalReference>(IrOpcode::kExternalConstant,
|
| + Operator::kPure, 0, 1,
|
| + "ExternalConstant", value);
|
| + }
|
| + Operator* NumberConstant(double value) {
|
| + return new (zone_)
|
| + Operator1<double>(IrOpcode::kNumberConstant, Operator::kPure, 0, 1,
|
| + "NumberConstant", value);
|
| + }
|
| + Operator* HeapConstant(PrintableUnique<Object> value) {
|
| + return new (zone_) Operator1<PrintableUnique<Object> >(
|
| + IrOpcode::kHeapConstant, Operator::kPure, 0, 1, "HeapConstant", value);
|
| + }
|
| + Operator* Phi(int arguments) {
|
| + ASSERT(arguments > 0); // Disallow empty phis.
|
| + return new (zone_) Operator1<int>(IrOpcode::kPhi, Operator::kPure,
|
| + arguments, 1, "Phi", arguments);
|
| + }
|
| + Operator* EffectPhi(int arguments) {
|
| + ASSERT(arguments > 0); // Disallow empty phis.
|
| + return new (zone_) Operator1<int>(IrOpcode::kEffectPhi, Operator::kPure, 0,
|
| + 0, "EffectPhi", arguments);
|
| + }
|
| + Operator* FrameState(const FrameStateDescriptor& descriptor) {
|
| + return new (zone_) Operator1<FrameStateDescriptor>(
|
| + IrOpcode::kFrameState, Operator::kPure, 0, 1, "FrameState", descriptor);
|
| + }
|
| + Operator* Call(CallDescriptor* descriptor) {
|
| + return new (zone_) CallOperator(descriptor, "Call");
|
| + }
|
| + Operator* Projection(int index) {
|
| + return new (zone_) Operator1<int>(IrOpcode::kProjection, Operator::kPure, 1,
|
| + 1, "Projection", index);
|
| + }
|
| +
|
| + private:
|
| + Zone* zone_;
|
| +};
|
| +
|
| +
|
| +template <typename T>
|
| +struct CommonOperatorTraits {
|
| + static inline bool Equals(T a, T b);
|
| + static inline bool HasValue(Operator* op);
|
| + static inline T ValueOf(Operator* op);
|
| +};
|
| +
|
| +template <>
|
| +struct CommonOperatorTraits<int32_t> {
|
| + static inline bool Equals(int32_t a, int32_t b) { return a == b; }
|
| + static inline bool HasValue(Operator* op) {
|
| + return op->opcode() == IrOpcode::kInt32Constant ||
|
| + op->opcode() == IrOpcode::kNumberConstant;
|
| + }
|
| + static inline int32_t ValueOf(Operator* op) {
|
| + if (op->opcode() == IrOpcode::kNumberConstant) {
|
| + // TODO(titzer): cache the converted int32 value in NumberConstant.
|
| + return FastD2I(reinterpret_cast<Operator1<double>*>(op)->parameter());
|
| + }
|
| + CHECK_EQ(IrOpcode::kInt32Constant, op->opcode());
|
| + return static_cast<Operator1<int32_t>*>(op)->parameter();
|
| + }
|
| +};
|
| +
|
| +template <>
|
| +struct CommonOperatorTraits<uint32_t> {
|
| + static inline bool Equals(uint32_t a, uint32_t b) { return a == b; }
|
| + static inline bool HasValue(Operator* op) {
|
| + return CommonOperatorTraits<int32_t>::HasValue(op);
|
| + }
|
| + static inline uint32_t ValueOf(Operator* op) {
|
| + if (op->opcode() == IrOpcode::kNumberConstant) {
|
| + // TODO(titzer): cache the converted uint32 value in NumberConstant.
|
| + return FastD2UI(reinterpret_cast<Operator1<double>*>(op)->parameter());
|
| + }
|
| + return static_cast<uint32_t>(CommonOperatorTraits<int32_t>::ValueOf(op));
|
| + }
|
| +};
|
| +
|
| +template <>
|
| +struct CommonOperatorTraits<int64_t> {
|
| + static inline bool Equals(int64_t a, int64_t b) { return a == b; }
|
| + static inline bool HasValue(Operator* op) {
|
| + return op->opcode() == IrOpcode::kInt32Constant ||
|
| + op->opcode() == IrOpcode::kInt64Constant ||
|
| + op->opcode() == IrOpcode::kNumberConstant;
|
| + }
|
| + static inline int64_t ValueOf(Operator* op) {
|
| + if (op->opcode() == IrOpcode::kInt32Constant) {
|
| + return static_cast<int64_t>(CommonOperatorTraits<int32_t>::ValueOf(op));
|
| + }
|
| + CHECK_EQ(IrOpcode::kInt64Constant, op->opcode());
|
| + return static_cast<Operator1<int64_t>*>(op)->parameter();
|
| + }
|
| +};
|
| +
|
| +template <>
|
| +struct CommonOperatorTraits<uint64_t> {
|
| + static inline bool Equals(uint64_t a, uint64_t b) { return a == b; }
|
| + static inline bool HasValue(Operator* op) {
|
| + return CommonOperatorTraits<int64_t>::HasValue(op);
|
| + }
|
| + static inline uint64_t ValueOf(Operator* op) {
|
| + return static_cast<uint64_t>(CommonOperatorTraits<int64_t>::ValueOf(op));
|
| + }
|
| +};
|
| +
|
| +template <>
|
| +struct CommonOperatorTraits<double> {
|
| + static inline bool Equals(double a, double b) {
|
| + return DoubleRepresentation(a).bits == DoubleRepresentation(b).bits;
|
| + }
|
| + static inline bool HasValue(Operator* op) {
|
| + return op->opcode() == IrOpcode::kFloat64Constant ||
|
| + op->opcode() == IrOpcode::kInt32Constant ||
|
| + op->opcode() == IrOpcode::kNumberConstant;
|
| + }
|
| + static inline double ValueOf(Operator* op) {
|
| + if (op->opcode() == IrOpcode::kFloat64Constant ||
|
| + op->opcode() == IrOpcode::kNumberConstant) {
|
| + return reinterpret_cast<Operator1<double>*>(op)->parameter();
|
| + }
|
| + return static_cast<double>(CommonOperatorTraits<int32_t>::ValueOf(op));
|
| + }
|
| +};
|
| +
|
| +template <>
|
| +struct CommonOperatorTraits<ExternalReference> {
|
| + static inline bool Equals(ExternalReference a, ExternalReference b) {
|
| + return a == b;
|
| + }
|
| + static inline bool HasValue(Operator* op) {
|
| + return op->opcode() == IrOpcode::kExternalConstant;
|
| + }
|
| + static inline ExternalReference ValueOf(Operator* op) {
|
| + CHECK_EQ(IrOpcode::kExternalConstant, op->opcode());
|
| + return static_cast<Operator1<ExternalReference>*>(op)->parameter();
|
| + }
|
| +};
|
| +
|
| +template <typename T>
|
| +struct CommonOperatorTraits<PrintableUnique<T> > {
|
| + static inline bool HasValue(Operator* op) {
|
| + return op->opcode() == IrOpcode::kHeapConstant;
|
| + }
|
| + static inline PrintableUnique<T> ValueOf(Operator* op) {
|
| + CHECK_EQ(IrOpcode::kHeapConstant, op->opcode());
|
| + return static_cast<Operator1<PrintableUnique<T> >*>(op)->parameter();
|
| + }
|
| +};
|
| +
|
| +template <typename T>
|
| +struct CommonOperatorTraits<Handle<T> > {
|
| + static inline bool HasValue(Operator* op) {
|
| + return CommonOperatorTraits<PrintableUnique<T> >::HasValue(op);
|
| + }
|
| + static inline Handle<T> ValueOf(Operator* op) {
|
| + return CommonOperatorTraits<PrintableUnique<T> >::ValueOf(op).handle();
|
| + }
|
| +};
|
| +
|
| +
|
| +template <typename T>
|
| +inline T ValueOf(Operator* op) {
|
| + return CommonOperatorTraits<T>::ValueOf(op);
|
| +}
|
| +}
|
| +}
|
| +} // namespace v8::internal::compiler
|
| +
|
| +#endif // V8_COMPILER_COMMON_OPERATOR_H_
|
|
|