72c39697b46b72bc7ae38fc83088ac9ddc8e8f6d
[platform/upstream/nodejs.git] / deps / v8 / src / compiler / js-operator.cc
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.
4
5 #include "src/compiler/js-operator.h"
6
7 #include <limits>
8
9 #include "src/base/lazy-instance.h"
10 #include "src/compiler/opcodes.h"
11 #include "src/compiler/operator.h"
12
13 namespace v8 {
14 namespace internal {
15 namespace compiler {
16
17 bool operator==(CallFunctionParameters const& lhs,
18                 CallFunctionParameters const& rhs) {
19   return lhs.arity() == rhs.arity() && lhs.flags() == rhs.flags();
20 }
21
22
23 bool operator!=(CallFunctionParameters const& lhs,
24                 CallFunctionParameters const& rhs) {
25   return !(lhs == rhs);
26 }
27
28
29 size_t hash_value(CallFunctionParameters const& p) {
30   return base::hash_combine(p.arity(), p.flags());
31 }
32
33
34 std::ostream& operator<<(std::ostream& os, CallFunctionParameters const& p) {
35   return os << p.arity() << ", " << p.flags();
36 }
37
38
39 const CallFunctionParameters& CallFunctionParametersOf(const Operator* op) {
40   DCHECK_EQ(IrOpcode::kJSCallFunction, op->opcode());
41   return OpParameter<CallFunctionParameters>(op);
42 }
43
44
45 bool operator==(CallRuntimeParameters const& lhs,
46                 CallRuntimeParameters const& rhs) {
47   return lhs.id() == rhs.id() && lhs.arity() == rhs.arity();
48 }
49
50
51 bool operator!=(CallRuntimeParameters const& lhs,
52                 CallRuntimeParameters const& rhs) {
53   return !(lhs == rhs);
54 }
55
56
57 size_t hash_value(CallRuntimeParameters const& p) {
58   return base::hash_combine(p.id(), p.arity());
59 }
60
61
62 std::ostream& operator<<(std::ostream& os, CallRuntimeParameters const& p) {
63   return os << p.id() << ", " << p.arity();
64 }
65
66
67 const CallRuntimeParameters& CallRuntimeParametersOf(const Operator* op) {
68   DCHECK_EQ(IrOpcode::kJSCallRuntime, op->opcode());
69   return OpParameter<CallRuntimeParameters>(op);
70 }
71
72
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());
79 }
80
81
82 bool operator==(ContextAccess const& lhs, ContextAccess const& rhs) {
83   return lhs.depth() == rhs.depth() && lhs.index() == rhs.index() &&
84          lhs.immutable() == rhs.immutable();
85 }
86
87
88 bool operator!=(ContextAccess const& lhs, ContextAccess const& rhs) {
89   return !(lhs == rhs);
90 }
91
92
93 size_t hash_value(ContextAccess const& access) {
94   return base::hash_combine(access.depth(), access.index(), access.immutable());
95 }
96
97
98 std::ostream& operator<<(std::ostream& os, ContextAccess const& access) {
99   return os << access.depth() << ", " << access.index() << ", "
100             << access.immutable();
101 }
102
103
104 ContextAccess const& ContextAccessOf(Operator const* op) {
105   DCHECK(op->opcode() == IrOpcode::kJSLoadContext ||
106          op->opcode() == IrOpcode::kJSStoreContext);
107   return OpParameter<ContextAccess>(op);
108 }
109
110
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());
114 }
115
116
117 size_t hash_value(VectorSlotPair const& p) {
118   // TODO(mvstanton): include the vector in the hash.
119   base::hash<int> h;
120   return h(p.slot().ToInt());
121 }
122
123
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();
129 }
130
131
132 bool operator!=(LoadNamedParameters const& lhs,
133                 LoadNamedParameters const& rhs) {
134   return !(lhs == rhs);
135 }
136
137
138 size_t hash_value(LoadNamedParameters const& p) {
139   return base::hash_combine(p.name(), p.contextual_mode(), p.feedback());
140 }
141
142
143 std::ostream& operator<<(std::ostream& os, LoadNamedParameters const& p) {
144   return os << Brief(*p.name().handle()) << ", " << p.contextual_mode();
145 }
146
147
148 std::ostream& operator<<(std::ostream& os, LoadPropertyParameters const& p) {
149   // Nothing special to print.
150   return os;
151 }
152
153
154 bool operator==(LoadPropertyParameters const& lhs,
155                 LoadPropertyParameters const& rhs) {
156   return lhs.feedback() == rhs.feedback();
157 }
158
159
160 bool operator!=(LoadPropertyParameters const& lhs,
161                 LoadPropertyParameters const& rhs) {
162   return !(lhs == rhs);
163 }
164
165
166 const LoadPropertyParameters& LoadPropertyParametersOf(const Operator* op) {
167   DCHECK_EQ(IrOpcode::kJSLoadProperty, op->opcode());
168   return OpParameter<LoadPropertyParameters>(op);
169 }
170
171
172 size_t hash_value(LoadPropertyParameters const& p) {
173   return hash_value(p.feedback());
174 }
175
176
177 const LoadNamedParameters& LoadNamedParametersOf(const Operator* op) {
178   DCHECK_EQ(IrOpcode::kJSLoadNamed, op->opcode());
179   return OpParameter<LoadNamedParameters>(op);
180 }
181
182
183 bool operator==(StoreNamedParameters const& lhs,
184                 StoreNamedParameters const& rhs) {
185   return lhs.language_mode() == rhs.language_mode() && lhs.name() == rhs.name();
186 }
187
188
189 bool operator!=(StoreNamedParameters const& lhs,
190                 StoreNamedParameters const& rhs) {
191   return !(lhs == rhs);
192 }
193
194
195 size_t hash_value(StoreNamedParameters const& p) {
196   return base::hash_combine(p.language_mode(), p.name());
197 }
198
199
200 std::ostream& operator<<(std::ostream& os, StoreNamedParameters const& p) {
201   return os << p.language_mode() << ", " << Brief(*p.name().handle());
202 }
203
204
205 const StoreNamedParameters& StoreNamedParametersOf(const Operator* op) {
206   DCHECK_EQ(IrOpcode::kJSStoreNamed, op->opcode());
207   return OpParameter<StoreNamedParameters>(op);
208 }
209
210
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)
248
249
250 struct JSOperatorGlobalCache FINAL {
251 #define CACHED(Name, properties, value_input_count, value_output_count)  \
252   struct Name##Operator FINAL : public Operator {                        \
253     Name##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) {}               \
258   };                                                                     \
259   Name##Operator k##Name##Operator;
260   CACHED_OP_LIST(CACHED)
261 #undef CACHED
262
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) {}
269   };
270   StorePropertyOperator<SLOPPY> kStorePropertySloppyOperator;
271   StorePropertyOperator<STRICT> kStorePropertyStrictOperator;
272 };
273
274
275 static base::LazyInstance<JSOperatorGlobalCache>::type kCache =
276     LAZY_INSTANCE_INITIALIZER;
277
278
279 JSOperatorBuilder::JSOperatorBuilder(Zone* zone)
280     : cache_(kCache.Get()), zone_(zone) {}
281
282
283 #define CACHED(Name, properties, value_input_count, value_output_count) \
284   const Operator* JSOperatorBuilder::Name() {                           \
285     return &cache_.k##Name##Operator;                                   \
286   }
287 CACHED_OP_LIST(CACHED)
288 #undef CACHED
289
290
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
299 }
300
301
302 const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id,
303                                                size_t arity) {
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
312 }
313
314
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
321 }
322
323
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
333 }
334
335
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
344 }
345
346
347 const Operator* JSOperatorBuilder::StoreProperty(LanguageMode language_mode) {
348   if (is_strict(language_mode)) {
349     return &cache_.kStorePropertyStrictOperator;
350   } else {
351     return &cache_.kStorePropertySloppyOperator;
352   }
353   UNREACHABLE();
354   return nullptr;
355 }
356
357
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
366 }
367
368
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
375 }
376
377
378 const Operator* JSOperatorBuilder::LoadContext(size_t depth, size_t index,
379                                                bool immutable) {
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
386 }
387
388
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
396 }
397
398
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
405       name);                                                     // parameter
406 }
407
408 }  // namespace compiler
409 }  // namespace internal
410 }  // namespace v8