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(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)
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::ZeroIfEliminatable(properties), \
257 value_output_count, Operator::ZeroIfPure(properties), \
258 Operator::ZeroIfNoThrow(properties)) {} \
260 Name##Operator k##Name##Operator;
261 CACHED_OP_LIST(CACHED)
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) {}
271 StorePropertyOperator<SLOPPY> kStorePropertySloppyOperator;
272 StorePropertyOperator<STRICT> kStorePropertyStrictOperator;
276 static base::LazyInstance<JSOperatorGlobalCache>::type kCache =
277 LAZY_INSTANCE_INITIALIZER;
280 JSOperatorBuilder::JSOperatorBuilder(Zone* zone)
281 : cache_(kCache.Get()), zone_(zone) {}
284 #define CACHED(Name, properties, value_input_count, value_output_count) \
285 const Operator* JSOperatorBuilder::Name() { \
286 return &cache_.k##Name##Operator; \
288 CACHED_OP_LIST(CACHED)
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
303 const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id,
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
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
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
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
348 const Operator* JSOperatorBuilder::StoreProperty(LanguageMode language_mode) {
349 if (is_strict(language_mode)) {
350 return &cache_.kStorePropertyStrictOperator;
352 return &cache_.kStorePropertySloppyOperator;
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
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
379 const Operator* JSOperatorBuilder::LoadContext(size_t depth, size_t index,
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
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
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
411 } // namespace compiler
412 } // namespace internal