deps: update v8 to 4.3.61.21
[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(StackCheck, 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::ZeroIfEliminatable(properties),             \
257                    value_output_count, Operator::ZeroIfPure(properties), \
258                    Operator::ZeroIfNoThrow(properties)) {}               \
259   };                                                                     \
260   Name##Operator k##Name##Operator;
261   CACHED_OP_LIST(CACHED)
262 #undef CACHED
263
264   template <LanguageMode kLanguageMode>
265   struct StorePropertyOperator FINAL : public Operator1<LanguageMode> {
266     StorePropertyOperator()
267         : Operator1<LanguageMode>(IrOpcode::kJSStoreProperty,
268                                   Operator::kNoProperties, "JSStoreProperty", 3,
269                                   1, 1, 0, 1, 2, kLanguageMode) {}
270   };
271   StorePropertyOperator<SLOPPY> kStorePropertySloppyOperator;
272   StorePropertyOperator<STRICT> kStorePropertyStrictOperator;
273 };
274
275
276 static base::LazyInstance<JSOperatorGlobalCache>::type kCache =
277     LAZY_INSTANCE_INITIALIZER;
278
279
280 JSOperatorBuilder::JSOperatorBuilder(Zone* zone)
281     : cache_(kCache.Get()), zone_(zone) {}
282
283
284 #define CACHED(Name, properties, value_input_count, value_output_count) \
285   const Operator* JSOperatorBuilder::Name() {                           \
286     return &cache_.k##Name##Operator;                                   \
287   }
288 CACHED_OP_LIST(CACHED)
289 #undef CACHED
290
291
292 const Operator* JSOperatorBuilder::CallFunction(size_t arity,
293                                                 CallFunctionFlags flags) {
294   CallFunctionParameters parameters(arity, flags);
295   return new (zone()) Operator1<CallFunctionParameters>(   // --
296       IrOpcode::kJSCallFunction, Operator::kNoProperties,  // opcode
297       "JSCallFunction",                                    // name
298       parameters.arity(), 1, 1, 1, 1, 2,                   // inputs/outputs
299       parameters);                                         // parameter
300 }
301
302
303 const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id,
304                                                size_t arity) {
305   CallRuntimeParameters parameters(id, arity);
306   const Runtime::Function* f = Runtime::FunctionForId(parameters.id());
307   DCHECK(f->nargs == -1 || f->nargs == static_cast<int>(parameters.arity()));
308   return new (zone()) Operator1<CallRuntimeParameters>(   // --
309       IrOpcode::kJSCallRuntime, Operator::kNoProperties,  // opcode
310       "JSCallRuntime",                                    // name
311       parameters.arity(), 1, 1, f->result_size, 1, 2,     // inputs/outputs
312       parameters);                                        // parameter
313 }
314
315
316 const Operator* JSOperatorBuilder::CallConstruct(int arguments) {
317   return new (zone()) Operator1<int>(                       // --
318       IrOpcode::kJSCallConstruct, Operator::kNoProperties,  // opcode
319       "JSCallConstruct",                                    // name
320       arguments, 1, 1, 1, 1, 2,                             // counts
321       arguments);                                           // parameter
322 }
323
324
325 const Operator* JSOperatorBuilder::LoadNamed(const Unique<Name>& name,
326                                              const VectorSlotPair& feedback,
327                                              ContextualMode contextual_mode) {
328   LoadNamedParameters parameters(name, feedback, contextual_mode);
329   return new (zone()) Operator1<LoadNamedParameters>(   // --
330       IrOpcode::kJSLoadNamed, Operator::kNoProperties,  // opcode
331       "JSLoadNamed",                                    // name
332       1, 1, 1, 1, 1, 2,                                 // counts
333       parameters);                                      // parameter
334 }
335
336
337 const Operator* JSOperatorBuilder::LoadProperty(
338     const VectorSlotPair& feedback) {
339   LoadPropertyParameters parameters(feedback);
340   return new (zone()) Operator1<LoadPropertyParameters>(   // --
341       IrOpcode::kJSLoadProperty, Operator::kNoProperties,  // opcode
342       "JSLoadProperty",                                    // name
343       2, 1, 1, 1, 1, 2,                                    // counts
344       parameters);                                         // parameter
345 }
346
347
348 const Operator* JSOperatorBuilder::StoreProperty(LanguageMode language_mode) {
349   if (is_strict(language_mode)) {
350     return &cache_.kStorePropertyStrictOperator;
351   } else {
352     return &cache_.kStorePropertySloppyOperator;
353   }
354   UNREACHABLE();
355   return nullptr;
356 }
357
358
359 const Operator* JSOperatorBuilder::StoreNamed(LanguageMode language_mode,
360                                               const Unique<Name>& name) {
361   StoreNamedParameters parameters(language_mode, name);
362   return new (zone()) Operator1<StoreNamedParameters>(   // --
363       IrOpcode::kJSStoreNamed, Operator::kNoProperties,  // opcode
364       "JSStoreNamed",                                    // name
365       2, 1, 1, 0, 1, 2,                                  // counts
366       parameters);                                       // parameter
367 }
368
369
370 const Operator* JSOperatorBuilder::DeleteProperty(LanguageMode language_mode) {
371   return new (zone()) Operator1<LanguageMode>(               // --
372       IrOpcode::kJSDeleteProperty, Operator::kNoProperties,  // opcode
373       "JSDeleteProperty",                                    // name
374       2, 1, 1, 1, 1, 2,                                      // counts
375       language_mode);                                        // parameter
376 }
377
378
379 const Operator* JSOperatorBuilder::LoadContext(size_t depth, size_t index,
380                                                bool immutable) {
381   ContextAccess access(depth, index, immutable);
382   return new (zone()) Operator1<ContextAccess>(  // --
383       IrOpcode::kJSLoadContext,                  // opcode
384       Operator::kNoWrite | Operator::kNoThrow,   // flags
385       "JSLoadContext",                           // name
386       1, 1, 0, 1, 1, 0,                          // counts
387       access);                                   // parameter
388 }
389
390
391 const Operator* JSOperatorBuilder::StoreContext(size_t depth, size_t index) {
392   ContextAccess access(depth, index, false);
393   return new (zone()) Operator1<ContextAccess>(  // --
394       IrOpcode::kJSStoreContext,                 // opcode
395       Operator::kNoRead | Operator::kNoThrow,    // flags
396       "JSStoreContext",                          // name
397       2, 1, 1, 0, 1, 0,                          // counts
398       access);                                   // parameter
399 }
400
401
402 const Operator* JSOperatorBuilder::CreateCatchContext(
403     const Unique<String>& name) {
404   return new (zone()) Operator1<Unique<String>>(                 // --
405       IrOpcode::kJSCreateCatchContext, Operator::kNoProperties,  // opcode
406       "JSCreateCatchContext",                                    // name
407       2, 1, 1, 1, 1, 2,                                          // counts
408       name);                                                     // parameter
409 }
410
411 }  // namespace compiler
412 }  // namespace internal
413 }  // namespace v8