| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/common-operator.h" | 5 #include "src/compiler/common-operator.h" |
| 6 | 6 |
| 7 #include "src/assembler.h" | 7 #include "src/assembler.h" |
| 8 #include "src/base/lazy-instance.h" | 8 #include "src/base/lazy-instance.h" |
| 9 #include "src/compiler/linkage.h" | 9 #include "src/compiler/linkage.h" |
| 10 #include "src/unique.h" | 10 #include "src/unique.h" |
| 11 #include "src/zone.h" | 11 #include "src/zone.h" |
| 12 | 12 |
| 13 namespace v8 { | 13 namespace v8 { |
| 14 namespace internal { | 14 namespace internal { |
| 15 namespace compiler { | 15 namespace compiler { |
| 16 | 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 void PrintParameter(std::ostream& os) const FINAL {} | |
| 28 }; | |
| 29 | |
| 30 } // namespace | |
| 31 | |
| 32 | |
| 33 std::ostream& operator<<(std::ostream& os, BranchHint hint) { | 17 std::ostream& operator<<(std::ostream& os, BranchHint hint) { |
| 34 switch (hint) { | 18 switch (hint) { |
| 35 case BranchHint::kNone: | 19 case BranchHint::kNone: |
| 36 return os << "None"; | 20 return os << "None"; |
| 37 case BranchHint::kTrue: | 21 case BranchHint::kTrue: |
| 38 return os << "True"; | 22 return os << "True"; |
| 39 case BranchHint::kFalse: | 23 case BranchHint::kFalse: |
| 40 return os << "False"; | 24 return os << "False"; |
| 41 } | 25 } |
| 42 UNREACHABLE(); | 26 UNREACHABLE(); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 info.state_combine()); | 68 info.state_combine()); |
| 85 } | 69 } |
| 86 | 70 |
| 87 | 71 |
| 88 std::ostream& operator<<(std::ostream& os, FrameStateCallInfo const& info) { | 72 std::ostream& operator<<(std::ostream& os, FrameStateCallInfo const& info) { |
| 89 return os << info.type() << ", " << info.bailout_id() << ", " | 73 return os << info.type() << ", " << info.bailout_id() << ", " |
| 90 << info.state_combine(); | 74 << info.state_combine(); |
| 91 } | 75 } |
| 92 | 76 |
| 93 | 77 |
| 94 #define SHARED_OP_LIST(V) \ | 78 #define CACHED_OP_LIST(V) \ |
| 95 V(Dead, Operator::kFoldable, 0, 0) \ | 79 V(Dead, Operator::kFoldable, 0, 0, 0, 1) \ |
| 96 V(End, Operator::kFoldable, 0, 1) \ | 80 V(End, Operator::kFoldable, 0, 0, 1, 0) \ |
| 97 V(IfTrue, Operator::kFoldable, 0, 1) \ | 81 V(IfTrue, Operator::kFoldable, 0, 0, 1, 1) \ |
| 98 V(IfFalse, Operator::kFoldable, 0, 1) \ | 82 V(IfFalse, Operator::kFoldable, 0, 0, 1, 1) \ |
| 99 V(Throw, Operator::kFoldable, 1, 1) \ | 83 V(Throw, Operator::kFoldable, 1, 1, 1, 1) \ |
| 100 V(Return, Operator::kNoProperties, 1, 1) | 84 V(Return, Operator::kNoProperties, 1, 1, 1, 1) |
| 101 | 85 |
| 102 | 86 |
| 103 struct CommonOperatorBuilderImpl FINAL { | 87 struct CommonOperatorGlobalCache FINAL { |
| 104 #define SHARED(Name, properties, value_input_count, control_input_count) \ | 88 #define CACHED(Name, properties, value_input_count, effect_input_count, \ |
| 105 struct Name##Operator FINAL : public ControlOperator { \ | 89 control_input_count, control_output_count) \ |
| 106 Name##Operator() \ | 90 struct Name##Operator FINAL : public Operator { \ |
| 107 : ControlOperator(IrOpcode::k##Name, properties, value_input_count, 0, \ | 91 Name##Operator() \ |
| 108 control_input_count, #Name) {} \ | 92 : Operator(IrOpcode::k##Name, properties, #Name, value_input_count, \ |
| 109 }; \ | 93 effect_input_count, control_input_count, 0, 0, \ |
| 94 control_output_count) {} \ |
| 95 }; \ |
| 110 Name##Operator k##Name##Operator; | 96 Name##Operator k##Name##Operator; |
| 111 SHARED_OP_LIST(SHARED) | 97 CACHED_OP_LIST(CACHED) |
| 112 #undef SHARED | 98 #undef CACHED |
| 113 }; | 99 }; |
| 114 | 100 |
| 115 | 101 |
| 116 static base::LazyInstance<CommonOperatorBuilderImpl>::type kImpl = | 102 static base::LazyInstance<CommonOperatorGlobalCache>::type kCache = |
| 117 LAZY_INSTANCE_INITIALIZER; | 103 LAZY_INSTANCE_INITIALIZER; |
| 118 | 104 |
| 119 | 105 |
| 120 CommonOperatorBuilder::CommonOperatorBuilder(Zone* zone) | 106 CommonOperatorBuilder::CommonOperatorBuilder(Zone* zone) |
| 121 : impl_(kImpl.Get()), zone_(zone) {} | 107 : cache_(kCache.Get()), zone_(zone) {} |
| 122 | 108 |
| 123 | 109 |
| 124 #define SHARED(Name, properties, value_input_count, control_input_count) \ | 110 #define CACHED(Name, properties, value_input_count, effect_input_count, \ |
| 125 const Operator* CommonOperatorBuilder::Name() { \ | 111 control_input_count, control_output_count) \ |
| 126 return &impl_.k##Name##Operator; \ | 112 const Operator* CommonOperatorBuilder::Name() { \ |
| 113 return &cache_.k##Name##Operator; \ |
| 127 } | 114 } |
| 128 SHARED_OP_LIST(SHARED) | 115 CACHED_OP_LIST(CACHED) |
| 129 #undef SHARED | 116 #undef CACHED |
| 130 | 117 |
| 131 | 118 |
| 132 const Operator* CommonOperatorBuilder::Branch(BranchHint hint) { | 119 const Operator* CommonOperatorBuilder::Branch(BranchHint hint) { |
| 133 return new (zone()) Operator1<BranchHint>( | 120 return new (zone()) Operator1<BranchHint>( |
| 134 IrOpcode::kBranch, Operator::kFoldable, 1, 0, "Branch", hint); | 121 IrOpcode::kBranch, Operator::kFoldable, "Branch", 1, 0, 1, 0, 0, 2, hint); |
| 135 } | 122 } |
| 136 | 123 |
| 137 | 124 |
| 138 const Operator* CommonOperatorBuilder::Start(int num_formal_parameters) { | 125 const Operator* CommonOperatorBuilder::Start(int num_formal_parameters) { |
| 139 // Outputs are formal parameters, plus context, receiver, and JSFunction. | 126 // Outputs are formal parameters, plus context, receiver, and JSFunction. |
| 140 const int value_output_count = num_formal_parameters + 3; | 127 const int value_output_count = num_formal_parameters + 3; |
| 141 return new (zone()) ControlOperator(IrOpcode::kStart, Operator::kFoldable, 0, | 128 return new (zone()) Operator( // -- |
| 142 value_output_count, 0, "Start"); | 129 IrOpcode::kStart, Operator::kFoldable, // opcode |
| 130 "Start", // name |
| 131 0, 0, 0, value_output_count, 1, 1); // counts |
| 143 } | 132 } |
| 144 | 133 |
| 145 | 134 |
| 146 const Operator* CommonOperatorBuilder::Merge(int controls) { | 135 const Operator* CommonOperatorBuilder::Merge(int controls) { |
| 147 return new (zone()) ControlOperator(IrOpcode::kMerge, Operator::kFoldable, 0, | 136 return new (zone()) Operator( // -- |
| 148 0, controls, "Merge"); | 137 IrOpcode::kMerge, Operator::kFoldable, // opcode |
| 138 "Merge", // name |
| 139 0, 0, controls, 0, 0, 1); // counts |
| 149 } | 140 } |
| 150 | 141 |
| 151 | 142 |
| 152 const Operator* CommonOperatorBuilder::Loop(int controls) { | 143 const Operator* CommonOperatorBuilder::Loop(int controls) { |
| 153 return new (zone()) ControlOperator(IrOpcode::kLoop, Operator::kFoldable, 0, | 144 return new (zone()) Operator( // -- |
| 154 0, controls, "Loop"); | 145 IrOpcode::kLoop, Operator::kFoldable, // opcode |
| 146 "Loop", // name |
| 147 0, 0, controls, 0, 0, 1); // counts |
| 155 } | 148 } |
| 156 | 149 |
| 157 | 150 |
| 158 const Operator* CommonOperatorBuilder::Terminate(int effects) { | 151 const Operator* CommonOperatorBuilder::Terminate(int effects) { |
| 159 return new (zone()) Operator1<int>(IrOpcode::kTerminate, | 152 return new (zone()) Operator( // -- |
| 160 Operator::kNoRead | Operator::kNoWrite, 0, | 153 IrOpcode::kTerminate, Operator::kPure, // opcode |
| 161 0, "Terminate", effects); | 154 "Terminate", // name |
| 155 0, effects, 1, 0, 0, 1); // counts |
| 162 } | 156 } |
| 163 | 157 |
| 164 | 158 |
| 165 const Operator* CommonOperatorBuilder::Parameter(int index) { | 159 const Operator* CommonOperatorBuilder::Parameter(int index) { |
| 166 return new (zone()) Operator1<int>(IrOpcode::kParameter, Operator::kPure, 1, | 160 return new (zone()) Operator1<int>( // -- |
| 167 1, "Parameter", index); | 161 IrOpcode::kParameter, Operator::kPure, // opcode |
| 162 "Parameter", // name |
| 163 1, 0, 0, 1, 0, 0, // counts |
| 164 index); // parameter |
| 168 } | 165 } |
| 169 | 166 |
| 170 | 167 |
| 171 const Operator* CommonOperatorBuilder::Int32Constant(int32_t value) { | 168 const Operator* CommonOperatorBuilder::Int32Constant(int32_t value) { |
| 172 return new (zone()) Operator1<int32_t>( | 169 return new (zone()) Operator1<int32_t>( // -- |
| 173 IrOpcode::kInt32Constant, Operator::kPure, 0, 1, "Int32Constant", value); | 170 IrOpcode::kInt32Constant, Operator::kPure, // opcode |
| 171 "Int32Constant", // name |
| 172 0, 0, 0, 1, 0, 0, // counts |
| 173 value); // parameter |
| 174 } | 174 } |
| 175 | 175 |
| 176 | 176 |
| 177 const Operator* CommonOperatorBuilder::Int64Constant(int64_t value) { | 177 const Operator* CommonOperatorBuilder::Int64Constant(int64_t value) { |
| 178 return new (zone()) Operator1<int64_t>( | 178 return new (zone()) Operator1<int64_t>( // -- |
| 179 IrOpcode::kInt64Constant, Operator::kPure, 0, 1, "Int64Constant", value); | 179 IrOpcode::kInt64Constant, Operator::kPure, // opcode |
| 180 "Int64Constant", // name |
| 181 0, 0, 0, 1, 0, 0, // counts |
| 182 value); // parameter |
| 180 } | 183 } |
| 181 | 184 |
| 182 | 185 |
| 183 const Operator* CommonOperatorBuilder::Float32Constant(volatile float value) { | 186 const Operator* CommonOperatorBuilder::Float32Constant(volatile float value) { |
| 184 return new (zone()) | 187 return new (zone()) |
| 185 Operator1<float, base::bit_equal_to<float>, base::bit_hash<float>>( | 188 Operator1<float, base::bit_equal_to<float>, base::bit_hash<float>>( // -- |
| 186 IrOpcode::kFloat32Constant, Operator::kPure, 0, 1, "Float32Constant", | 189 IrOpcode::kFloat32Constant, Operator::kPure, // opcode |
| 187 value); | 190 "Float32Constant", // name |
| 191 0, 0, 0, 1, 0, 0, // counts |
| 192 value); // parameter |
| 188 } | 193 } |
| 189 | 194 |
| 190 | 195 |
| 191 const Operator* CommonOperatorBuilder::Float64Constant(volatile double value) { | 196 const Operator* CommonOperatorBuilder::Float64Constant(volatile double value) { |
| 192 return new (zone()) | 197 return new (zone()) Operator1<double, base::bit_equal_to<double>, |
| 193 Operator1<double, base::bit_equal_to<double>, base::bit_hash<double>>( | 198 base::bit_hash<double>>( // -- |
| 194 IrOpcode::kFloat64Constant, Operator::kPure, 0, 1, "Float64Constant", | 199 IrOpcode::kFloat64Constant, Operator::kPure, // opcode |
| 195 value); | 200 "Float64Constant", // name |
| 201 0, 0, 0, 1, 0, 0, // counts |
| 202 value); // parameter |
| 196 } | 203 } |
| 197 | 204 |
| 198 | 205 |
| 199 const Operator* CommonOperatorBuilder::ExternalConstant( | 206 const Operator* CommonOperatorBuilder::ExternalConstant( |
| 200 const ExternalReference& value) { | 207 const ExternalReference& value) { |
| 201 return new (zone()) | 208 return new (zone()) Operator1<ExternalReference>( // -- |
| 202 Operator1<ExternalReference>(IrOpcode::kExternalConstant, Operator::kPure, | 209 IrOpcode::kExternalConstant, Operator::kPure, // opcode |
| 203 0, 1, "ExternalConstant", value); | 210 "ExternalConstant", // name |
| 211 0, 0, 0, 1, 0, 0, // counts |
| 212 value); // parameter |
| 204 } | 213 } |
| 205 | 214 |
| 206 | 215 |
| 207 const Operator* CommonOperatorBuilder::NumberConstant(volatile double value) { | 216 const Operator* CommonOperatorBuilder::NumberConstant(volatile double value) { |
| 208 return new (zone()) | 217 return new (zone()) Operator1<double, base::bit_equal_to<double>, |
| 209 Operator1<double, base::bit_equal_to<double>, base::bit_hash<double>>( | 218 base::bit_hash<double>>( // -- |
| 210 IrOpcode::kNumberConstant, Operator::kPure, 0, 1, "NumberConstant", | 219 IrOpcode::kNumberConstant, Operator::kPure, // opcode |
| 211 value); | 220 "NumberConstant", // name |
| 221 0, 0, 0, 1, 0, 0, // counts |
| 222 value); // parameter |
| 212 } | 223 } |
| 213 | 224 |
| 214 | 225 |
| 215 const Operator* CommonOperatorBuilder::HeapConstant( | 226 const Operator* CommonOperatorBuilder::HeapConstant( |
| 216 const Unique<HeapObject>& value) { | 227 const Unique<HeapObject>& value) { |
| 217 return new (zone()) Operator1<Unique<HeapObject>>( | 228 return new (zone()) Operator1<Unique<HeapObject>>( // -- |
| 218 IrOpcode::kHeapConstant, Operator::kPure, 0, 1, "HeapConstant", value); | 229 IrOpcode::kHeapConstant, Operator::kPure, // opcode |
| 230 "HeapConstant", // name |
| 231 0, 0, 0, 1, 0, 0, // counts |
| 232 value); // parameter |
| 219 } | 233 } |
| 220 | 234 |
| 221 | 235 |
| 222 const Operator* CommonOperatorBuilder::Phi(MachineType type, int arguments) { | 236 const Operator* CommonOperatorBuilder::Phi(MachineType type, int arguments) { |
| 223 DCHECK(arguments > 0); // Disallow empty phis. | 237 DCHECK(arguments > 0); // Disallow empty phis. |
| 224 return new (zone()) Operator1<MachineType>(IrOpcode::kPhi, Operator::kPure, | 238 return new (zone()) Operator1<MachineType>( // -- |
| 225 arguments, 1, "Phi", type); | 239 IrOpcode::kPhi, Operator::kPure, // opcode |
| 240 "Phi", // name |
| 241 arguments, 0, 1, 1, 0, 0, // counts |
| 242 type); // parameter |
| 226 } | 243 } |
| 227 | 244 |
| 228 | 245 |
| 229 const Operator* CommonOperatorBuilder::EffectPhi(int arguments) { | 246 const Operator* CommonOperatorBuilder::EffectPhi(int arguments) { |
| 230 DCHECK(arguments > 0); // Disallow empty phis. | 247 DCHECK(arguments > 0); // Disallow empty phis. |
| 231 return new (zone()) Operator1<int>(IrOpcode::kEffectPhi, Operator::kPure, 0, | 248 return new (zone()) Operator( // -- |
| 232 0, "EffectPhi", arguments); | 249 IrOpcode::kEffectPhi, Operator::kPure, // opcode |
| 250 "EffectPhi", // name |
| 251 0, arguments, 1, 0, 1, 0); // counts |
| 233 } | 252 } |
| 234 | 253 |
| 235 | 254 |
| 236 const Operator* CommonOperatorBuilder::ValueEffect(int arguments) { | 255 const Operator* CommonOperatorBuilder::ValueEffect(int arguments) { |
| 237 DCHECK(arguments > 0); // Disallow empty value effects. | 256 DCHECK(arguments > 0); // Disallow empty value effects. |
| 238 return new (zone()) Operator1<int>(IrOpcode::kValueEffect, Operator::kPure, | 257 return new (zone()) Operator( // -- |
| 239 arguments, 0, "ValueEffect", arguments); | 258 IrOpcode::kValueEffect, Operator::kPure, // opcode |
| 259 "ValueEffect", // name |
| 260 arguments, 0, 0, 0, 1, 0); // counts |
| 240 } | 261 } |
| 241 | 262 |
| 242 | 263 |
| 243 const Operator* CommonOperatorBuilder::Finish(int arguments) { | 264 const Operator* CommonOperatorBuilder::Finish(int arguments) { |
| 244 DCHECK(arguments > 0); // Disallow empty finishes. | 265 DCHECK(arguments > 0); // Disallow empty finishes. |
| 245 return new (zone()) Operator1<int>(IrOpcode::kFinish, Operator::kPure, 1, 1, | 266 return new (zone()) Operator( // -- |
| 246 "Finish", arguments); | 267 IrOpcode::kFinish, Operator::kPure, // opcode |
| 268 "Finish", // name |
| 269 1, arguments, 0, 1, 0, 0); // counts |
| 247 } | 270 } |
| 248 | 271 |
| 249 | 272 |
| 250 const Operator* CommonOperatorBuilder::StateValues(int arguments) { | 273 const Operator* CommonOperatorBuilder::StateValues(int arguments) { |
| 251 return new (zone()) Operator1<int>(IrOpcode::kStateValues, Operator::kPure, | 274 return new (zone()) Operator( // -- |
| 252 arguments, 1, "StateValues", arguments); | 275 IrOpcode::kStateValues, Operator::kPure, // opcode |
| 276 "StateValues", // name |
| 277 arguments, 0, 0, 1, 0, 0); // counts |
| 253 } | 278 } |
| 254 | 279 |
| 255 | 280 |
| 256 const Operator* CommonOperatorBuilder::FrameState( | 281 const Operator* CommonOperatorBuilder::FrameState( |
| 257 FrameStateType type, BailoutId bailout_id, | 282 FrameStateType type, BailoutId bailout_id, |
| 258 OutputFrameStateCombine state_combine, MaybeHandle<JSFunction> jsfunction) { | 283 OutputFrameStateCombine state_combine, MaybeHandle<JSFunction> jsfunction) { |
| 259 return new (zone()) Operator1<FrameStateCallInfo>( | 284 return new (zone()) Operator1<FrameStateCallInfo>( // -- |
| 260 IrOpcode::kFrameState, Operator::kPure, 4, 1, "FrameState", | 285 IrOpcode::kFrameState, Operator::kPure, // opcode |
| 286 "FrameState", // name |
| 287 4, 0, 0, 1, 0, 0, // counts |
| 261 FrameStateCallInfo(type, bailout_id, state_combine, jsfunction)); | 288 FrameStateCallInfo(type, bailout_id, state_combine, jsfunction)); |
| 262 } | 289 } |
| 263 | 290 |
| 264 | 291 |
| 265 const Operator* CommonOperatorBuilder::Call(const CallDescriptor* descriptor) { | 292 const Operator* CommonOperatorBuilder::Call(const CallDescriptor* descriptor) { |
| 266 class CallOperator FINAL : public Operator1<const CallDescriptor*> { | 293 class CallOperator FINAL : public Operator1<const CallDescriptor*> { |
| 267 public: | 294 public: |
| 268 // TODO(titzer): Operator still uses int, whereas CallDescriptor uses | |
| 269 // size_t. | |
| 270 CallOperator(const CallDescriptor* descriptor, const char* mnemonic) | 295 CallOperator(const CallDescriptor* descriptor, const char* mnemonic) |
| 271 : Operator1<const CallDescriptor*>( | 296 : Operator1<const CallDescriptor*>( |
| 272 IrOpcode::kCall, descriptor->properties(), | 297 IrOpcode::kCall, descriptor->properties(), mnemonic, |
| 273 static_cast<int>(descriptor->InputCount() + | 298 descriptor->InputCount() + descriptor->FrameStateCount(), |
| 274 descriptor->FrameStateCount()), | 299 Operator::ZeroIfPure(descriptor->properties()), |
| 275 static_cast<int>(descriptor->ReturnCount()), mnemonic, | 300 Operator::ZeroIfPure(descriptor->properties()), |
| 276 descriptor) {} | 301 descriptor->ReturnCount(), |
| 302 Operator::ZeroIfPure(descriptor->properties()), 0, descriptor) {} |
| 277 | 303 |
| 278 virtual void PrintParameter(std::ostream& os) const OVERRIDE { | 304 virtual void PrintParameter(std::ostream& os) const OVERRIDE { |
| 279 os << "[" << *parameter() << "]"; | 305 os << "[" << *parameter() << "]"; |
| 280 } | 306 } |
| 281 }; | 307 }; |
| 282 return new (zone()) CallOperator(descriptor, "Call"); | 308 return new (zone()) CallOperator(descriptor, "Call"); |
| 283 } | 309 } |
| 284 | 310 |
| 285 | 311 |
| 286 const Operator* CommonOperatorBuilder::Projection(size_t index) { | 312 const Operator* CommonOperatorBuilder::Projection(size_t index) { |
| 287 return new (zone()) Operator1<size_t>(IrOpcode::kProjection, Operator::kPure, | 313 return new (zone()) Operator1<size_t>( // -- |
| 288 1, 1, "Projection", index); | 314 IrOpcode::kProjection, Operator::kPure, // opcode |
| 315 "Projection", // name |
| 316 1, 0, 0, 1, 0, 0, // counts |
| 317 index); // parameter |
| 289 } | 318 } |
| 290 | 319 |
| 291 } // namespace compiler | 320 } // namespace compiler |
| 292 } // namespace internal | 321 } // namespace internal |
| 293 } // namespace v8 | 322 } // namespace v8 |
| OLD | NEW |