Commit db10bef4 authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

[turbofan] First step of Operator refactoring.

- Real const-correctness
- Proper forward declarations instead of #include "src/v8.h"
- Flags for Operator properties.
- etc.

TEST=compiler-unittests,cctest
R=svenpanne@chromium.org

Review URL: https://codereview.chromium.org/526313002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23601 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 7955937d
......@@ -460,6 +460,7 @@ source_set("v8_base") {
"src/codegen.h",
"src/compilation-cache.cc",
"src/compilation-cache.h",
"src/compiler/access-builder.cc",
"src/compiler/access-builder.h",
"src/compiler/ast-graph-builder.cc",
"src/compiler/ast-graph-builder.h",
......@@ -529,6 +530,7 @@ source_set("v8_base") {
"src/compiler/opcodes.h",
"src/compiler/operator-properties-inl.h",
"src/compiler/operator-properties.h",
"src/compiler/operator.cc",
"src/compiler/operator.h",
"src/compiler/phi-reducer.h",
"src/compiler/pipeline.cc",
......@@ -547,6 +549,7 @@ source_set("v8_base") {
"src/compiler/simplified-node-factory.h",
"src/compiler/simplified-operator-reducer.cc",
"src/compiler/simplified-operator-reducer.h",
"src/compiler/simplified-operator.cc",
"src/compiler/simplified-operator.h",
"src/compiler/source-position.cc",
"src/compiler/source-position.h",
......
......@@ -65,51 +65,38 @@ class Flags FINAL {
#define DEFINE_OPERATORS_FOR_FLAGS(Type) \
inline ::v8::base::Flags<Type::flag_type> operator&( \
Type::flag_type lhs, \
Type::flag_type rhs)ALLOW_UNUSED WARN_UNUSED_RESULT; \
inline ::v8::base::Flags<Type::flag_type> operator&(Type::flag_type lhs, \
Type::flag_type rhs) { \
return ::v8::base::Flags<Type::flag_type>(lhs) & rhs; \
inline Type operator&(Type::flag_type lhs, \
Type::flag_type rhs)ALLOW_UNUSED WARN_UNUSED_RESULT; \
inline Type operator&(Type::flag_type lhs, Type::flag_type rhs) { \
return Type(lhs) & rhs; \
} \
inline ::v8::base::Flags<Type::flag_type> operator&( \
Type::flag_type lhs, const ::v8::base::Flags<Type::flag_type>& rhs) \
ALLOW_UNUSED WARN_UNUSED_RESULT; \
inline ::v8::base::Flags<Type::flag_type> operator&( \
Type::flag_type lhs, const ::v8::base::Flags<Type::flag_type>& rhs) { \
inline Type operator&(Type::flag_type lhs, \
const Type& rhs)ALLOW_UNUSED WARN_UNUSED_RESULT; \
inline Type operator&(Type::flag_type lhs, const Type& rhs) { \
return rhs & lhs; \
} \
inline void operator&(Type::flag_type lhs, Type::mask_type rhs)ALLOW_UNUSED; \
inline void operator&(Type::flag_type lhs, Type::mask_type rhs) {} \
inline ::v8::base::Flags<Type::flag_type> operator|(Type::flag_type lhs, \
Type::flag_type rhs) \
inline Type operator|(Type::flag_type lhs, Type::flag_type rhs) \
ALLOW_UNUSED WARN_UNUSED_RESULT; \
inline ::v8::base::Flags<Type::flag_type> operator|(Type::flag_type lhs, \
Type::flag_type rhs) { \
return ::v8::base::Flags<Type::flag_type>(lhs) | rhs; \
inline Type operator|(Type::flag_type lhs, Type::flag_type rhs) { \
return Type(lhs) | rhs; \
} \
inline ::v8::base::Flags<Type::flag_type> operator|( \
Type::flag_type lhs, const ::v8::base::Flags<Type::flag_type>& rhs) \
inline Type operator|(Type::flag_type lhs, const Type& rhs) \
ALLOW_UNUSED WARN_UNUSED_RESULT; \
inline ::v8::base::Flags<Type::flag_type> operator|( \
Type::flag_type lhs, const ::v8::base::Flags<Type::flag_type>& rhs) { \
inline Type operator|(Type::flag_type lhs, const Type& rhs) { \
return rhs | lhs; \
} \
inline void operator|(Type::flag_type lhs, Type::mask_type rhs) \
ALLOW_UNUSED; \
inline void operator|(Type::flag_type lhs, Type::mask_type rhs) {} \
inline ::v8::base::Flags<Type::flag_type> operator^(Type::flag_type lhs, \
Type::flag_type rhs) \
inline Type operator^(Type::flag_type lhs, Type::flag_type rhs) \
ALLOW_UNUSED WARN_UNUSED_RESULT; \
inline ::v8::base::Flags<Type::flag_type> operator^(Type::flag_type lhs, \
Type::flag_type rhs) { \
return ::v8::base::Flags<Type::flag_type>(lhs) ^ rhs; \
} inline ::v8::base::Flags<Type::flag_type> \
operator^(Type::flag_type lhs, \
const ::v8::base::Flags<Type::flag_type>& rhs) \
inline Type operator^(Type::flag_type lhs, Type::flag_type rhs) { \
return Type(lhs) ^ rhs; \
} inline Type operator^(Type::flag_type lhs, const Type& rhs) \
ALLOW_UNUSED WARN_UNUSED_RESULT; \
inline ::v8::base::Flags<Type::flag_type> operator^( \
Type::flag_type lhs, const ::v8::base::Flags<Type::flag_type>& rhs) { \
inline Type operator^(Type::flag_type lhs, const Type& rhs) { \
return rhs ^ lhs; \
} inline void operator^(Type::flag_type lhs, Type::mask_type rhs) \
ALLOW_UNUSED; \
......
// Copyright 2014 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.
#include "src/compiler/access-builder.h"
#include "src/types-inl.h"
namespace v8 {
namespace internal {
namespace compiler {
// static
FieldAccess AccessBuilder::ForMap() {
return {kTaggedBase, HeapObject::kMapOffset, Handle<Name>(), Type::Any(),
kMachAnyTagged};
}
// static
FieldAccess AccessBuilder::ForJSObjectProperties() {
return {kTaggedBase, JSObject::kPropertiesOffset, Handle<Name>(), Type::Any(),
kMachAnyTagged};
}
// static
FieldAccess AccessBuilder::ForJSObjectElements() {
return {kTaggedBase, JSObject::kElementsOffset, Handle<Name>(),
Type::Internal(), kMachAnyTagged};
}
// static
FieldAccess AccessBuilder::ForJSArrayBufferBackingStore() {
return {kTaggedBase, JSArrayBuffer::kBackingStoreOffset, Handle<Name>(),
Type::UntaggedPtr(), kMachPtr};
}
// static
FieldAccess AccessBuilder::ForExternalArrayPointer() {
return {kTaggedBase, ExternalArray::kExternalPointerOffset, Handle<Name>(),
Type::UntaggedPtr(), kMachPtr};
}
// static
ElementAccess AccessBuilder::ForFixedArrayElement() {
return {kTaggedBase, FixedArray::kHeaderSize, Type::Any(), kMachAnyTagged};
}
// static
ElementAccess AccessBuilder::ForBackingStoreElement(MachineType rep) {
return {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(),
rep};
}
// static
ElementAccess AccessBuilder::ForTypedArrayElement(ExternalArrayType type,
bool is_external) {
BaseTaggedness taggedness = is_external ? kUntaggedBase : kTaggedBase;
int header_size = is_external ? 0 : FixedTypedArrayBase::kDataOffset;
switch (type) {
case kExternalInt8Array:
return {taggedness, header_size, Type::Signed32(), kMachInt8};
case kExternalUint8Array:
case kExternalUint8ClampedArray:
return {taggedness, header_size, Type::Unsigned32(), kMachUint8};
case kExternalInt16Array:
return {taggedness, header_size, Type::Signed32(), kMachInt16};
case kExternalUint16Array:
return {taggedness, header_size, Type::Unsigned32(), kMachUint16};
case kExternalInt32Array:
return {taggedness, header_size, Type::Signed32(), kMachInt32};
case kExternalUint32Array:
return {taggedness, header_size, Type::Unsigned32(), kMachUint32};
case kExternalFloat32Array:
return {taggedness, header_size, Type::Number(), kRepFloat32};
case kExternalFloat64Array:
return {taggedness, header_size, Type::Number(), kRepFloat64};
}
UNREACHABLE();
return {kUntaggedBase, 0, Type::None(), kMachNone};
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -14,79 +14,35 @@ namespace compiler {
// This access builder provides a set of static methods constructing commonly
// used FieldAccess and ElementAccess descriptors. These descriptors server as
// parameters to simplified load/store operators.
class AccessBuilder : public AllStatic {
class AccessBuilder FINAL : public AllStatic {
public:
// Provides access to HeapObject::map() field.
static FieldAccess ForMap() {
return {kTaggedBase, HeapObject::kMapOffset, Handle<Name>(), Type::Any(),
kMachAnyTagged};
}
static FieldAccess ForMap();
// Provides access to JSObject::properties() field.
static FieldAccess ForJSObjectProperties() {
return {kTaggedBase, JSObject::kPropertiesOffset, Handle<Name>(),
Type::Any(), kMachAnyTagged};
}
static FieldAccess ForJSObjectProperties();
// Provides access to JSObject::elements() field.
static FieldAccess ForJSObjectElements() {
return {kTaggedBase, JSObject::kElementsOffset, Handle<Name>(),
Type::Internal(), kMachAnyTagged};
}
static FieldAccess ForJSObjectElements();
// Provides access to JSArrayBuffer::backing_store() field.
static FieldAccess ForJSArrayBufferBackingStore() {
return {kTaggedBase, JSArrayBuffer::kBackingStoreOffset, Handle<Name>(),
Type::UntaggedPtr(), kMachPtr};
}
static FieldAccess ForJSArrayBufferBackingStore();
// Provides access to ExternalArray::external_pointer() field.
static FieldAccess ForExternalArrayPointer() {
return {kTaggedBase, ExternalArray::kExternalPointerOffset, Handle<Name>(),
Type::UntaggedPtr(), kMachPtr};
}
static FieldAccess ForExternalArrayPointer();
// Provides access to FixedArray elements.
static ElementAccess ForFixedArrayElement() {
return {kTaggedBase, FixedArray::kHeaderSize, Type::Any(), kMachAnyTagged};
}
static ElementAccess ForFixedArrayElement();
// TODO(mstarzinger): Raw access only for testing, drop me.
static ElementAccess ForBackingStoreElement(MachineType rep) {
return {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag,
Type::Any(), rep};
}
static ElementAccess ForBackingStoreElement(MachineType rep);
// Provides access to Fixed{type}TypedArray and External{type}Array elements.
static ElementAccess ForTypedArrayElement(ExternalArrayType type,
bool is_external) {
BaseTaggedness taggedness = is_external ? kUntaggedBase : kTaggedBase;
int header_size = is_external ? 0 : FixedTypedArrayBase::kDataOffset;
switch (type) {
case kExternalInt8Array:
return {taggedness, header_size, Type::Signed32(), kMachInt8};
case kExternalUint8Array:
case kExternalUint8ClampedArray:
return {taggedness, header_size, Type::Unsigned32(), kMachUint8};
case kExternalInt16Array:
return {taggedness, header_size, Type::Signed32(), kMachInt16};
case kExternalUint16Array:
return {taggedness, header_size, Type::Unsigned32(), kMachUint16};
case kExternalInt32Array:
return {taggedness, header_size, Type::Signed32(), kMachInt32};
case kExternalUint32Array:
return {taggedness, header_size, Type::Unsigned32(), kMachUint32};
case kExternalFloat32Array:
return {taggedness, header_size, Type::Number(), kRepFloat32};
case kExternalFloat64Array:
return {taggedness, header_size, Type::Number(), kRepFloat64};
}
UNREACHABLE();
return {kUntaggedBase, 0, Type::None(), kMachNone};
}
bool is_external);
private:
DISALLOW_COPY_AND_ASSIGN(AccessBuilder);
DISALLOW_IMPLICIT_CONSTRUCTORS(AccessBuilder);
};
} // namespace compiler
......
......@@ -39,10 +39,9 @@ CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
}
CallDescriptor* Linkage::GetRuntimeCallDescriptor(Runtime::FunctionId function,
int parameter_count,
Operator::Property properties,
Zone* zone) {
CallDescriptor* Linkage::GetRuntimeCallDescriptor(
Runtime::FunctionId function, int parameter_count,
Operator::Properties properties, Zone* zone) {
return LinkageHelper::GetRuntimeCallDescriptor<LinkageHelperTraits>(
zone, function, parameter_count, properties);
}
......@@ -62,6 +61,7 @@ CallDescriptor* Linkage::GetSimplifiedCDescriptor(
return LinkageHelper::GetSimplifiedCDescriptor<LinkageHelperTraits>(
zone, num_params, return_type, param_types);
}
}
}
} // namespace v8::internal::compiler
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -39,10 +39,9 @@ CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
}
CallDescriptor* Linkage::GetRuntimeCallDescriptor(Runtime::FunctionId function,
int parameter_count,
Operator::Property properties,
Zone* zone) {
CallDescriptor* Linkage::GetRuntimeCallDescriptor(
Runtime::FunctionId function, int parameter_count,
Operator::Properties properties, Zone* zone) {
return LinkageHelper::GetRuntimeCallDescriptor<LinkageHelperTraits>(
zone, function, parameter_count, properties);
}
......@@ -63,6 +62,6 @@ CallDescriptor* Linkage::GetSimplifiedCDescriptor(
zone, num_params, return_type, param_types);
}
}
}
} // namespace v8::internal::compiler
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -20,18 +20,20 @@ class OStream;
namespace compiler {
class ControlOperator : public Operator1<int> {
class ControlOperator FINAL : public Operator1<int> {
public:
ControlOperator(IrOpcode::Value opcode, uint16_t properties, int inputs,
ControlOperator(IrOpcode::Value opcode, Properties properties, int inputs,
int outputs, int controls, const char* mnemonic)
: Operator1<int>(opcode, properties, inputs, outputs, mnemonic,
controls) {}
virtual OStream& PrintParameter(OStream& os) const { return os; } // NOLINT
virtual OStream& PrintParameter(OStream& os) const OVERRIDE { // NOLINT
return os;
}
int ControlInputCount() const { return parameter(); }
};
class CallOperator : public Operator1<CallDescriptor*> {
class CallOperator FINAL : public Operator1<CallDescriptor*> {
public:
CallOperator(CallDescriptor* descriptor, const char* mnemonic)
: Operator1<CallDescriptor*>(
......@@ -39,7 +41,7 @@ class CallOperator : public Operator1<CallDescriptor*> {
descriptor->InputCount() + descriptor->FrameStateCount(),
descriptor->ReturnCount(), mnemonic, descriptor) {}
virtual OStream& PrintParameter(OStream& os) const { // NOLINT
virtual OStream& PrintParameter(OStream& os) const OVERRIDE { // NOLINT
return os << "[" << *parameter() << "]";
}
};
......@@ -91,7 +93,8 @@ class CommonOperatorBuilder {
Operator* Throw() { CONTROL_OP(Throw, 1, 1); }
Operator* Return() {
return new (zone_) ControlOperator(IrOpcode::kReturn, 0, 1, 0, 1, "Return");
return new (zone_) ControlOperator(
IrOpcode::kReturn, Operator::kNoProperties, 1, 0, 1, "Return");
}
Operator* Merge(int controls) {
......
......@@ -35,10 +35,9 @@ CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
}
CallDescriptor* Linkage::GetRuntimeCallDescriptor(Runtime::FunctionId function,
int parameter_count,
Operator::Property properties,
Zone* zone) {
CallDescriptor* Linkage::GetRuntimeCallDescriptor(
Runtime::FunctionId function, int parameter_count,
Operator::Properties properties, Zone* zone) {
return LinkageHelper::GetRuntimeCallDescriptor<LinkageHelperTraits>(
zone, function, parameter_count, properties);
}
......
......@@ -377,10 +377,11 @@ void JSGenericLowering::ReplaceWithBuiltinCall(Node* node,
void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
Runtime::FunctionId f,
int nargs_override) {
Operator::Property props = node->op()->properties();
Operator::Properties properties = node->op()->properties();
const Runtime::Function* fun = Runtime::FunctionForId(f);
int nargs = (nargs_override < 0) ? fun->nargs : nargs_override;
CallDescriptor* desc = linkage()->GetRuntimeCallDescriptor(f, nargs, props);
CallDescriptor* desc =
linkage()->GetRuntimeCallDescriptor(f, nargs, properties);
Node* ref = ExternalConstant(ExternalReference(f, isolate()));
Node* arity = Int32Constant(nargs);
if (!centrystub_constant_.is_set()) {
......
......@@ -71,7 +71,7 @@ class LinkageHelper {
template <typename LinkageTraits>
static CallDescriptor* GetRuntimeCallDescriptor(
Zone* zone, Runtime::FunctionId function_id, int parameter_count,
Operator::Property properties) {
Operator::Properties properties) {
const int code_count = 1;
const int function_count = 1;
const int num_args_count = 1;
......
......@@ -95,7 +95,7 @@ CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count) {
CallDescriptor* Linkage::GetRuntimeCallDescriptor(
Runtime::FunctionId function, int parameter_count,
Operator::Property properties) {
Operator::Properties properties) {
return GetRuntimeCallDescriptor(function, parameter_count, properties,
this->info_->zone());
}
......@@ -139,10 +139,9 @@ CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
}
CallDescriptor* Linkage::GetRuntimeCallDescriptor(Runtime::FunctionId function,
int parameter_count,
Operator::Property properties,
Zone* zone) {
CallDescriptor* Linkage::GetRuntimeCallDescriptor(
Runtime::FunctionId function, int parameter_count,
Operator::Properties properties, Zone* zone) {
UNIMPLEMENTED();
return NULL;
}
......
......@@ -54,8 +54,9 @@ class CallDescriptor FINAL : public ZoneObject {
CallDescriptor(Kind kind, int8_t return_count, int16_t parameter_count,
int16_t input_count, LinkageLocation* locations,
Operator::Property properties, RegList callee_saved_registers,
Flags flags, const char* debug_name = "")
Operator::Properties properties,
RegList callee_saved_registers, Flags flags,
const char* debug_name = "")
: kind_(kind),
return_count_(return_count),
parameter_count_(parameter_count),
......@@ -97,7 +98,7 @@ class CallDescriptor FINAL : public ZoneObject {
}
// Operator properties describe how this call can be optimized, if at all.
Operator::Property properties() const { return properties_; }
Operator::Properties properties() const { return properties_; }
// Get the callee-saved registers, if any, across this call.
RegList CalleeSavedRegisters() { return callee_saved_registers_; }
......@@ -112,7 +113,7 @@ class CallDescriptor FINAL : public ZoneObject {
int16_t parameter_count_;
int16_t input_count_;
LinkageLocation* locations_;
Operator::Property properties_;
Operator::Properties properties_;
RegList callee_saved_registers_;
Flags flags_;
const char* debug_name_;
......@@ -149,11 +150,10 @@ class Linkage : public ZoneObject {
static CallDescriptor* GetJSCallDescriptor(int parameter_count, Zone* zone);
CallDescriptor* GetRuntimeCallDescriptor(Runtime::FunctionId function,
int parameter_count,
Operator::Property properties);
static CallDescriptor* GetRuntimeCallDescriptor(Runtime::FunctionId function,
int parameter_count,
Operator::Property properties,
Zone* zone);
Operator::Properties properties);
static CallDescriptor* GetRuntimeCallDescriptor(
Runtime::FunctionId function, int parameter_count,
Operator::Properties properties, Zone* zone);
CallDescriptor* GetStubCallDescriptor(
CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count = 0,
......
// Copyright 2014 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.
#include "src/compiler/operator.h"
#include "src/assembler.h"
namespace v8 {
namespace internal {
namespace compiler {
Operator::~Operator() {}
SimpleOperator::SimpleOperator(Opcode opcode, Properties properties,
int input_count, int output_count,
const char* mnemonic)
: Operator(opcode, properties, mnemonic),
input_count_(input_count),
output_count_(output_count) {}
SimpleOperator::~SimpleOperator() {}
// static
OStream& StaticParameterTraits<ExternalReference>::PrintTo(
OStream& os, ExternalReference reference) {
os << reference.address();
// TODO(bmeurer): Move to operator<<(os, ExternalReference)
const Runtime::Function* function =
Runtime::FunctionForEntry(reference.address());
if (function) {
os << " <" << function->name << ".entry>";
}
return os;
}
// static
int StaticParameterTraits<ExternalReference>::HashCode(
ExternalReference reference) {
return reinterpret_cast<intptr_t>(reference.address()) & 0xFFFFFFFF;
}
// static
bool StaticParameterTraits<ExternalReference>::Equals(ExternalReference lhs,
ExternalReference rhs) {
return lhs == rhs;
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -5,14 +5,17 @@
#ifndef V8_COMPILER_OPERATOR_H_
#define V8_COMPILER_OPERATOR_H_
#include "src/v8.h"
#include "src/assembler.h"
#include "src/base/flags.h"
#include "src/ostreams.h"
#include "src/unique.h"
namespace v8 {
namespace internal {
// Forward declarations.
class ExternalReference;
namespace compiler {
// An operator represents description of the "computation" of a node in the
......@@ -29,9 +32,7 @@ namespace compiler {
// meaningful to the operator itself.
class Operator : public ZoneObject {
public:
Operator(uint8_t opcode, uint16_t properties)
: opcode_(opcode), properties_(properties) {}
virtual ~Operator() {}
typedef uint8_t Opcode;
// Properties inform the operator-independent optimizer about legal
// transformations for nodes that have this operator.
......@@ -49,78 +50,88 @@ class Operator : public ZoneObject {
kEliminatable = kNoWrite | kNoThrow,
kPure = kNoRead | kNoWrite | kNoThrow | kIdempotent
};
typedef base::Flags<Property, uint8_t> Properties;
Operator(Opcode opcode, Properties properties, const char* mnemonic)
: opcode_(opcode), properties_(properties), mnemonic_(mnemonic) {}
virtual ~Operator();
// A small integer unique to all instances of a particular kind of operator,
// useful for quick matching for specific kinds of operators. For fast access
// the opcode is stored directly in the operator object.
inline uint8_t opcode() const { return opcode_; }
Opcode opcode() const { return opcode_; }
// Returns a constant string representing the mnemonic of the operator,
// without the static parameters. Useful for debugging.
virtual const char* mnemonic() = 0;
const char* mnemonic() const { return mnemonic_; }
// Check if this operator equals another operator. Equivalent operators can
// be merged, and nodes with equivalent operators and equivalent inputs
// can be merged.
virtual bool Equals(Operator* other) = 0;
virtual bool Equals(const Operator* other) const = 0;
// Compute a hashcode to speed up equivalence-set checking.
// Equal operators should always have equal hashcodes, and unequal operators
// should have unequal hashcodes with high probability.
virtual int HashCode() = 0;
virtual int HashCode() const = 0;
// Check whether this operator has the given property.
inline bool HasProperty(Property property) const {
return (properties_ & static_cast<int>(property)) == property;
bool HasProperty(Property property) const {
return (properties() & property) == property;
}
// Number of data inputs to the operator, for verifying graph structure.
virtual int InputCount() = 0;
virtual int InputCount() const = 0;
// Number of data outputs from the operator, for verifying graph structure.
virtual int OutputCount() = 0;
virtual int OutputCount() const = 0;
inline Property properties() { return static_cast<Property>(properties_); }
Properties properties() const { return properties_; }
// TODO(titzer): API for input and output types, for typechecking graph.
private:
protected:
// Print the full operator into the given stream, including any
// static parameters. Useful for debugging and visualizing the IR.
virtual OStream& PrintTo(OStream& os) const = 0; // NOLINT
friend OStream& operator<<(OStream& os, const Operator& op);
uint8_t opcode_;
uint16_t properties_;
private:
Opcode opcode_;
Properties properties_;
const char* mnemonic_;
DISALLOW_COPY_AND_ASSIGN(Operator);
};
DEFINE_OPERATORS_FOR_FLAGS(Operator::Properties)
OStream& operator<<(OStream& os, const Operator& op);
// An implementation of Operator that has no static parameters. Such operators
// have just a name, an opcode, and a fixed number of inputs and outputs.
// They can represented by singletons and shared globally.
class SimpleOperator : public Operator {
class SimpleOperator FINAL : public Operator {
public:
SimpleOperator(uint8_t opcode, uint16_t properties, int input_count,
int output_count, const char* mnemonic)
: Operator(opcode, properties),
input_count_(input_count),
output_count_(output_count),
mnemonic_(mnemonic) {}
SimpleOperator(Opcode opcode, Properties properties, int input_count,
int output_count, const char* mnemonic);
~SimpleOperator();
virtual const char* mnemonic() { return mnemonic_; }
virtual bool Equals(Operator* that) { return opcode() == that->opcode(); }
virtual int HashCode() { return opcode(); }
virtual int InputCount() { return input_count_; }
virtual int OutputCount() { return output_count_; }
virtual bool Equals(const Operator* that) const OVERRIDE {
return opcode() == that->opcode();
}
virtual int HashCode() const OVERRIDE { return opcode(); }
virtual int InputCount() const OVERRIDE { return input_count_; }
virtual int OutputCount() const OVERRIDE { return output_count_; }
private:
virtual OStream& PrintTo(OStream& os) const { // NOLINT
return os << mnemonic_;
virtual OStream& PrintTo(OStream& os) const OVERRIDE { // NOLINT
return os << mnemonic();
}
int input_count_;
int output_count_;
const char* mnemonic_;
DISALLOW_COPY_AND_ASSIGN(SimpleOperator);
};
// Template specialization implements a kind of type class for dealing with the
......@@ -138,21 +149,9 @@ struct StaticParameterTraits {
template <>
struct StaticParameterTraits<ExternalReference> {
static OStream& PrintTo(OStream& os, ExternalReference val) { // NOLINT
os << val.address();
const Runtime::Function* function =
Runtime::FunctionForEntry(val.address());
if (function != NULL) {
os << " <" << function->name << ".entry>";
}
return os;
}
static int HashCode(ExternalReference a) {
return reinterpret_cast<intptr_t>(a.address()) & 0xFFFFFFFF;
}
static bool Equals(ExternalReference a, ExternalReference b) {
return a == b;
}
static OStream& PrintTo(OStream& os, ExternalReference reference); // NOLINT
static int HashCode(ExternalReference reference);
static bool Equals(ExternalReference lhs, ExternalReference rhs);
};
// Specialization for static parameters of type {int}.
......@@ -233,48 +232,45 @@ struct StaticParameterTraits<Handle<Object> > {
template <typename T>
class Operator1 : public Operator {
public:
Operator1(uint8_t opcode, uint16_t properties, int input_count,
Operator1(Opcode opcode, Properties properties, int input_count,
int output_count, const char* mnemonic, T parameter)
: Operator(opcode, properties),
: Operator(opcode, properties, mnemonic),
input_count_(input_count),
output_count_(output_count),
mnemonic_(mnemonic),
parameter_(parameter) {}
const T& parameter() const { return parameter_; }
virtual const char* mnemonic() { return mnemonic_; }
virtual bool Equals(Operator* other) {
virtual bool Equals(const Operator* other) const OVERRIDE {
if (opcode() != other->opcode()) return false;
Operator1<T>* that = static_cast<Operator1<T>*>(other);
T temp1 = this->parameter_;
T temp2 = that->parameter_;
return StaticParameterTraits<T>::Equals(temp1, temp2);
const Operator1<T>* that = static_cast<const Operator1<T>*>(other);
return StaticParameterTraits<T>::Equals(this->parameter_, that->parameter_);
}
virtual int HashCode() {
virtual int HashCode() const OVERRIDE {
return opcode() + 33 * StaticParameterTraits<T>::HashCode(this->parameter_);
}
virtual int InputCount() { return input_count_; }
virtual int OutputCount() { return output_count_; }
virtual int InputCount() const OVERRIDE { return input_count_; }
virtual int OutputCount() const OVERRIDE { return output_count_; }
virtual OStream& PrintParameter(OStream& os) const { // NOLINT
return StaticParameterTraits<T>::PrintTo(os << "[", parameter_) << "]";
}
private:
virtual OStream& PrintTo(OStream& os) const { // NOLINT
return PrintParameter(os << mnemonic_);
protected:
virtual OStream& PrintTo(OStream& os) const FINAL { // NOLINT
return PrintParameter(os << mnemonic());
}
private:
int input_count_;
int output_count_;
const char* mnemonic_;
T parameter_;
};
// Type definitions for operators with specific types of parameters.
typedef Operator1<PrintableUnique<Name> > NameOperator;
}
}
} // namespace v8::internal::compiler
} // namespace compiler
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_OPERATOR_H_
// Copyright 2012 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.
#include "src/compiler/simplified-operator.h"
#include "src/types-inl.h"
namespace v8 {
namespace internal {
namespace compiler {
// static
bool StaticParameterTraits<FieldAccess>::Equals(const FieldAccess& lhs,
const FieldAccess& rhs) {
return lhs.base_is_tagged == rhs.base_is_tagged && lhs.offset == rhs.offset &&
lhs.machine_type == rhs.machine_type && lhs.type->Is(rhs.type);
}
// static
bool StaticParameterTraits<ElementAccess>::Equals(const ElementAccess& lhs,
const ElementAccess& rhs) {
return lhs.base_is_tagged == rhs.base_is_tagged &&
lhs.header_size == rhs.header_size &&
lhs.machine_type == rhs.machine_type && lhs.type->Is(rhs.type);
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -11,6 +11,14 @@
namespace v8 {
namespace internal {
// Forward declarations.
template <class>
class TypeImpl;
struct ZoneTypeConfig;
typedef TypeImpl<ZoneTypeConfig> Type;
namespace compiler {
enum BaseTaggedness { kUntaggedBase, kTaggedBase };
......@@ -49,34 +57,27 @@ static const int kNonHeapObjectHeaderSize = kHeapObjectTag;
// Specialization for static parameters of type {FieldAccess}.
template <>
struct StaticParameterTraits<const FieldAccess> {
struct StaticParameterTraits<FieldAccess> {
static OStream& PrintTo(OStream& os, const FieldAccess& val) { // NOLINT
return os << val.offset;
}
static int HashCode(const FieldAccess& val) {
return (val.offset < 16) | (val.machine_type & 0xffff);
}
static bool Equals(const FieldAccess& a, const FieldAccess& b) {
return a.base_is_tagged == b.base_is_tagged && a.offset == b.offset &&
a.machine_type == b.machine_type && a.type->Is(b.type);
}
static bool Equals(const FieldAccess& lhs, const FieldAccess& rhs);
};
// Specialization for static parameters of type {ElementAccess}.
template <>
struct StaticParameterTraits<const ElementAccess> {
struct StaticParameterTraits<ElementAccess> {
static OStream& PrintTo(OStream& os, const ElementAccess& val) { // NOLINT
return os << val.header_size;
}
static int HashCode(const ElementAccess& val) {
return (val.header_size < 16) | (val.machine_type & 0xffff);
}
static bool Equals(const ElementAccess& a, const ElementAccess& b) {
return a.base_is_tagged == b.base_is_tagged &&
a.header_size == b.header_size && a.machine_type == b.machine_type &&
a.type->Is(b.type);
}
static bool Equals(const ElementAccess& lhs, const ElementAccess& rhs);
};
......@@ -94,55 +95,6 @@ inline const ElementAccess ElementAccessOf(Operator* op) {
}
// This access helper provides a set of static methods constructing commonly
// used FieldAccess and ElementAccess descriptors.
class Access : public AllStatic {
public:
// Provides access to JSObject::elements() field.
static FieldAccess ForJSObjectElements() {
return {kTaggedBase, JSObject::kElementsOffset, Handle<Name>(),
Type::Internal(), kMachAnyTagged};
}
// Provides access to ExternalArray::external_pointer() field.
static FieldAccess ForExternalArrayPointer() {
return {kTaggedBase, ExternalArray::kExternalPointerOffset, Handle<Name>(),
Type::UntaggedPtr(), kMachPtr};
}
// Provides access to Fixed{type}TypedArray and External{type}Array elements.
static ElementAccess ForTypedArrayElement(ExternalArrayType type,
bool is_external) {
BaseTaggedness taggedness = is_external ? kUntaggedBase : kTaggedBase;
int header_size = is_external ? 0 : FixedTypedArrayBase::kDataOffset;
switch (type) {
case kExternalInt8Array:
return {taggedness, header_size, Type::Signed32(), kMachInt8};
case kExternalUint8Array:
case kExternalUint8ClampedArray:
return {taggedness, header_size, Type::Unsigned32(), kMachUint8};
case kExternalInt16Array:
return {taggedness, header_size, Type::Signed32(), kMachInt16};
case kExternalUint16Array:
return {taggedness, header_size, Type::Unsigned32(), kMachUint16};
case kExternalInt32Array:
return {taggedness, header_size, Type::Signed32(), kMachInt32};
case kExternalUint32Array:
return {taggedness, header_size, Type::Unsigned32(), kMachUint32};
case kExternalFloat32Array:
return {taggedness, header_size, Type::Number(), kRepFloat32};
case kExternalFloat64Array:
return {taggedness, header_size, Type::Number(), kRepFloat64};
}
UNREACHABLE();
return {kUntaggedBase, 0, Type::None(), kMachNone};
}
private:
DISALLOW_COPY_AND_ASSIGN(Access);
};
// Interface for building simplified operators, which represent the
// medium-level operations of V8, including adding numbers, allocating objects,
// indexing into objects and arrays, etc.
......
......@@ -54,10 +54,9 @@ CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
}
CallDescriptor* Linkage::GetRuntimeCallDescriptor(Runtime::FunctionId function,
int parameter_count,
Operator::Property properties,
Zone* zone) {
CallDescriptor* Linkage::GetRuntimeCallDescriptor(
Runtime::FunctionId function, int parameter_count,
Operator::Properties properties, Zone* zone) {
return LinkageHelper::GetRuntimeCallDescriptor<LinkageHelperTraits>(
zone, function, parameter_count, properties);
}
......@@ -78,6 +77,6 @@ CallDescriptor* Linkage::GetSimplifiedCDescriptor(
zone, num_params, return_type, param_types);
}
}
}
} // namespace v8::internal::compiler
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -14,40 +14,40 @@ using namespace v8::internal::compiler;
#define Infinity (std::numeric_limits<double>::infinity())
TEST(TestOperatorMnemonic) {
SimpleOperator op1(10, 0, 0, 0, "ThisOne");
SimpleOperator op1(10, Operator::kNoProperties, 0, 0, "ThisOne");
CHECK_EQ(0, strcmp(op1.mnemonic(), "ThisOne"));
SimpleOperator op2(11, 0, 0, 0, "ThatOne");
SimpleOperator op2(11, Operator::kNoProperties, 0, 0, "ThatOne");
CHECK_EQ(0, strcmp(op2.mnemonic(), "ThatOne"));
Operator1<int> op3(12, 0, 0, 1, "Mnemonic1", 12333);
Operator1<int> op3(12, Operator::kNoProperties, 0, 1, "Mnemonic1", 12333);
CHECK_EQ(0, strcmp(op3.mnemonic(), "Mnemonic1"));
Operator1<double> op4(13, 0, 0, 1, "TheOther", 99.9);
Operator1<double> op4(13, Operator::kNoProperties, 0, 1, "TheOther", 99.9);
CHECK_EQ(0, strcmp(op4.mnemonic(), "TheOther"));
}
TEST(TestSimpleOperatorHash) {
SimpleOperator op1(17, 0, 0, 0, "Another");
SimpleOperator op1(17, Operator::kNoProperties, 0, 0, "Another");
CHECK_EQ(17, op1.HashCode());
SimpleOperator op2(18, 0, 0, 0, "Falsch");
SimpleOperator op2(18, Operator::kNoProperties, 0, 0, "Falsch");
CHECK_EQ(18, op2.HashCode());
}
TEST(TestSimpleOperatorEquals) {
SimpleOperator op1a(19, 0, 0, 0, "Another1");
SimpleOperator op1b(19, 2, 2, 2, "Another2");
SimpleOperator op1a(19, Operator::kNoProperties, 0, 0, "Another1");
SimpleOperator op1b(19, Operator::kFoldable, 2, 2, "Another2");
CHECK(op1a.Equals(&op1a));
CHECK(op1a.Equals(&op1b));
CHECK(op1b.Equals(&op1a));
CHECK(op1b.Equals(&op1b));
SimpleOperator op2a(20, 0, 0, 0, "Falsch1");
SimpleOperator op2b(20, 1, 1, 1, "Falsch2");
SimpleOperator op2a(20, Operator::kNoProperties, 0, 0, "Falsch1");
SimpleOperator op2b(20, Operator::kFoldable, 1, 1, "Falsch2");
CHECK(op2a.Equals(&op2a));
CHECK(op2a.Equals(&op2b));
......@@ -74,14 +74,14 @@ static SmartArrayPointer<const char> OperatorToString(Operator* op) {
TEST(TestSimpleOperatorPrint) {
SimpleOperator op1a(19, 0, 0, 0, "Another1");
SimpleOperator op1b(19, 2, 2, 2, "Another2");
SimpleOperator op1a(19, Operator::kNoProperties, 0, 0, "Another1");
SimpleOperator op1b(19, Operator::kFoldable, 2, 2, "Another2");
CHECK_EQ("Another1", OperatorToString(&op1a).get());
CHECK_EQ("Another2", OperatorToString(&op1b).get());
SimpleOperator op2a(20, 0, 0, 0, "Flog1");
SimpleOperator op2b(20, 1, 1, 1, "Flog2");
SimpleOperator op2a(20, Operator::kNoProperties, 0, 0, "Flog1");
SimpleOperator op2b(20, Operator::kFoldable, 1, 1, "Flog2");
CHECK_EQ("Flog1", OperatorToString(&op2a).get());
CHECK_EQ("Flog2", OperatorToString(&op2b).get());
......@@ -89,13 +89,13 @@ TEST(TestSimpleOperatorPrint) {
TEST(TestOperator1intHash) {
Operator1<int> op1a(23, 0, 0, 0, "Wolfie", 11);
Operator1<int> op1b(23, 2, 2, 2, "Doggie", 11);
Operator1<int> op1a(23, Operator::kNoProperties, 0, 0, "Wolfie", 11);
Operator1<int> op1b(23, Operator::kFoldable, 2, 2, "Doggie", 11);
CHECK_EQ(op1a.HashCode(), op1b.HashCode());
Operator1<int> op2a(24, 0, 0, 0, "Arfie", 3);
Operator1<int> op2b(24, 0, 0, 0, "Arfie", 4);
Operator1<int> op2a(24, Operator::kNoProperties, 0, 0, "Arfie", 3);
Operator1<int> op2b(24, Operator::kNoProperties, 0, 0, "Arfie", 4);
CHECK_NE(op1a.HashCode(), op2a.HashCode());
CHECK_NE(op2a.HashCode(), op2b.HashCode());
......@@ -103,16 +103,16 @@ TEST(TestOperator1intHash) {
TEST(TestOperator1intEquals) {
Operator1<int> op1a(23, 0, 0, 0, "Scratchy", 11);
Operator1<int> op1b(23, 2, 2, 2, "Scratchy", 11);
Operator1<int> op1a(23, Operator::kNoProperties, 0, 0, "Scratchy", 11);
Operator1<int> op1b(23, Operator::kFoldable, 2, 2, "Scratchy", 11);
CHECK(op1a.Equals(&op1a));
CHECK(op1a.Equals(&op1b));
CHECK(op1b.Equals(&op1a));
CHECK(op1b.Equals(&op1b));
Operator1<int> op2a(24, 0, 0, 0, "Im", 3);
Operator1<int> op2b(24, 0, 0, 0, "Im", 4);
Operator1<int> op2a(24, Operator::kNoProperties, 0, 0, "Im", 3);
Operator1<int> op2b(24, Operator::kNoProperties, 0, 0, "Im", 4);
CHECK(op2a.Equals(&op2a));
CHECK(!op2a.Equals(&op2b));
......@@ -129,7 +129,7 @@ TEST(TestOperator1intEquals) {
CHECK(!op2b.Equals(&op1a));
CHECK(!op2b.Equals(&op1b));
SimpleOperator op3(25, 0, 0, 0, "Weepy");
SimpleOperator op3(25, Operator::kNoProperties, 0, 0, "Weepy");
CHECK(!op1a.Equals(&op3));
CHECK(!op1b.Equals(&op3));
......@@ -144,28 +144,28 @@ TEST(TestOperator1intEquals) {
TEST(TestOperator1intPrint) {
Operator1<int> op1(12, 0, 0, 1, "Op1Test", 0);
Operator1<int> op1(12, Operator::kNoProperties, 0, 1, "Op1Test", 0);
CHECK_EQ("Op1Test[0]", OperatorToString(&op1).get());
Operator1<int> op2(12, 0, 0, 1, "Op1Test", 66666666);
Operator1<int> op2(12, Operator::kNoProperties, 0, 1, "Op1Test", 66666666);
CHECK_EQ("Op1Test[66666666]", OperatorToString(&op2).get());
Operator1<int> op3(12, 0, 0, 1, "FooBar", 2347);
Operator1<int> op3(12, Operator::kNoProperties, 0, 1, "FooBar", 2347);
CHECK_EQ("FooBar[2347]", OperatorToString(&op3).get());
Operator1<int> op4(12, 0, 0, 1, "BarFoo", -879);
Operator1<int> op4(12, Operator::kNoProperties, 0, 1, "BarFoo", -879);
CHECK_EQ("BarFoo[-879]", OperatorToString(&op4).get());
}
TEST(TestOperator1doubleHash) {
Operator1<double> op1a(23, 0, 0, 0, "Wolfie", 11.77);
Operator1<double> op1b(23, 2, 2, 2, "Doggie", 11.77);
Operator1<double> op1a(23, Operator::kNoProperties, 0, 0, "Wolfie", 11.77);
Operator1<double> op1b(23, Operator::kFoldable, 2, 2, "Doggie", 11.77);
CHECK_EQ(op1a.HashCode(), op1b.HashCode());
Operator1<double> op2a(24, 0, 0, 0, "Arfie", -6.7);
Operator1<double> op2b(24, 0, 0, 0, "Arfie", -6.8);
Operator1<double> op2a(24, Operator::kNoProperties, 0, 0, "Arfie", -6.7);
Operator1<double> op2b(24, Operator::kNoProperties, 0, 0, "Arfie", -6.8);
CHECK_NE(op1a.HashCode(), op2a.HashCode());
CHECK_NE(op2a.HashCode(), op2b.HashCode());
......@@ -173,16 +173,16 @@ TEST(TestOperator1doubleHash) {
TEST(TestOperator1doubleEquals) {
Operator1<double> op1a(23, 0, 0, 0, "Scratchy", 11.77);
Operator1<double> op1b(23, 2, 2, 2, "Scratchy", 11.77);
Operator1<double> op1a(23, Operator::kNoProperties, 0, 0, "Scratchy", 11.77);
Operator1<double> op1b(23, Operator::kFoldable, 2, 2, "Scratchy", 11.77);
CHECK(op1a.Equals(&op1a));
CHECK(op1a.Equals(&op1b));
CHECK(op1b.Equals(&op1a));
CHECK(op1b.Equals(&op1b));
Operator1<double> op2a(24, 0, 0, 0, "Im", 3.1);
Operator1<double> op2b(24, 0, 0, 0, "Im", 3.2);
Operator1<double> op2a(24, Operator::kNoProperties, 0, 0, "Im", 3.1);
Operator1<double> op2b(24, Operator::kNoProperties, 0, 0, "Im", 3.2);
CHECK(op2a.Equals(&op2a));
CHECK(!op2a.Equals(&op2b));
......@@ -199,7 +199,7 @@ TEST(TestOperator1doubleEquals) {
CHECK(!op2b.Equals(&op1a));
CHECK(!op2b.Equals(&op1b));
SimpleOperator op3(25, 0, 0, 0, "Weepy");
SimpleOperator op3(25, Operator::kNoProperties, 0, 0, "Weepy");
CHECK(!op1a.Equals(&op3));
CHECK(!op1b.Equals(&op3));
......@@ -211,8 +211,8 @@ TEST(TestOperator1doubleEquals) {
CHECK(!op3.Equals(&op2a));
CHECK(!op3.Equals(&op2b));
Operator1<double> op4a(24, 0, 0, 0, "Bashful", NaN);
Operator1<double> op4b(24, 0, 0, 0, "Bashful", NaN);
Operator1<double> op4a(24, Operator::kNoProperties, 0, 0, "Bashful", NaN);
Operator1<double> op4b(24, Operator::kNoProperties, 0, 0, "Bashful", NaN);
CHECK(op4a.Equals(&op4a));
CHECK(op4a.Equals(&op4b));
......@@ -227,18 +227,18 @@ TEST(TestOperator1doubleEquals) {
TEST(TestOperator1doublePrint) {
Operator1<double> op1(12, 0, 0, 1, "Op1Test", 0);
Operator1<double> op1(12, Operator::kNoProperties, 0, 1, "Op1Test", 0);
CHECK_EQ("Op1Test[0]", OperatorToString(&op1).get());
Operator1<double> op2(12, 0, 0, 1, "Op1Test", 7.3);
Operator1<double> op2(12, Operator::kNoProperties, 0, 1, "Op1Test", 7.3);
CHECK_EQ("Op1Test[7.3]", OperatorToString(&op2).get());
Operator1<double> op3(12, 0, 0, 1, "FooBar", 2e+123);
Operator1<double> op3(12, Operator::kNoProperties, 0, 1, "FooBar", 2e+123);
CHECK_EQ("FooBar[2e+123]", OperatorToString(&op3).get());
Operator1<double> op4(12, 0, 0, 1, "BarFoo", Infinity);
Operator1<double> op4(12, Operator::kNoProperties, 0, 1, "BarFoo", Infinity);
CHECK_EQ("BarFoo[inf]", OperatorToString(&op4).get());
Operator1<double> op5(12, 0, 0, 1, "BarFoo", NaN);
Operator1<double> op5(12, Operator::kNoProperties, 0, 1, "BarFoo", NaN);
CHECK_EQ("BarFoo[nan]", OperatorToString(&op5).get());
}
......@@ -372,6 +372,7 @@
'../../src/codegen.h',
'../../src/compilation-cache.cc',
'../../src/compilation-cache.h',
'../../src/compiler/access-builder.cc',
'../../src/compiler/access-builder.h',
'../../src/compiler/ast-graph-builder.cc',
'../../src/compiler/ast-graph-builder.h',
......@@ -441,6 +442,7 @@
'../../src/compiler/opcodes.h',
'../../src/compiler/operator-properties-inl.h',
'../../src/compiler/operator-properties.h',
'../../src/compiler/operator.cc',
'../../src/compiler/operator.h',
'../../src/compiler/phi-reducer.h',
'../../src/compiler/pipeline.cc',
......@@ -459,6 +461,7 @@
'../../src/compiler/simplified-node-factory.h',
'../../src/compiler/simplified-operator-reducer.cc',
'../../src/compiler/simplified-operator-reducer.h',
'../../src/compiler/simplified-operator.cc',
'../../src/compiler/simplified-operator.h',
'../../src/compiler/source-position.cc',
'../../src/compiler/source-position.h',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment