1// Copyright 2013 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#ifndef V8_COMPILER_JS_OPERATOR_H_
6#define V8_COMPILER_JS_OPERATOR_H_
7
8#include "src/base/compiler-specific.h"
9#include "src/globals.h"
10#include "src/runtime/runtime.h"
11#include "src/type-hints.h"
12
13namespace v8 {
14namespace internal {
15namespace compiler {
16
17// Forward declarations.
18class Operator;
19struct JSOperatorGlobalCache;
20
21
22// Defines a pair of {TypeFeedbackVector} and {TypeFeedbackVectorSlot}, which
23// is used to access the type feedback for a certain {Node}.
24class V8_EXPORT_PRIVATE VectorSlotPair {
25 public:
26  VectorSlotPair();
27  VectorSlotPair(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
28      : vector_(vector), slot_(slot) {}
29
30  bool IsValid() const { return !vector_.is_null() && !slot_.IsInvalid(); }
31
32  Handle<TypeFeedbackVector> vector() const { return vector_; }
33  FeedbackVectorSlot slot() const { return slot_; }
34
35  int index() const;
36
37 private:
38  const Handle<TypeFeedbackVector> vector_;
39  const FeedbackVectorSlot slot_;
40};
41
42bool operator==(VectorSlotPair const&, VectorSlotPair const&);
43bool operator!=(VectorSlotPair const&, VectorSlotPair const&);
44
45size_t hash_value(VectorSlotPair const&);
46
47
48// The ConvertReceiverMode is used as parameter by JSConvertReceiver operators.
49ConvertReceiverMode ConvertReceiverModeOf(Operator const* op);
50
51
52// The ToBooleanHints are used as parameter by JSToBoolean operators.
53ToBooleanHints ToBooleanHintsOf(Operator const* op);
54
55
56// Defines the arity and the feedback for a JavaScript constructor call. This is
57// used as a parameter by JSCallConstruct operators.
58class CallConstructParameters final {
59 public:
60  CallConstructParameters(uint32_t arity, float frequency,
61                          VectorSlotPair const& feedback)
62      : arity_(arity), frequency_(frequency), feedback_(feedback) {}
63
64  uint32_t arity() const { return arity_; }
65  float frequency() const { return frequency_; }
66  VectorSlotPair const& feedback() const { return feedback_; }
67
68 private:
69  uint32_t const arity_;
70  float const frequency_;
71  VectorSlotPair const feedback_;
72};
73
74bool operator==(CallConstructParameters const&, CallConstructParameters const&);
75bool operator!=(CallConstructParameters const&, CallConstructParameters const&);
76
77size_t hash_value(CallConstructParameters const&);
78
79std::ostream& operator<<(std::ostream&, CallConstructParameters const&);
80
81CallConstructParameters const& CallConstructParametersOf(Operator const*);
82
83
84// Defines the arity and the call flags for a JavaScript function call. This is
85// used as a parameter by JSCallFunction operators.
86class CallFunctionParameters final {
87 public:
88  CallFunctionParameters(size_t arity, float frequency,
89                         VectorSlotPair const& feedback,
90                         TailCallMode tail_call_mode,
91                         ConvertReceiverMode convert_mode)
92      : bit_field_(ArityField::encode(arity) |
93                   ConvertReceiverModeField::encode(convert_mode) |
94                   TailCallModeField::encode(tail_call_mode)),
95        frequency_(frequency),
96        feedback_(feedback) {}
97
98  size_t arity() const { return ArityField::decode(bit_field_); }
99  float frequency() const { return frequency_; }
100  ConvertReceiverMode convert_mode() const {
101    return ConvertReceiverModeField::decode(bit_field_);
102  }
103  TailCallMode tail_call_mode() const {
104    return TailCallModeField::decode(bit_field_);
105  }
106  VectorSlotPair const& feedback() const { return feedback_; }
107
108  bool operator==(CallFunctionParameters const& that) const {
109    return this->bit_field_ == that.bit_field_ &&
110           this->frequency_ == that.frequency_ &&
111           this->feedback_ == that.feedback_;
112  }
113  bool operator!=(CallFunctionParameters const& that) const {
114    return !(*this == that);
115  }
116
117 private:
118  friend size_t hash_value(CallFunctionParameters const& p) {
119    return base::hash_combine(p.bit_field_, p.frequency_, p.feedback_);
120  }
121
122  typedef BitField<size_t, 0, 29> ArityField;
123  typedef BitField<ConvertReceiverMode, 29, 2> ConvertReceiverModeField;
124  typedef BitField<TailCallMode, 31, 1> TailCallModeField;
125
126  uint32_t const bit_field_;
127  float const frequency_;
128  VectorSlotPair const feedback_;
129};
130
131size_t hash_value(CallFunctionParameters const&);
132
133std::ostream& operator<<(std::ostream&, CallFunctionParameters const&);
134
135const CallFunctionParameters& CallFunctionParametersOf(const Operator* op);
136
137
138// Defines the arity and the ID for a runtime function call. This is used as a
139// parameter by JSCallRuntime operators.
140class CallRuntimeParameters final {
141 public:
142  CallRuntimeParameters(Runtime::FunctionId id, size_t arity)
143      : id_(id), arity_(arity) {}
144
145  Runtime::FunctionId id() const { return id_; }
146  size_t arity() const { return arity_; }
147
148 private:
149  const Runtime::FunctionId id_;
150  const size_t arity_;
151};
152
153bool operator==(CallRuntimeParameters const&, CallRuntimeParameters const&);
154bool operator!=(CallRuntimeParameters const&, CallRuntimeParameters const&);
155
156size_t hash_value(CallRuntimeParameters const&);
157
158std::ostream& operator<<(std::ostream&, CallRuntimeParameters const&);
159
160const CallRuntimeParameters& CallRuntimeParametersOf(const Operator* op);
161
162
163// Defines the location of a context slot relative to a specific scope. This is
164// used as a parameter by JSLoadContext and JSStoreContext operators and allows
165// accessing a context-allocated variable without keeping track of the scope.
166class ContextAccess final {
167 public:
168  ContextAccess(size_t depth, size_t index, bool immutable);
169
170  size_t depth() const { return depth_; }
171  size_t index() const { return index_; }
172  bool immutable() const { return immutable_; }
173
174 private:
175  // For space reasons, we keep this tightly packed, otherwise we could just use
176  // a simple int/int/bool POD.
177  const bool immutable_;
178  const uint16_t depth_;
179  const uint32_t index_;
180};
181
182bool operator==(ContextAccess const&, ContextAccess const&);
183bool operator!=(ContextAccess const&, ContextAccess const&);
184
185size_t hash_value(ContextAccess const&);
186
187V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, ContextAccess const&);
188
189ContextAccess const& ContextAccessOf(Operator const*);
190
191// Defines the name and ScopeInfo for a new catch context. This is used as a
192// parameter by the JSCreateCatchContext operator.
193class CreateCatchContextParameters final {
194 public:
195  CreateCatchContextParameters(Handle<String> catch_name,
196                               Handle<ScopeInfo> scope_info);
197
198  Handle<String> catch_name() const { return catch_name_; }
199  Handle<ScopeInfo> scope_info() const { return scope_info_; }
200
201 private:
202  Handle<String> const catch_name_;
203  Handle<ScopeInfo> const scope_info_;
204};
205
206bool operator==(CreateCatchContextParameters const& lhs,
207                CreateCatchContextParameters const& rhs);
208bool operator!=(CreateCatchContextParameters const& lhs,
209                CreateCatchContextParameters const& rhs);
210
211size_t hash_value(CreateCatchContextParameters const& parameters);
212
213std::ostream& operator<<(std::ostream& os,
214                         CreateCatchContextParameters const& parameters);
215
216CreateCatchContextParameters const& CreateCatchContextParametersOf(
217    Operator const*);
218
219// Defines the property of an object for a named access. This is
220// used as a parameter by the JSLoadNamed and JSStoreNamed operators.
221class NamedAccess final {
222 public:
223  NamedAccess(LanguageMode language_mode, Handle<Name> name,
224              VectorSlotPair const& feedback)
225      : name_(name), feedback_(feedback), language_mode_(language_mode) {}
226
227  Handle<Name> name() const { return name_; }
228  LanguageMode language_mode() const { return language_mode_; }
229  VectorSlotPair const& feedback() const { return feedback_; }
230
231 private:
232  Handle<Name> const name_;
233  VectorSlotPair const feedback_;
234  LanguageMode const language_mode_;
235};
236
237bool operator==(NamedAccess const&, NamedAccess const&);
238bool operator!=(NamedAccess const&, NamedAccess const&);
239
240size_t hash_value(NamedAccess const&);
241
242std::ostream& operator<<(std::ostream&, NamedAccess const&);
243
244const NamedAccess& NamedAccessOf(const Operator* op);
245
246
247// Defines the property being loaded from an object by a named load. This is
248// used as a parameter by JSLoadGlobal operator.
249class LoadGlobalParameters final {
250 public:
251  LoadGlobalParameters(const Handle<Name>& name, const VectorSlotPair& feedback,
252                       TypeofMode typeof_mode)
253      : name_(name), feedback_(feedback), typeof_mode_(typeof_mode) {}
254
255  const Handle<Name>& name() const { return name_; }
256  TypeofMode typeof_mode() const { return typeof_mode_; }
257
258  const VectorSlotPair& feedback() const { return feedback_; }
259
260 private:
261  const Handle<Name> name_;
262  const VectorSlotPair feedback_;
263  const TypeofMode typeof_mode_;
264};
265
266bool operator==(LoadGlobalParameters const&, LoadGlobalParameters const&);
267bool operator!=(LoadGlobalParameters const&, LoadGlobalParameters const&);
268
269size_t hash_value(LoadGlobalParameters const&);
270
271std::ostream& operator<<(std::ostream&, LoadGlobalParameters const&);
272
273const LoadGlobalParameters& LoadGlobalParametersOf(const Operator* op);
274
275
276// Defines the property being stored to an object by a named store. This is
277// used as a parameter by JSStoreGlobal operator.
278class StoreGlobalParameters final {
279 public:
280  StoreGlobalParameters(LanguageMode language_mode,
281                        const VectorSlotPair& feedback,
282                        const Handle<Name>& name)
283      : language_mode_(language_mode), name_(name), feedback_(feedback) {}
284
285  LanguageMode language_mode() const { return language_mode_; }
286  const VectorSlotPair& feedback() const { return feedback_; }
287  const Handle<Name>& name() const { return name_; }
288
289 private:
290  const LanguageMode language_mode_;
291  const Handle<Name> name_;
292  const VectorSlotPair feedback_;
293};
294
295bool operator==(StoreGlobalParameters const&, StoreGlobalParameters const&);
296bool operator!=(StoreGlobalParameters const&, StoreGlobalParameters const&);
297
298size_t hash_value(StoreGlobalParameters const&);
299
300std::ostream& operator<<(std::ostream&, StoreGlobalParameters const&);
301
302const StoreGlobalParameters& StoreGlobalParametersOf(const Operator* op);
303
304
305// Defines the property of an object for a keyed access. This is used
306// as a parameter by the JSLoadProperty and JSStoreProperty operators.
307class PropertyAccess final {
308 public:
309  PropertyAccess(LanguageMode language_mode, VectorSlotPair const& feedback)
310      : feedback_(feedback), language_mode_(language_mode) {}
311
312  LanguageMode language_mode() const { return language_mode_; }
313  VectorSlotPair const& feedback() const { return feedback_; }
314
315 private:
316  VectorSlotPair const feedback_;
317  LanguageMode const language_mode_;
318};
319
320bool operator==(PropertyAccess const&, PropertyAccess const&);
321bool operator!=(PropertyAccess const&, PropertyAccess const&);
322
323size_t hash_value(PropertyAccess const&);
324
325std::ostream& operator<<(std::ostream&, PropertyAccess const&);
326
327PropertyAccess const& PropertyAccessOf(const Operator* op);
328
329
330// CreateArgumentsType is used as parameter to JSCreateArguments nodes.
331CreateArgumentsType const& CreateArgumentsTypeOf(const Operator* op);
332
333
334// Defines shared information for the array that should be created. This is
335// used as parameter by JSCreateArray operators.
336class CreateArrayParameters final {
337 public:
338  explicit CreateArrayParameters(size_t arity, Handle<AllocationSite> site)
339      : arity_(arity), site_(site) {}
340
341  size_t arity() const { return arity_; }
342  Handle<AllocationSite> site() const { return site_; }
343
344 private:
345  size_t const arity_;
346  Handle<AllocationSite> const site_;
347};
348
349bool operator==(CreateArrayParameters const&, CreateArrayParameters const&);
350bool operator!=(CreateArrayParameters const&, CreateArrayParameters const&);
351
352size_t hash_value(CreateArrayParameters const&);
353
354std::ostream& operator<<(std::ostream&, CreateArrayParameters const&);
355
356const CreateArrayParameters& CreateArrayParametersOf(const Operator* op);
357
358
359// Defines shared information for the closure that should be created. This is
360// used as a parameter by JSCreateClosure operators.
361class CreateClosureParameters final {
362 public:
363  CreateClosureParameters(Handle<SharedFunctionInfo> shared_info,
364                          PretenureFlag pretenure)
365      : shared_info_(shared_info), pretenure_(pretenure) {}
366
367  Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
368  PretenureFlag pretenure() const { return pretenure_; }
369
370 private:
371  const Handle<SharedFunctionInfo> shared_info_;
372  const PretenureFlag pretenure_;
373};
374
375bool operator==(CreateClosureParameters const&, CreateClosureParameters const&);
376bool operator!=(CreateClosureParameters const&, CreateClosureParameters const&);
377
378size_t hash_value(CreateClosureParameters const&);
379
380std::ostream& operator<<(std::ostream&, CreateClosureParameters const&);
381
382const CreateClosureParameters& CreateClosureParametersOf(const Operator* op);
383
384// Defines shared information for the literal that should be created. This is
385// used as parameter by JSCreateLiteralArray, JSCreateLiteralObject and
386// JSCreateLiteralRegExp operators.
387class CreateLiteralParameters final {
388 public:
389  CreateLiteralParameters(Handle<HeapObject> constant, int length, int flags,
390                          int index)
391      : constant_(constant), length_(length), flags_(flags), index_(index) {}
392
393  Handle<HeapObject> constant() const { return constant_; }
394  int length() const { return length_; }
395  int flags() const { return flags_; }
396  int index() const { return index_; }
397
398 private:
399  Handle<HeapObject> const constant_;
400  int const length_;
401  int const flags_;
402  int const index_;
403};
404
405bool operator==(CreateLiteralParameters const&, CreateLiteralParameters const&);
406bool operator!=(CreateLiteralParameters const&, CreateLiteralParameters const&);
407
408size_t hash_value(CreateLiteralParameters const&);
409
410std::ostream& operator<<(std::ostream&, CreateLiteralParameters const&);
411
412const CreateLiteralParameters& CreateLiteralParametersOf(const Operator* op);
413
414BinaryOperationHint BinaryOperationHintOf(const Operator* op);
415
416CompareOperationHint CompareOperationHintOf(const Operator* op);
417
418// Interface for building JavaScript-level operators, e.g. directly from the
419// AST. Most operators have no parameters, thus can be globally shared for all
420// graphs.
421class V8_EXPORT_PRIVATE JSOperatorBuilder final
422    : public NON_EXPORTED_BASE(ZoneObject) {
423 public:
424  explicit JSOperatorBuilder(Zone* zone);
425
426  const Operator* Equal(CompareOperationHint hint);
427  const Operator* NotEqual(CompareOperationHint hint);
428  const Operator* StrictEqual(CompareOperationHint hint);
429  const Operator* StrictNotEqual(CompareOperationHint hint);
430  const Operator* LessThan(CompareOperationHint hint);
431  const Operator* GreaterThan(CompareOperationHint hint);
432  const Operator* LessThanOrEqual(CompareOperationHint hint);
433  const Operator* GreaterThanOrEqual(CompareOperationHint hint);
434
435  const Operator* BitwiseOr(BinaryOperationHint hint);
436  const Operator* BitwiseXor(BinaryOperationHint hint);
437  const Operator* BitwiseAnd(BinaryOperationHint hint);
438  const Operator* ShiftLeft(BinaryOperationHint hint);
439  const Operator* ShiftRight(BinaryOperationHint hint);
440  const Operator* ShiftRightLogical(BinaryOperationHint hint);
441  const Operator* Add(BinaryOperationHint hint);
442  const Operator* Subtract(BinaryOperationHint hint);
443  const Operator* Multiply(BinaryOperationHint hint);
444  const Operator* Divide(BinaryOperationHint hint);
445  const Operator* Modulus(BinaryOperationHint hint);
446
447  const Operator* ToBoolean(ToBooleanHints hints);
448  const Operator* ToInteger();
449  const Operator* ToLength();
450  const Operator* ToName();
451  const Operator* ToNumber();
452  const Operator* ToObject();
453  const Operator* ToString();
454
455  const Operator* Create();
456  const Operator* CreateArguments(CreateArgumentsType type);
457  const Operator* CreateArray(size_t arity, Handle<AllocationSite> site);
458  const Operator* CreateClosure(Handle<SharedFunctionInfo> shared_info,
459                                PretenureFlag pretenure);
460  const Operator* CreateIterResultObject();
461  const Operator* CreateKeyValueArray();
462  const Operator* CreateLiteralArray(Handle<FixedArray> constant_elements,
463                                     int literal_flags, int literal_index,
464                                     int number_of_elements);
465  const Operator* CreateLiteralObject(Handle<FixedArray> constant_properties,
466                                      int literal_flags, int literal_index,
467                                      int number_of_properties);
468  const Operator* CreateLiteralRegExp(Handle<String> constant_pattern,
469                                      int literal_flags, int literal_index);
470
471  const Operator* CallFunction(
472      size_t arity, float frequency = 0.0f,
473      VectorSlotPair const& feedback = VectorSlotPair(),
474      ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny,
475      TailCallMode tail_call_mode = TailCallMode::kDisallow);
476  const Operator* CallRuntime(Runtime::FunctionId id);
477  const Operator* CallRuntime(Runtime::FunctionId id, size_t arity);
478  const Operator* CallRuntime(const Runtime::Function* function, size_t arity);
479  const Operator* CallConstruct(uint32_t arity, float frequency,
480                                VectorSlotPair const& feedback);
481
482  const Operator* ConvertReceiver(ConvertReceiverMode convert_mode);
483
484  const Operator* LoadProperty(VectorSlotPair const& feedback);
485  const Operator* LoadNamed(Handle<Name> name, VectorSlotPair const& feedback);
486
487  const Operator* StoreProperty(LanguageMode language_mode,
488                                VectorSlotPair const& feedback);
489  const Operator* StoreNamed(LanguageMode language_mode, Handle<Name> name,
490                             VectorSlotPair const& feedback);
491
492  const Operator* DeleteProperty(LanguageMode language_mode);
493
494  const Operator* HasProperty();
495
496  const Operator* LoadGlobal(const Handle<Name>& name,
497                             const VectorSlotPair& feedback,
498                             TypeofMode typeof_mode = NOT_INSIDE_TYPEOF);
499  const Operator* StoreGlobal(LanguageMode language_mode,
500                              const Handle<Name>& name,
501                              const VectorSlotPair& feedback);
502
503  const Operator* LoadContext(size_t depth, size_t index, bool immutable);
504  const Operator* StoreContext(size_t depth, size_t index);
505
506  const Operator* LoadModule(int32_t cell_index);
507  const Operator* StoreModule(int32_t cell_index);
508
509  const Operator* TypeOf();
510  const Operator* InstanceOf();
511  const Operator* OrdinaryHasInstance();
512
513  const Operator* ForInNext();
514  const Operator* ForInPrepare();
515
516  const Operator* LoadMessage();
517  const Operator* StoreMessage();
518
519  // Used to implement Ignition's SuspendGenerator bytecode.
520  const Operator* GeneratorStore(int register_count);
521
522  // Used to implement Ignition's ResumeGenerator bytecode.
523  const Operator* GeneratorRestoreContinuation();
524  const Operator* GeneratorRestoreRegister(int index);
525
526  const Operator* StackCheck();
527
528  const Operator* CreateFunctionContext(int slot_count);
529  const Operator* CreateCatchContext(const Handle<String>& name,
530                                     const Handle<ScopeInfo>& scope_info);
531  const Operator* CreateWithContext(const Handle<ScopeInfo>& scope_info);
532  const Operator* CreateBlockContext(const Handle<ScopeInfo>& scpope_info);
533  const Operator* CreateModuleContext();
534  const Operator* CreateScriptContext(const Handle<ScopeInfo>& scpope_info);
535
536 private:
537  Zone* zone() const { return zone_; }
538
539  const JSOperatorGlobalCache& cache_;
540  Zone* const zone_;
541
542  DISALLOW_COPY_AND_ASSIGN(JSOperatorBuilder);
543};
544
545}  // namespace compiler
546}  // namespace internal
547}  // namespace v8
548
549#endif  // V8_COMPILER_JS_OPERATOR_H_
550