1 // Copyright 2012 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/simplified-operator.h" 6 7 #include "src/base/lazy-instance.h" 8 #include "src/compiler/opcodes.h" 9 #include "src/compiler/operator.h" 10 #include "src/types-inl.h" 11 12 namespace v8 { 13 namespace internal { 14 namespace compiler { 15 16 OStream& operator<<(OStream& os, BaseTaggedness base_taggedness) { 17 switch (base_taggedness) { 18 case kUntaggedBase: 19 return os << "untagged base"; 20 case kTaggedBase: 21 return os << "tagged base"; 22 } 23 UNREACHABLE(); 24 return os; 25 } 26 27 28 bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) { 29 return lhs.base_is_tagged == rhs.base_is_tagged && 30 lhs.header_size == rhs.header_size && lhs.type == rhs.type && 31 lhs.machine_type == rhs.machine_type; 32 } 33 34 35 bool operator!=(ElementAccess const& lhs, ElementAccess const& rhs) { 36 return !(lhs == rhs); 37 } 38 39 40 OStream& operator<<(OStream& os, ElementAccess const& access) { 41 os << "[" << access.base_is_tagged << ", " << access.header_size << ", "; 42 access.type->PrintTo(os); 43 os << ", " << access.machine_type << "]"; 44 return os; 45 } 46 47 48 const FieldAccess& FieldAccessOf(const Operator* op) { 49 DCHECK_NOT_NULL(op); 50 DCHECK(op->opcode() == IrOpcode::kLoadField || 51 op->opcode() == IrOpcode::kStoreField); 52 return OpParameter<FieldAccess>(op); 53 } 54 55 56 const ElementAccess& ElementAccessOf(const Operator* op) { 57 DCHECK_NOT_NULL(op); 58 DCHECK(op->opcode() == IrOpcode::kLoadElement || 59 op->opcode() == IrOpcode::kStoreElement); 60 return OpParameter<ElementAccess>(op); 61 } 62 63 64 // Specialization for static parameters of type {FieldAccess}. 65 template <> 66 struct StaticParameterTraits<FieldAccess> { 67 static OStream& PrintTo(OStream& os, const FieldAccess& val) { 68 return os << val.offset; 69 } 70 static int HashCode(const FieldAccess& val) { 71 return (val.offset < 16) | (val.machine_type & 0xffff); 72 } 73 static bool Equals(const FieldAccess& lhs, const FieldAccess& rhs) { 74 return lhs.base_is_tagged == rhs.base_is_tagged && 75 lhs.offset == rhs.offset && lhs.machine_type == rhs.machine_type && 76 lhs.type->Is(rhs.type); 77 } 78 }; 79 80 81 // Specialization for static parameters of type {ElementAccess}. 82 template <> 83 struct StaticParameterTraits<ElementAccess> { 84 static OStream& PrintTo(OStream& os, const ElementAccess& access) { 85 return os << access; 86 } 87 static int HashCode(const ElementAccess& access) { 88 return (access.header_size < 16) | (access.machine_type & 0xffff); 89 } 90 static bool Equals(const ElementAccess& lhs, const ElementAccess& rhs) { 91 return lhs.base_is_tagged == rhs.base_is_tagged && 92 lhs.header_size == rhs.header_size && 93 lhs.machine_type == rhs.machine_type && lhs.type->Is(rhs.type); 94 } 95 }; 96 97 98 #define PURE_OP_LIST(V) \ 99 V(BooleanNot, Operator::kNoProperties, 1) \ 100 V(BooleanToNumber, Operator::kNoProperties, 1) \ 101 V(NumberEqual, Operator::kCommutative, 2) \ 102 V(NumberLessThan, Operator::kNoProperties, 2) \ 103 V(NumberLessThanOrEqual, Operator::kNoProperties, 2) \ 104 V(NumberAdd, Operator::kCommutative, 2) \ 105 V(NumberSubtract, Operator::kNoProperties, 2) \ 106 V(NumberMultiply, Operator::kCommutative, 2) \ 107 V(NumberDivide, Operator::kNoProperties, 2) \ 108 V(NumberModulus, Operator::kNoProperties, 2) \ 109 V(NumberToInt32, Operator::kNoProperties, 1) \ 110 V(NumberToUint32, Operator::kNoProperties, 1) \ 111 V(StringEqual, Operator::kCommutative, 2) \ 112 V(StringLessThan, Operator::kNoProperties, 2) \ 113 V(StringLessThanOrEqual, Operator::kNoProperties, 2) \ 114 V(StringAdd, Operator::kNoProperties, 2) \ 115 V(ChangeTaggedToInt32, Operator::kNoProperties, 1) \ 116 V(ChangeTaggedToUint32, Operator::kNoProperties, 1) \ 117 V(ChangeTaggedToFloat64, Operator::kNoProperties, 1) \ 118 V(ChangeInt32ToTagged, Operator::kNoProperties, 1) \ 119 V(ChangeUint32ToTagged, Operator::kNoProperties, 1) \ 120 V(ChangeFloat64ToTagged, Operator::kNoProperties, 1) \ 121 V(ChangeBoolToBit, Operator::kNoProperties, 1) \ 122 V(ChangeBitToBool, Operator::kNoProperties, 1) 123 124 125 #define ACCESS_OP_LIST(V) \ 126 V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1) \ 127 V(StoreField, FieldAccess, Operator::kNoRead, 2, 0) \ 128 V(LoadElement, ElementAccess, Operator::kNoWrite, 3, 1) \ 129 V(StoreElement, ElementAccess, Operator::kNoRead, 4, 0) 130 131 132 struct SimplifiedOperatorBuilderImpl FINAL { 133 #define PURE(Name, properties, input_count) \ 134 struct Name##Operator FINAL : public SimpleOperator { \ 135 Name##Operator() \ 136 : SimpleOperator(IrOpcode::k##Name, Operator::kPure | properties, \ 137 input_count, 1, #Name) {} \ 138 }; \ 139 Name##Operator k##Name; 140 PURE_OP_LIST(PURE) 141 #undef PURE 142 }; 143 144 145 static base::LazyInstance<SimplifiedOperatorBuilderImpl>::type kImpl = 146 LAZY_INSTANCE_INITIALIZER; 147 148 149 SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone) 150 : impl_(kImpl.Get()), zone_(zone) {} 151 152 153 #define PURE(Name, properties, input_count) \ 154 const Operator* SimplifiedOperatorBuilder::Name() { return &impl_.k##Name; } 155 PURE_OP_LIST(PURE) 156 #undef PURE 157 158 159 const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) { 160 // TODO(titzer): What about the type parameter? 161 return new (zone()) SimpleOperator(IrOpcode::kReferenceEqual, 162 Operator::kCommutative | Operator::kPure, 163 2, 1, "ReferenceEqual"); 164 } 165 166 167 #define ACCESS(Name, Type, properties, input_count, output_count) \ 168 const Operator* SimplifiedOperatorBuilder::Name(const Type& access) { \ 169 return new (zone()) \ 170 Operator1<Type>(IrOpcode::k##Name, Operator::kNoThrow | properties, \ 171 input_count, output_count, #Name, access); \ 172 } 173 ACCESS_OP_LIST(ACCESS) 174 #undef ACCESS 175 176 } // namespace compiler 177 } // namespace internal 178 } // namespace v8 179