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
3 // found in the LICENSE file.
5 #include "src/compiler/js-operator.h"
9 #include "src/base/lazy-instance.h"
10 #include "src/compiler/opcodes.h"
11 #include "src/compiler/operator.h"
17 bool operator==(CallFunctionParameters const& lhs,
18 CallFunctionParameters const& rhs) {
19 return lhs.arity() == rhs.arity() && lhs.flags() == rhs.flags();
23 bool operator!=(CallFunctionParameters const& lhs,
24 CallFunctionParameters const& rhs) {
29 size_t hash_value(CallFunctionParameters const& p) {
30 return base::hash_combine(p.arity(), p.flags());
34 std::ostream& operator<<(std::ostream& os, CallFunctionParameters const& p) {
35 return os << p.arity() << ", " << p.flags();
39 const CallFunctionParameters& CallFunctionParametersOf(const Operator* op) {
40 DCHECK_EQ(IrOpcode::kJSCallFunction, op->opcode());
41 return OpParameter<CallFunctionParameters>(op);
45 bool operator==(CallRuntimeParameters const& lhs,
46 CallRuntimeParameters const& rhs) {
47 return lhs.id() == rhs.id() && lhs.arity() == rhs.arity();
51 bool operator!=(CallRuntimeParameters const& lhs,
52 CallRuntimeParameters const& rhs) {
57 size_t hash_value(CallRuntimeParameters const& p) {
58 return base::hash_combine(p.id(), p.arity());
62 std::ostream& operator<<(std::ostream& os, CallRuntimeParameters const& p) {
63 return os << p.id() << ", " << p.arity();
67 const CallRuntimeParameters& CallRuntimeParametersOf(const Operator* op) {
68 DCHECK_EQ(IrOpcode::kJSCallRuntime, op->opcode());
69 return OpParameter<CallRuntimeParameters>(op);
73 ContextAccess::ContextAccess(size_t depth, size_t index, bool immutable)
74 : immutable_(immutable),
75 depth_(static_cast<uint16_t>(depth)),
76 index_(static_cast<uint32_t>(index)) {
77 DCHECK(depth <= std::numeric_limits<uint16_t>::max());
78 DCHECK(index <= std::numeric_limits<uint32_t>::max());
82 bool operator==(ContextAccess const& lhs, ContextAccess const& rhs) {
83 return lhs.depth() == rhs.depth() && lhs.index() == rhs.index() &&
84 lhs.immutable() == rhs.immutable();
88 bool operator!=(ContextAccess const& lhs, ContextAccess const& rhs) {
93 size_t hash_value(ContextAccess const& access) {
94 return base::hash_combine(access.depth(), access.index(), access.immutable());
98 std::ostream& operator<<(std::ostream& os, ContextAccess const& access) {
99 return os << access.depth() << ", " << access.index() << ", "
100 << access.immutable();
104 ContextAccess const& ContextAccessOf(Operator const* op) {
105 DCHECK(op->opcode() == IrOpcode::kJSLoadContext ||
106 op->opcode() == IrOpcode::kJSStoreContext);
107 return OpParameter<ContextAccess>(op);
111 bool operator==(VectorSlotPair const& lhs, VectorSlotPair const& rhs) {
112 return lhs.slot().ToInt() == rhs.slot().ToInt() &&
113 lhs.vector().is_identical_to(rhs.vector());
117 size_t hash_value(VectorSlotPair const& p) {
118 // TODO(mvstanton): include the vector in the hash.
120 return h(p.slot().ToInt());
124 bool operator==(LoadNamedParameters const& lhs,
125 LoadNamedParameters const& rhs) {
126 return lhs.name() == rhs.name() &&
127 lhs.contextual_mode() == rhs.contextual_mode() &&
128 lhs.feedback() == rhs.feedback();
132 bool operator!=(LoadNamedParameters const& lhs,
133 LoadNamedParameters const& rhs) {
134 return !(lhs == rhs);
138 size_t hash_value(LoadNamedParameters const& p) {
139 return base::hash_combine(p.name(), p.contextual_mode(), p.feedback());
143 std::ostream& operator<<(std::ostream& os, LoadNamedParameters const& p) {
144 return os << Brief(*p.name().handle()) << ", " << p.contextual_mode();
148 std::ostream& operator<<(std::ostream& os, LoadPropertyParameters const& p) {
149 // Nothing special to print.
154 bool operator==(LoadPropertyParameters const& lhs,
155 LoadPropertyParameters const& rhs) {
156 return lhs.feedback() == rhs.feedback();
160 bool operator!=(LoadPropertyParameters const& lhs,
161 LoadPropertyParameters const& rhs) {
162 return !(lhs == rhs);
166 const LoadPropertyParameters& LoadPropertyParametersOf(const Operator* op) {
167 DCHECK_EQ(IrOpcode::kJSLoadProperty, op->opcode());
168 return OpParameter<LoadPropertyParameters>(op);
172 size_t hash_value(LoadPropertyParameters const& p) {
173 return hash_value(p.feedback());
177 const LoadNamedParameters& LoadNamedParametersOf(const Operator* op) {
178 DCHECK_EQ(IrOpcode::kJSLoadNamed, op->opcode());
179 return OpParameter<LoadNamedParameters>(op);
183 bool operator==(StoreNamedParameters const& lhs,
184 StoreNamedParameters const& rhs) {
185 return lhs.language_mode() == rhs.language_mode() && lhs.name() == rhs.name();
189 bool operator!=(StoreNamedParameters const& lhs,
190 StoreNamedParameters const& rhs) {
191 return !(lhs == rhs);
195 size_t hash_value(StoreNamedParameters const& p) {
196 return base::hash_combine(p.language_mode(), p.name());
200 std::ostream& operator<<(std::ostream& os, StoreNamedParameters const& p) {
201 return os << p.language_mode() << ", " << Brief(*p.name().handle());
205 const StoreNamedParameters& StoreNamedParametersOf(const Operator* op) {
206 DCHECK_EQ(IrOpcode::kJSStoreNamed, op->opcode());
207 return OpParameter<StoreNamedParameters>(op);
211 #define CACHED_OP_LIST(V) \
212 V(Equal, Operator::kNoProperties, 2, 1) \
213 V(NotEqual, Operator::kNoProperties, 2, 1) \
214 V(StrictEqual, Operator::kPure, 2, 1) \
215 V(StrictNotEqual, Operator::kPure, 2, 1) \
216 V(LessThan, Operator::kNoProperties, 2, 1) \
217 V(GreaterThan, Operator::kNoProperties, 2, 1) \
218 V(LessThanOrEqual, Operator::kNoProperties, 2, 1) \
219 V(GreaterThanOrEqual, Operator::kNoProperties, 2, 1) \
220 V(BitwiseOr, Operator::kNoProperties, 2, 1) \
221 V(BitwiseXor, Operator::kNoProperties, 2, 1) \
222 V(BitwiseAnd, Operator::kNoProperties, 2, 1) \
223 V(ShiftLeft, Operator::kNoProperties, 2, 1) \
224 V(ShiftRight, Operator::kNoProperties, 2, 1) \
225 V(ShiftRightLogical, Operator::kNoProperties, 2, 1) \
226 V(Add, Operator::kNoProperties, 2, 1) \
227 V(Subtract, Operator::kNoProperties, 2, 1) \
228 V(Multiply, Operator::kNoProperties, 2, 1) \
229 V(Divide, Operator::kNoProperties, 2, 1) \
230 V(Modulus, Operator::kNoProperties, 2, 1) \
231 V(UnaryNot, Operator::kPure, 1, 1) \
232 V(ToBoolean, Operator::kPure, 1, 1) \
233 V(ToNumber, Operator::kNoProperties, 1, 1) \
234 V(ToString, Operator::kNoProperties, 1, 1) \
235 V(ToName, Operator::kNoProperties, 1, 1) \
236 V(ToObject, Operator::kNoProperties, 1, 1) \
237 V(Yield, Operator::kNoProperties, 1, 1) \
238 V(Create, Operator::kEliminatable, 0, 1) \
239 V(HasProperty, Operator::kNoProperties, 2, 1) \
240 V(TypeOf, Operator::kPure, 1, 1) \
241 V(InstanceOf, Operator::kNoProperties, 2, 1) \
242 V(Debugger, Operator::kNoProperties, 0, 0) \
243 V(CreateFunctionContext, Operator::kNoProperties, 1, 1) \
244 V(CreateWithContext, Operator::kNoProperties, 2, 1) \
245 V(CreateBlockContext, Operator::kNoProperties, 2, 1) \
246 V(CreateModuleContext, Operator::kNoProperties, 2, 1) \
247 V(CreateScriptContext, Operator::kNoProperties, 2, 1)
250 struct JSOperatorGlobalCache FINAL {
251 #define CACHED(Name, properties, value_input_count, value_output_count) \
252 struct Name##Operator FINAL : public Operator { \
254 : Operator(IrOpcode::kJS##Name, properties, "JS" #Name, \
255 value_input_count, Operator::ZeroIfPure(properties), \
256 Operator::ZeroIfPure(properties), value_output_count, \
257 Operator::ZeroIfPure(properties), 0) {} \
259 Name##Operator k##Name##Operator;
260 CACHED_OP_LIST(CACHED)
263 template <LanguageMode kLanguageMode>
264 struct StorePropertyOperator FINAL : public Operator1<LanguageMode> {
265 StorePropertyOperator()
266 : Operator1<LanguageMode>(IrOpcode::kJSStoreProperty,
267 Operator::kNoProperties, "JSStoreProperty", 3,
268 1, 1, 0, 1, 0, kLanguageMode) {}
270 StorePropertyOperator<SLOPPY> kStorePropertySloppyOperator;
271 StorePropertyOperator<STRICT> kStorePropertyStrictOperator;
275 static base::LazyInstance<JSOperatorGlobalCache>::type kCache =
276 LAZY_INSTANCE_INITIALIZER;
279 JSOperatorBuilder::JSOperatorBuilder(Zone* zone)
280 : cache_(kCache.Get()), zone_(zone) {}
283 #define CACHED(Name, properties, value_input_count, value_output_count) \
284 const Operator* JSOperatorBuilder::Name() { \
285 return &cache_.k##Name##Operator; \
287 CACHED_OP_LIST(CACHED)
291 const Operator* JSOperatorBuilder::CallFunction(size_t arity,
292 CallFunctionFlags flags) {
293 CallFunctionParameters parameters(arity, flags);
294 return new (zone()) Operator1<CallFunctionParameters>( // --
295 IrOpcode::kJSCallFunction, Operator::kNoProperties, // opcode
296 "JSCallFunction", // name
297 parameters.arity(), 1, 1, 1, 1, 0, // inputs/outputs
298 parameters); // parameter
302 const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id,
304 CallRuntimeParameters parameters(id, arity);
305 const Runtime::Function* f = Runtime::FunctionForId(parameters.id());
306 DCHECK(f->nargs == -1 || f->nargs == static_cast<int>(parameters.arity()));
307 return new (zone()) Operator1<CallRuntimeParameters>( // --
308 IrOpcode::kJSCallRuntime, Operator::kNoProperties, // opcode
309 "JSCallRuntime", // name
310 parameters.arity(), 1, 1, f->result_size, 1, 0, // inputs/outputs
311 parameters); // parameter
315 const Operator* JSOperatorBuilder::CallConstruct(int arguments) {
316 return new (zone()) Operator1<int>( // --
317 IrOpcode::kJSCallConstruct, Operator::kNoProperties, // opcode
318 "JSCallConstruct", // name
319 arguments, 1, 1, 1, 1, 0, // counts
320 arguments); // parameter
324 const Operator* JSOperatorBuilder::LoadNamed(const Unique<Name>& name,
325 const VectorSlotPair& feedback,
326 ContextualMode contextual_mode) {
327 LoadNamedParameters parameters(name, feedback, contextual_mode);
328 return new (zone()) Operator1<LoadNamedParameters>( // --
329 IrOpcode::kJSLoadNamed, Operator::kNoProperties, // opcode
330 "JSLoadNamed", // name
331 1, 1, 1, 1, 1, 0, // counts
332 parameters); // parameter
336 const Operator* JSOperatorBuilder::LoadProperty(
337 const VectorSlotPair& feedback) {
338 LoadPropertyParameters parameters(feedback);
339 return new (zone()) Operator1<LoadPropertyParameters>( // --
340 IrOpcode::kJSLoadProperty, Operator::kNoProperties, // opcode
341 "JSLoadProperty", // name
342 2, 1, 1, 1, 1, 0, // counts
343 parameters); // parameter
347 const Operator* JSOperatorBuilder::StoreProperty(LanguageMode language_mode) {
348 if (is_strict(language_mode)) {
349 return &cache_.kStorePropertyStrictOperator;
351 return &cache_.kStorePropertySloppyOperator;
358 const Operator* JSOperatorBuilder::StoreNamed(LanguageMode language_mode,
359 const Unique<Name>& name) {
360 StoreNamedParameters parameters(language_mode, name);
361 return new (zone()) Operator1<StoreNamedParameters>( // --
362 IrOpcode::kJSStoreNamed, Operator::kNoProperties, // opcode
363 "JSStoreNamed", // name
364 2, 1, 1, 0, 1, 0, // counts
365 parameters); // parameter
369 const Operator* JSOperatorBuilder::DeleteProperty(LanguageMode language_mode) {
370 return new (zone()) Operator1<LanguageMode>( // --
371 IrOpcode::kJSDeleteProperty, Operator::kNoProperties, // opcode
372 "JSDeleteProperty", // name
373 2, 1, 1, 1, 1, 0, // counts
374 language_mode); // parameter
378 const Operator* JSOperatorBuilder::LoadContext(size_t depth, size_t index,
380 ContextAccess access(depth, index, immutable);
381 return new (zone()) Operator1<ContextAccess>( // --
382 IrOpcode::kJSLoadContext, Operator::kNoWrite, // opcode
383 "JSLoadContext", // name
384 1, 1, 0, 1, 1, 0, // counts
385 access); // parameter
389 const Operator* JSOperatorBuilder::StoreContext(size_t depth, size_t index) {
390 ContextAccess access(depth, index, false);
391 return new (zone()) Operator1<ContextAccess>( // --
392 IrOpcode::kJSStoreContext, Operator::kNoRead, // opcode
393 "JSStoreContext", // name
394 2, 1, 1, 0, 1, 0, // counts
395 access); // parameter
399 const Operator* JSOperatorBuilder::CreateCatchContext(
400 const Unique<String>& name) {
401 return new (zone()) Operator1<Unique<String>>( // --
402 IrOpcode::kJSCreateCatchContext, Operator::kNoProperties, // opcode
403 "JSCreateCatchContext", // name
404 2, 1, 1, 1, 1, 0, // counts
408 } // namespace compiler
409 } // namespace internal