Home | History | Annotate | Download | only in compiler
      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 #include "src/handles-inl.h"
     13 #include "src/type-feedback-vector.h"
     14 
     15 namespace v8 {
     16 namespace internal {
     17 namespace compiler {
     18 
     19 VectorSlotPair::VectorSlotPair() {}
     20 
     21 
     22 int VectorSlotPair::index() const {
     23   return vector_.is_null() ? -1 : vector_->GetIndex(slot_);
     24 }
     25 
     26 
     27 bool operator==(VectorSlotPair const& lhs, VectorSlotPair const& rhs) {
     28   return lhs.slot() == rhs.slot() &&
     29          lhs.vector().location() == rhs.vector().location();
     30 }
     31 
     32 
     33 bool operator!=(VectorSlotPair const& lhs, VectorSlotPair const& rhs) {
     34   return !(lhs == rhs);
     35 }
     36 
     37 
     38 size_t hash_value(VectorSlotPair const& p) {
     39   return base::hash_combine(p.slot(), p.vector().location());
     40 }
     41 
     42 
     43 ConvertReceiverMode ConvertReceiverModeOf(Operator const* op) {
     44   DCHECK_EQ(IrOpcode::kJSConvertReceiver, op->opcode());
     45   return OpParameter<ConvertReceiverMode>(op);
     46 }
     47 
     48 
     49 ToBooleanHints ToBooleanHintsOf(Operator const* op) {
     50   DCHECK_EQ(IrOpcode::kJSToBoolean, op->opcode());
     51   return OpParameter<ToBooleanHints>(op);
     52 }
     53 
     54 
     55 bool operator==(CallConstructParameters const& lhs,
     56                 CallConstructParameters const& rhs) {
     57   return lhs.arity() == rhs.arity() && lhs.frequency() == rhs.frequency() &&
     58          lhs.feedback() == rhs.feedback();
     59 }
     60 
     61 
     62 bool operator!=(CallConstructParameters const& lhs,
     63                 CallConstructParameters const& rhs) {
     64   return !(lhs == rhs);
     65 }
     66 
     67 
     68 size_t hash_value(CallConstructParameters const& p) {
     69   return base::hash_combine(p.arity(), p.frequency(), p.feedback());
     70 }
     71 
     72 
     73 std::ostream& operator<<(std::ostream& os, CallConstructParameters const& p) {
     74   return os << p.arity() << ", " << p.frequency();
     75 }
     76 
     77 
     78 CallConstructParameters const& CallConstructParametersOf(Operator const* op) {
     79   DCHECK_EQ(IrOpcode::kJSCallConstruct, op->opcode());
     80   return OpParameter<CallConstructParameters>(op);
     81 }
     82 
     83 
     84 std::ostream& operator<<(std::ostream& os, CallFunctionParameters const& p) {
     85   os << p.arity() << ", " << p.frequency() << ", " << p.convert_mode() << ", "
     86      << p.tail_call_mode();
     87   return os;
     88 }
     89 
     90 
     91 const CallFunctionParameters& CallFunctionParametersOf(const Operator* op) {
     92   DCHECK_EQ(IrOpcode::kJSCallFunction, op->opcode());
     93   return OpParameter<CallFunctionParameters>(op);
     94 }
     95 
     96 
     97 bool operator==(CallRuntimeParameters const& lhs,
     98                 CallRuntimeParameters const& rhs) {
     99   return lhs.id() == rhs.id() && lhs.arity() == rhs.arity();
    100 }
    101 
    102 
    103 bool operator!=(CallRuntimeParameters const& lhs,
    104                 CallRuntimeParameters const& rhs) {
    105   return !(lhs == rhs);
    106 }
    107 
    108 
    109 size_t hash_value(CallRuntimeParameters const& p) {
    110   return base::hash_combine(p.id(), p.arity());
    111 }
    112 
    113 
    114 std::ostream& operator<<(std::ostream& os, CallRuntimeParameters const& p) {
    115   return os << p.id() << ", " << p.arity();
    116 }
    117 
    118 
    119 const CallRuntimeParameters& CallRuntimeParametersOf(const Operator* op) {
    120   DCHECK_EQ(IrOpcode::kJSCallRuntime, op->opcode());
    121   return OpParameter<CallRuntimeParameters>(op);
    122 }
    123 
    124 
    125 ContextAccess::ContextAccess(size_t depth, size_t index, bool immutable)
    126     : immutable_(immutable),
    127       depth_(static_cast<uint16_t>(depth)),
    128       index_(static_cast<uint32_t>(index)) {
    129   DCHECK(depth <= std::numeric_limits<uint16_t>::max());
    130   DCHECK(index <= std::numeric_limits<uint32_t>::max());
    131 }
    132 
    133 
    134 bool operator==(ContextAccess const& lhs, ContextAccess const& rhs) {
    135   return lhs.depth() == rhs.depth() && lhs.index() == rhs.index() &&
    136          lhs.immutable() == rhs.immutable();
    137 }
    138 
    139 
    140 bool operator!=(ContextAccess const& lhs, ContextAccess const& rhs) {
    141   return !(lhs == rhs);
    142 }
    143 
    144 
    145 size_t hash_value(ContextAccess const& access) {
    146   return base::hash_combine(access.depth(), access.index(), access.immutable());
    147 }
    148 
    149 
    150 std::ostream& operator<<(std::ostream& os, ContextAccess const& access) {
    151   return os << access.depth() << ", " << access.index() << ", "
    152             << access.immutable();
    153 }
    154 
    155 
    156 ContextAccess const& ContextAccessOf(Operator const* op) {
    157   DCHECK(op->opcode() == IrOpcode::kJSLoadContext ||
    158          op->opcode() == IrOpcode::kJSStoreContext);
    159   return OpParameter<ContextAccess>(op);
    160 }
    161 
    162 CreateCatchContextParameters::CreateCatchContextParameters(
    163     Handle<String> catch_name, Handle<ScopeInfo> scope_info)
    164     : catch_name_(catch_name), scope_info_(scope_info) {}
    165 
    166 bool operator==(CreateCatchContextParameters const& lhs,
    167                 CreateCatchContextParameters const& rhs) {
    168   return lhs.catch_name().location() == rhs.catch_name().location() &&
    169          lhs.scope_info().location() == rhs.scope_info().location();
    170 }
    171 
    172 bool operator!=(CreateCatchContextParameters const& lhs,
    173                 CreateCatchContextParameters const& rhs) {
    174   return !(lhs == rhs);
    175 }
    176 
    177 size_t hash_value(CreateCatchContextParameters const& parameters) {
    178   return base::hash_combine(parameters.catch_name().location(),
    179                             parameters.scope_info().location());
    180 }
    181 
    182 std::ostream& operator<<(std::ostream& os,
    183                          CreateCatchContextParameters const& parameters) {
    184   return os << Brief(*parameters.catch_name()) << ", "
    185             << Brief(*parameters.scope_info());
    186 }
    187 
    188 CreateCatchContextParameters const& CreateCatchContextParametersOf(
    189     Operator const* op) {
    190   DCHECK_EQ(IrOpcode::kJSCreateCatchContext, op->opcode());
    191   return OpParameter<CreateCatchContextParameters>(op);
    192 }
    193 
    194 bool operator==(NamedAccess const& lhs, NamedAccess const& rhs) {
    195   return lhs.name().location() == rhs.name().location() &&
    196          lhs.language_mode() == rhs.language_mode() &&
    197          lhs.feedback() == rhs.feedback();
    198 }
    199 
    200 
    201 bool operator!=(NamedAccess const& lhs, NamedAccess const& rhs) {
    202   return !(lhs == rhs);
    203 }
    204 
    205 
    206 size_t hash_value(NamedAccess const& p) {
    207   return base::hash_combine(p.name().location(), p.language_mode(),
    208                             p.feedback());
    209 }
    210 
    211 
    212 std::ostream& operator<<(std::ostream& os, NamedAccess const& p) {
    213   return os << Brief(*p.name()) << ", " << p.language_mode();
    214 }
    215 
    216 
    217 NamedAccess const& NamedAccessOf(const Operator* op) {
    218   DCHECK(op->opcode() == IrOpcode::kJSLoadNamed ||
    219          op->opcode() == IrOpcode::kJSStoreNamed);
    220   return OpParameter<NamedAccess>(op);
    221 }
    222 
    223 
    224 std::ostream& operator<<(std::ostream& os, PropertyAccess const& p) {
    225   return os << p.language_mode();
    226 }
    227 
    228 
    229 bool operator==(PropertyAccess const& lhs, PropertyAccess const& rhs) {
    230   return lhs.language_mode() == rhs.language_mode() &&
    231          lhs.feedback() == rhs.feedback();
    232 }
    233 
    234 
    235 bool operator!=(PropertyAccess const& lhs, PropertyAccess const& rhs) {
    236   return !(lhs == rhs);
    237 }
    238 
    239 
    240 PropertyAccess const& PropertyAccessOf(const Operator* op) {
    241   DCHECK(op->opcode() == IrOpcode::kJSLoadProperty ||
    242          op->opcode() == IrOpcode::kJSStoreProperty);
    243   return OpParameter<PropertyAccess>(op);
    244 }
    245 
    246 
    247 size_t hash_value(PropertyAccess const& p) {
    248   return base::hash_combine(p.language_mode(), p.feedback());
    249 }
    250 
    251 
    252 bool operator==(LoadGlobalParameters const& lhs,
    253                 LoadGlobalParameters const& rhs) {
    254   return lhs.name().location() == rhs.name().location() &&
    255          lhs.feedback() == rhs.feedback() &&
    256          lhs.typeof_mode() == rhs.typeof_mode();
    257 }
    258 
    259 
    260 bool operator!=(LoadGlobalParameters const& lhs,
    261                 LoadGlobalParameters const& rhs) {
    262   return !(lhs == rhs);
    263 }
    264 
    265 
    266 size_t hash_value(LoadGlobalParameters const& p) {
    267   return base::hash_combine(p.name().location(), p.typeof_mode());
    268 }
    269 
    270 
    271 std::ostream& operator<<(std::ostream& os, LoadGlobalParameters const& p) {
    272   return os << Brief(*p.name()) << ", " << p.typeof_mode();
    273 }
    274 
    275 
    276 const LoadGlobalParameters& LoadGlobalParametersOf(const Operator* op) {
    277   DCHECK_EQ(IrOpcode::kJSLoadGlobal, op->opcode());
    278   return OpParameter<LoadGlobalParameters>(op);
    279 }
    280 
    281 
    282 bool operator==(StoreGlobalParameters const& lhs,
    283                 StoreGlobalParameters const& rhs) {
    284   return lhs.language_mode() == rhs.language_mode() &&
    285          lhs.name().location() == rhs.name().location() &&
    286          lhs.feedback() == rhs.feedback();
    287 }
    288 
    289 
    290 bool operator!=(StoreGlobalParameters const& lhs,
    291                 StoreGlobalParameters const& rhs) {
    292   return !(lhs == rhs);
    293 }
    294 
    295 
    296 size_t hash_value(StoreGlobalParameters const& p) {
    297   return base::hash_combine(p.language_mode(), p.name().location(),
    298                             p.feedback());
    299 }
    300 
    301 
    302 std::ostream& operator<<(std::ostream& os, StoreGlobalParameters const& p) {
    303   return os << p.language_mode() << ", " << Brief(*p.name());
    304 }
    305 
    306 
    307 const StoreGlobalParameters& StoreGlobalParametersOf(const Operator* op) {
    308   DCHECK_EQ(IrOpcode::kJSStoreGlobal, op->opcode());
    309   return OpParameter<StoreGlobalParameters>(op);
    310 }
    311 
    312 
    313 CreateArgumentsType const& CreateArgumentsTypeOf(const Operator* op) {
    314   DCHECK_EQ(IrOpcode::kJSCreateArguments, op->opcode());
    315   return OpParameter<CreateArgumentsType>(op);
    316 }
    317 
    318 
    319 bool operator==(CreateArrayParameters const& lhs,
    320                 CreateArrayParameters const& rhs) {
    321   return lhs.arity() == rhs.arity() &&
    322          lhs.site().location() == rhs.site().location();
    323 }
    324 
    325 
    326 bool operator!=(CreateArrayParameters const& lhs,
    327                 CreateArrayParameters const& rhs) {
    328   return !(lhs == rhs);
    329 }
    330 
    331 
    332 size_t hash_value(CreateArrayParameters const& p) {
    333   return base::hash_combine(p.arity(), p.site().location());
    334 }
    335 
    336 
    337 std::ostream& operator<<(std::ostream& os, CreateArrayParameters const& p) {
    338   os << p.arity();
    339   if (!p.site().is_null()) os << ", " << Brief(*p.site());
    340   return os;
    341 }
    342 
    343 
    344 const CreateArrayParameters& CreateArrayParametersOf(const Operator* op) {
    345   DCHECK_EQ(IrOpcode::kJSCreateArray, op->opcode());
    346   return OpParameter<CreateArrayParameters>(op);
    347 }
    348 
    349 
    350 bool operator==(CreateClosureParameters const& lhs,
    351                 CreateClosureParameters const& rhs) {
    352   return lhs.pretenure() == rhs.pretenure() &&
    353          lhs.shared_info().location() == rhs.shared_info().location();
    354 }
    355 
    356 
    357 bool operator!=(CreateClosureParameters const& lhs,
    358                 CreateClosureParameters const& rhs) {
    359   return !(lhs == rhs);
    360 }
    361 
    362 
    363 size_t hash_value(CreateClosureParameters const& p) {
    364   return base::hash_combine(p.pretenure(), p.shared_info().location());
    365 }
    366 
    367 
    368 std::ostream& operator<<(std::ostream& os, CreateClosureParameters const& p) {
    369   return os << p.pretenure() << ", " << Brief(*p.shared_info());
    370 }
    371 
    372 
    373 const CreateClosureParameters& CreateClosureParametersOf(const Operator* op) {
    374   DCHECK_EQ(IrOpcode::kJSCreateClosure, op->opcode());
    375   return OpParameter<CreateClosureParameters>(op);
    376 }
    377 
    378 
    379 bool operator==(CreateLiteralParameters const& lhs,
    380                 CreateLiteralParameters const& rhs) {
    381   return lhs.constant().location() == rhs.constant().location() &&
    382          lhs.length() == rhs.length() && lhs.flags() == rhs.flags() &&
    383          lhs.index() == rhs.index();
    384 }
    385 
    386 
    387 bool operator!=(CreateLiteralParameters const& lhs,
    388                 CreateLiteralParameters const& rhs) {
    389   return !(lhs == rhs);
    390 }
    391 
    392 
    393 size_t hash_value(CreateLiteralParameters const& p) {
    394   return base::hash_combine(p.constant().location(), p.length(), p.flags(),
    395                             p.index());
    396 }
    397 
    398 
    399 std::ostream& operator<<(std::ostream& os, CreateLiteralParameters const& p) {
    400   return os << Brief(*p.constant()) << ", " << p.length() << ", " << p.flags()
    401             << ", " << p.index();
    402 }
    403 
    404 
    405 const CreateLiteralParameters& CreateLiteralParametersOf(const Operator* op) {
    406   DCHECK(op->opcode() == IrOpcode::kJSCreateLiteralArray ||
    407          op->opcode() == IrOpcode::kJSCreateLiteralObject ||
    408          op->opcode() == IrOpcode::kJSCreateLiteralRegExp);
    409   return OpParameter<CreateLiteralParameters>(op);
    410 }
    411 
    412 BinaryOperationHint BinaryOperationHintOf(const Operator* op) {
    413   DCHECK(op->opcode() == IrOpcode::kJSBitwiseOr ||
    414          op->opcode() == IrOpcode::kJSBitwiseXor ||
    415          op->opcode() == IrOpcode::kJSBitwiseAnd ||
    416          op->opcode() == IrOpcode::kJSShiftLeft ||
    417          op->opcode() == IrOpcode::kJSShiftRight ||
    418          op->opcode() == IrOpcode::kJSShiftRightLogical ||
    419          op->opcode() == IrOpcode::kJSAdd ||
    420          op->opcode() == IrOpcode::kJSSubtract ||
    421          op->opcode() == IrOpcode::kJSMultiply ||
    422          op->opcode() == IrOpcode::kJSDivide ||
    423          op->opcode() == IrOpcode::kJSModulus);
    424   return OpParameter<BinaryOperationHint>(op);
    425 }
    426 
    427 CompareOperationHint CompareOperationHintOf(const Operator* op) {
    428   DCHECK(op->opcode() == IrOpcode::kJSEqual ||
    429          op->opcode() == IrOpcode::kJSNotEqual ||
    430          op->opcode() == IrOpcode::kJSStrictEqual ||
    431          op->opcode() == IrOpcode::kJSStrictNotEqual ||
    432          op->opcode() == IrOpcode::kJSLessThan ||
    433          op->opcode() == IrOpcode::kJSGreaterThan ||
    434          op->opcode() == IrOpcode::kJSLessThanOrEqual ||
    435          op->opcode() == IrOpcode::kJSGreaterThanOrEqual);
    436   return OpParameter<CompareOperationHint>(op);
    437 }
    438 
    439 #define CACHED_OP_LIST(V)                                   \
    440   V(ToInteger, Operator::kNoProperties, 1, 1)               \
    441   V(ToLength, Operator::kNoProperties, 1, 1)                \
    442   V(ToName, Operator::kNoProperties, 1, 1)                  \
    443   V(ToNumber, Operator::kNoProperties, 1, 1)                \
    444   V(ToObject, Operator::kFoldable, 1, 1)                    \
    445   V(ToString, Operator::kNoProperties, 1, 1)                \
    446   V(Create, Operator::kEliminatable, 2, 1)                  \
    447   V(CreateIterResultObject, Operator::kEliminatable, 2, 1)  \
    448   V(CreateKeyValueArray, Operator::kEliminatable, 2, 1)     \
    449   V(HasProperty, Operator::kNoProperties, 2, 1)             \
    450   V(TypeOf, Operator::kPure, 1, 1)                          \
    451   V(InstanceOf, Operator::kNoProperties, 2, 1)              \
    452   V(OrdinaryHasInstance, Operator::kNoProperties, 2, 1)     \
    453   V(ForInNext, Operator::kNoProperties, 4, 1)               \
    454   V(ForInPrepare, Operator::kNoProperties, 1, 3)            \
    455   V(LoadMessage, Operator::kNoThrow, 0, 1)                  \
    456   V(StoreMessage, Operator::kNoThrow, 1, 0)                 \
    457   V(GeneratorRestoreContinuation, Operator::kNoThrow, 1, 1) \
    458   V(StackCheck, Operator::kNoWrite, 0, 0)
    459 
    460 #define BINARY_OP_LIST(V) \
    461   V(BitwiseOr)            \
    462   V(BitwiseXor)           \
    463   V(BitwiseAnd)           \
    464   V(ShiftLeft)            \
    465   V(ShiftRight)           \
    466   V(ShiftRightLogical)    \
    467   V(Add)                  \
    468   V(Subtract)             \
    469   V(Multiply)             \
    470   V(Divide)               \
    471   V(Modulus)
    472 
    473 #define COMPARE_OP_LIST(V)                    \
    474   V(Equal, Operator::kNoProperties)           \
    475   V(NotEqual, Operator::kNoProperties)        \
    476   V(StrictEqual, Operator::kPure)             \
    477   V(StrictNotEqual, Operator::kPure)          \
    478   V(LessThan, Operator::kNoProperties)        \
    479   V(GreaterThan, Operator::kNoProperties)     \
    480   V(LessThanOrEqual, Operator::kNoProperties) \
    481   V(GreaterThanOrEqual, Operator::kNoProperties)
    482 
    483 struct JSOperatorGlobalCache final {
    484 #define CACHED_OP(Name, properties, value_input_count, value_output_count) \
    485   struct Name##Operator final : public Operator {                          \
    486     Name##Operator()                                                       \
    487         : Operator(IrOpcode::kJS##Name, properties, "JS" #Name,            \
    488                    value_input_count, Operator::ZeroIfPure(properties),    \
    489                    Operator::ZeroIfEliminatable(properties),               \
    490                    value_output_count, Operator::ZeroIfPure(properties),   \
    491                    Operator::ZeroIfNoThrow(properties)) {}                 \
    492   };                                                                       \
    493   Name##Operator k##Name##Operator;
    494   CACHED_OP_LIST(CACHED_OP)
    495 #undef CACHED_OP
    496 
    497 #define BINARY_OP(Name)                                                       \
    498   template <BinaryOperationHint kHint>                                        \
    499   struct Name##Operator final : public Operator1<BinaryOperationHint> {       \
    500     Name##Operator()                                                          \
    501         : Operator1<BinaryOperationHint>(IrOpcode::kJS##Name,                 \
    502                                          Operator::kNoProperties, "JS" #Name, \
    503                                          2, 1, 1, 1, 1, 2, kHint) {}          \
    504   };                                                                          \
    505   Name##Operator<BinaryOperationHint::kNone> k##Name##NoneOperator;           \
    506   Name##Operator<BinaryOperationHint::kSignedSmall>                           \
    507       k##Name##SignedSmallOperator;                                           \
    508   Name##Operator<BinaryOperationHint::kSigned32> k##Name##Signed32Operator;   \
    509   Name##Operator<BinaryOperationHint::kNumberOrOddball>                       \
    510       k##Name##NumberOrOddballOperator;                                       \
    511   Name##Operator<BinaryOperationHint::kString> k##Name##StringOperator;       \
    512   Name##Operator<BinaryOperationHint::kAny> k##Name##AnyOperator;
    513   BINARY_OP_LIST(BINARY_OP)
    514 #undef BINARY_OP
    515 
    516 #define COMPARE_OP(Name, properties)                                      \
    517   template <CompareOperationHint kHint>                                   \
    518   struct Name##Operator final : public Operator1<CompareOperationHint> {  \
    519     Name##Operator()                                                      \
    520         : Operator1<CompareOperationHint>(                                \
    521               IrOpcode::kJS##Name, properties, "JS" #Name, 2, 1, 1, 1, 1, \
    522               Operator::ZeroIfNoThrow(properties), kHint) {}              \
    523   };                                                                      \
    524   Name##Operator<CompareOperationHint::kNone> k##Name##NoneOperator;      \
    525   Name##Operator<CompareOperationHint::kSignedSmall>                      \
    526       k##Name##SignedSmallOperator;                                       \
    527   Name##Operator<CompareOperationHint::kNumber> k##Name##NumberOperator;  \
    528   Name##Operator<CompareOperationHint::kNumberOrOddball>                  \
    529       k##Name##NumberOrOddballOperator;                                   \
    530   Name##Operator<CompareOperationHint::kAny> k##Name##AnyOperator;
    531   COMPARE_OP_LIST(COMPARE_OP)
    532 #undef COMPARE_OP
    533 };
    534 
    535 static base::LazyInstance<JSOperatorGlobalCache>::type kCache =
    536     LAZY_INSTANCE_INITIALIZER;
    537 
    538 JSOperatorBuilder::JSOperatorBuilder(Zone* zone)
    539     : cache_(kCache.Get()), zone_(zone) {}
    540 
    541 #define CACHED_OP(Name, properties, value_input_count, value_output_count) \
    542   const Operator* JSOperatorBuilder::Name() {                              \
    543     return &cache_.k##Name##Operator;                                      \
    544   }
    545 CACHED_OP_LIST(CACHED_OP)
    546 #undef CACHED_OP
    547 
    548 #define BINARY_OP(Name)                                               \
    549   const Operator* JSOperatorBuilder::Name(BinaryOperationHint hint) { \
    550     switch (hint) {                                                   \
    551       case BinaryOperationHint::kNone:                                \
    552         return &cache_.k##Name##NoneOperator;                         \
    553       case BinaryOperationHint::kSignedSmall:                         \
    554         return &cache_.k##Name##SignedSmallOperator;                  \
    555       case BinaryOperationHint::kSigned32:                            \
    556         return &cache_.k##Name##Signed32Operator;                     \
    557       case BinaryOperationHint::kNumberOrOddball:                     \
    558         return &cache_.k##Name##NumberOrOddballOperator;              \
    559       case BinaryOperationHint::kString:                              \
    560         return &cache_.k##Name##StringOperator;                       \
    561       case BinaryOperationHint::kAny:                                 \
    562         return &cache_.k##Name##AnyOperator;                          \
    563     }                                                                 \
    564     UNREACHABLE();                                                    \
    565     return nullptr;                                                   \
    566   }
    567 BINARY_OP_LIST(BINARY_OP)
    568 #undef BINARY_OP
    569 
    570 #define COMPARE_OP(Name, ...)                                          \
    571   const Operator* JSOperatorBuilder::Name(CompareOperationHint hint) { \
    572     switch (hint) {                                                    \
    573       case CompareOperationHint::kNone:                                \
    574         return &cache_.k##Name##NoneOperator;                          \
    575       case CompareOperationHint::kSignedSmall:                         \
    576         return &cache_.k##Name##SignedSmallOperator;                   \
    577       case CompareOperationHint::kNumber:                              \
    578         return &cache_.k##Name##NumberOperator;                        \
    579       case CompareOperationHint::kNumberOrOddball:                     \
    580         return &cache_.k##Name##NumberOrOddballOperator;               \
    581       case CompareOperationHint::kAny:                                 \
    582         return &cache_.k##Name##AnyOperator;                           \
    583     }                                                                  \
    584     UNREACHABLE();                                                     \
    585     return nullptr;                                                    \
    586   }
    587 COMPARE_OP_LIST(COMPARE_OP)
    588 #undef COMPARE_OP
    589 
    590 const Operator* JSOperatorBuilder::ToBoolean(ToBooleanHints hints) {
    591   // TODO(turbofan): Cache most important versions of this operator.
    592   return new (zone()) Operator1<ToBooleanHints>(  //--
    593       IrOpcode::kJSToBoolean, Operator::kPure,    // opcode
    594       "JSToBoolean",                              // name
    595       1, 0, 0, 1, 0, 0,                           // inputs/outputs
    596       hints);                                     // parameter
    597 }
    598 
    599 const Operator* JSOperatorBuilder::CallFunction(
    600     size_t arity, float frequency, VectorSlotPair const& feedback,
    601     ConvertReceiverMode convert_mode, TailCallMode tail_call_mode) {
    602   CallFunctionParameters parameters(arity, frequency, feedback, tail_call_mode,
    603                                     convert_mode);
    604   return new (zone()) Operator1<CallFunctionParameters>(   // --
    605       IrOpcode::kJSCallFunction, Operator::kNoProperties,  // opcode
    606       "JSCallFunction",                                    // name
    607       parameters.arity(), 1, 1, 1, 1, 2,                   // inputs/outputs
    608       parameters);                                         // parameter
    609 }
    610 
    611 
    612 const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id) {
    613   const Runtime::Function* f = Runtime::FunctionForId(id);
    614   return CallRuntime(f, f->nargs);
    615 }
    616 
    617 
    618 const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id,
    619                                                size_t arity) {
    620   const Runtime::Function* f = Runtime::FunctionForId(id);
    621   return CallRuntime(f, arity);
    622 }
    623 
    624 
    625 const Operator* JSOperatorBuilder::CallRuntime(const Runtime::Function* f,
    626                                                size_t arity) {
    627   CallRuntimeParameters parameters(f->function_id, arity);
    628   DCHECK(f->nargs == -1 || f->nargs == static_cast<int>(parameters.arity()));
    629   return new (zone()) Operator1<CallRuntimeParameters>(   // --
    630       IrOpcode::kJSCallRuntime, Operator::kNoProperties,  // opcode
    631       "JSCallRuntime",                                    // name
    632       parameters.arity(), 1, 1, f->result_size, 1, 2,     // inputs/outputs
    633       parameters);                                        // parameter
    634 }
    635 
    636 const Operator* JSOperatorBuilder::CallConstruct(
    637     uint32_t arity, float frequency, VectorSlotPair const& feedback) {
    638   CallConstructParameters parameters(arity, frequency, feedback);
    639   return new (zone()) Operator1<CallConstructParameters>(   // --
    640       IrOpcode::kJSCallConstruct, Operator::kNoProperties,  // opcode
    641       "JSCallConstruct",                                    // name
    642       parameters.arity(), 1, 1, 1, 1, 2,                    // counts
    643       parameters);                                          // parameter
    644 }
    645 
    646 
    647 const Operator* JSOperatorBuilder::ConvertReceiver(
    648     ConvertReceiverMode convert_mode) {
    649   return new (zone()) Operator1<ConvertReceiverMode>(         // --
    650       IrOpcode::kJSConvertReceiver, Operator::kEliminatable,  // opcode
    651       "JSConvertReceiver",                                    // name
    652       1, 1, 1, 1, 1, 0,                                       // counts
    653       convert_mode);                                          // parameter
    654 }
    655 
    656 const Operator* JSOperatorBuilder::LoadNamed(Handle<Name> name,
    657                                              const VectorSlotPair& feedback) {
    658   NamedAccess access(SLOPPY, name, feedback);
    659   return new (zone()) Operator1<NamedAccess>(           // --
    660       IrOpcode::kJSLoadNamed, Operator::kNoProperties,  // opcode
    661       "JSLoadNamed",                                    // name
    662       2, 1, 1, 1, 1, 2,                                 // counts
    663       access);                                          // parameter
    664 }
    665 
    666 const Operator* JSOperatorBuilder::LoadProperty(
    667     VectorSlotPair const& feedback) {
    668   PropertyAccess access(SLOPPY, feedback);
    669   return new (zone()) Operator1<PropertyAccess>(           // --
    670       IrOpcode::kJSLoadProperty, Operator::kNoProperties,  // opcode
    671       "JSLoadProperty",                                    // name
    672       3, 1, 1, 1, 1, 2,                                    // counts
    673       access);                                             // parameter
    674 }
    675 
    676 const Operator* JSOperatorBuilder::GeneratorStore(int register_count) {
    677   return new (zone()) Operator1<int>(                   // --
    678       IrOpcode::kJSGeneratorStore, Operator::kNoThrow,  // opcode
    679       "JSGeneratorStore",                               // name
    680       3 + register_count, 1, 1, 0, 1, 0,                // counts
    681       register_count);                                  // parameter
    682 }
    683 
    684 const Operator* JSOperatorBuilder::GeneratorRestoreRegister(int index) {
    685   return new (zone()) Operator1<int>(                             // --
    686       IrOpcode::kJSGeneratorRestoreRegister, Operator::kNoThrow,  // opcode
    687       "JSGeneratorRestoreRegister",                               // name
    688       1, 1, 1, 1, 1, 0,                                           // counts
    689       index);                                                     // parameter
    690 }
    691 
    692 const Operator* JSOperatorBuilder::StoreNamed(LanguageMode language_mode,
    693                                               Handle<Name> name,
    694                                               VectorSlotPair const& feedback) {
    695   NamedAccess access(language_mode, name, feedback);
    696   return new (zone()) Operator1<NamedAccess>(            // --
    697       IrOpcode::kJSStoreNamed, Operator::kNoProperties,  // opcode
    698       "JSStoreNamed",                                    // name
    699       3, 1, 1, 0, 1, 2,                                  // counts
    700       access);                                           // parameter
    701 }
    702 
    703 
    704 const Operator* JSOperatorBuilder::StoreProperty(
    705     LanguageMode language_mode, VectorSlotPair const& feedback) {
    706   PropertyAccess access(language_mode, feedback);
    707   return new (zone()) Operator1<PropertyAccess>(            // --
    708       IrOpcode::kJSStoreProperty, Operator::kNoProperties,  // opcode
    709       "JSStoreProperty",                                    // name
    710       4, 1, 1, 0, 1, 2,                                     // counts
    711       access);                                              // parameter
    712 }
    713 
    714 
    715 const Operator* JSOperatorBuilder::DeleteProperty(LanguageMode language_mode) {
    716   return new (zone()) Operator1<LanguageMode>(               // --
    717       IrOpcode::kJSDeleteProperty, Operator::kNoProperties,  // opcode
    718       "JSDeleteProperty",                                    // name
    719       2, 1, 1, 1, 1, 2,                                      // counts
    720       language_mode);                                        // parameter
    721 }
    722 
    723 
    724 const Operator* JSOperatorBuilder::LoadGlobal(const Handle<Name>& name,
    725                                               const VectorSlotPair& feedback,
    726                                               TypeofMode typeof_mode) {
    727   LoadGlobalParameters parameters(name, feedback, typeof_mode);
    728   return new (zone()) Operator1<LoadGlobalParameters>(   // --
    729       IrOpcode::kJSLoadGlobal, Operator::kNoProperties,  // opcode
    730       "JSLoadGlobal",                                    // name
    731       1, 1, 1, 1, 1, 2,                                  // counts
    732       parameters);                                       // parameter
    733 }
    734 
    735 
    736 const Operator* JSOperatorBuilder::StoreGlobal(LanguageMode language_mode,
    737                                                const Handle<Name>& name,
    738                                                const VectorSlotPair& feedback) {
    739   StoreGlobalParameters parameters(language_mode, feedback, name);
    740   return new (zone()) Operator1<StoreGlobalParameters>(   // --
    741       IrOpcode::kJSStoreGlobal, Operator::kNoProperties,  // opcode
    742       "JSStoreGlobal",                                    // name
    743       2, 1, 1, 0, 1, 2,                                   // counts
    744       parameters);                                        // parameter
    745 }
    746 
    747 
    748 const Operator* JSOperatorBuilder::LoadContext(size_t depth, size_t index,
    749                                                bool immutable) {
    750   ContextAccess access(depth, index, immutable);
    751   return new (zone()) Operator1<ContextAccess>(  // --
    752       IrOpcode::kJSLoadContext,                  // opcode
    753       Operator::kNoWrite | Operator::kNoThrow,   // flags
    754       "JSLoadContext",                           // name
    755       1, 1, 0, 1, 1, 0,                          // counts
    756       access);                                   // parameter
    757 }
    758 
    759 
    760 const Operator* JSOperatorBuilder::StoreContext(size_t depth, size_t index) {
    761   ContextAccess access(depth, index, false);
    762   return new (zone()) Operator1<ContextAccess>(  // --
    763       IrOpcode::kJSStoreContext,                 // opcode
    764       Operator::kNoRead | Operator::kNoThrow,    // flags
    765       "JSStoreContext",                          // name
    766       2, 1, 1, 0, 1, 0,                          // counts
    767       access);                                   // parameter
    768 }
    769 
    770 const Operator* JSOperatorBuilder::LoadModule(int32_t cell_index) {
    771   return new (zone()) Operator1<int32_t>(       // --
    772       IrOpcode::kJSLoadModule,                  // opcode
    773       Operator::kNoWrite | Operator::kNoThrow,  // flags
    774       "JSLoadModule",                           // name
    775       1, 1, 1, 1, 1, 0,                         // counts
    776       cell_index);                              // parameter
    777 }
    778 
    779 const Operator* JSOperatorBuilder::StoreModule(int32_t cell_index) {
    780   return new (zone()) Operator1<int32_t>(      // --
    781       IrOpcode::kJSStoreModule,                // opcode
    782       Operator::kNoRead | Operator::kNoThrow,  // flags
    783       "JSStoreModule",                         // name
    784       2, 1, 1, 0, 1, 0,                        // counts
    785       cell_index);                             // parameter
    786 }
    787 
    788 const Operator* JSOperatorBuilder::CreateArguments(CreateArgumentsType type) {
    789   return new (zone()) Operator1<CreateArgumentsType>(         // --
    790       IrOpcode::kJSCreateArguments, Operator::kEliminatable,  // opcode
    791       "JSCreateArguments",                                    // name
    792       1, 1, 0, 1, 1, 0,                                       // counts
    793       type);                                                  // parameter
    794 }
    795 
    796 
    797 const Operator* JSOperatorBuilder::CreateArray(size_t arity,
    798                                                Handle<AllocationSite> site) {
    799   // constructor, new_target, arg1, ..., argN
    800   int const value_input_count = static_cast<int>(arity) + 2;
    801   CreateArrayParameters parameters(arity, site);
    802   return new (zone()) Operator1<CreateArrayParameters>(   // --
    803       IrOpcode::kJSCreateArray, Operator::kNoProperties,  // opcode
    804       "JSCreateArray",                                    // name
    805       value_input_count, 1, 1, 1, 1, 2,                   // counts
    806       parameters);                                        // parameter
    807 }
    808 
    809 
    810 const Operator* JSOperatorBuilder::CreateClosure(
    811     Handle<SharedFunctionInfo> shared_info, PretenureFlag pretenure) {
    812   CreateClosureParameters parameters(shared_info, pretenure);
    813   return new (zone()) Operator1<CreateClosureParameters>(  // --
    814       IrOpcode::kJSCreateClosure, Operator::kNoThrow,      // opcode
    815       "JSCreateClosure",                                   // name
    816       0, 1, 1, 1, 1, 0,                                    // counts
    817       parameters);                                         // parameter
    818 }
    819 
    820 const Operator* JSOperatorBuilder::CreateLiteralArray(
    821     Handle<FixedArray> constant_elements, int literal_flags, int literal_index,
    822     int number_of_elements) {
    823   CreateLiteralParameters parameters(constant_elements, number_of_elements,
    824                                      literal_flags, literal_index);
    825   return new (zone()) Operator1<CreateLiteralParameters>(        // --
    826       IrOpcode::kJSCreateLiteralArray, Operator::kNoProperties,  // opcode
    827       "JSCreateLiteralArray",                                    // name
    828       1, 1, 1, 1, 1, 2,                                          // counts
    829       parameters);                                               // parameter
    830 }
    831 
    832 const Operator* JSOperatorBuilder::CreateLiteralObject(
    833     Handle<FixedArray> constant_properties, int literal_flags,
    834     int literal_index, int number_of_properties) {
    835   CreateLiteralParameters parameters(constant_properties, number_of_properties,
    836                                      literal_flags, literal_index);
    837   return new (zone()) Operator1<CreateLiteralParameters>(         // --
    838       IrOpcode::kJSCreateLiteralObject, Operator::kNoProperties,  // opcode
    839       "JSCreateLiteralObject",                                    // name
    840       1, 1, 1, 1, 1, 2,                                           // counts
    841       parameters);                                                // parameter
    842 }
    843 
    844 
    845 const Operator* JSOperatorBuilder::CreateLiteralRegExp(
    846     Handle<String> constant_pattern, int literal_flags, int literal_index) {
    847   CreateLiteralParameters parameters(constant_pattern, -1, literal_flags,
    848                                      literal_index);
    849   return new (zone()) Operator1<CreateLiteralParameters>(         // --
    850       IrOpcode::kJSCreateLiteralRegExp, Operator::kNoProperties,  // opcode
    851       "JSCreateLiteralRegExp",                                    // name
    852       1, 1, 1, 1, 1, 2,                                           // counts
    853       parameters);                                                // parameter
    854 }
    855 
    856 
    857 const Operator* JSOperatorBuilder::CreateFunctionContext(int slot_count) {
    858   return new (zone()) Operator1<int>(                               // --
    859       IrOpcode::kJSCreateFunctionContext, Operator::kNoProperties,  // opcode
    860       "JSCreateFunctionContext",                                    // name
    861       1, 1, 1, 1, 1, 2,                                             // counts
    862       slot_count);                                                  // parameter
    863 }
    864 
    865 const Operator* JSOperatorBuilder::CreateCatchContext(
    866     const Handle<String>& name, const Handle<ScopeInfo>& scope_info) {
    867   CreateCatchContextParameters parameters(name, scope_info);
    868   return new (zone()) Operator1<CreateCatchContextParameters>(
    869       IrOpcode::kJSCreateCatchContext, Operator::kNoProperties,  // opcode
    870       "JSCreateCatchContext",                                    // name
    871       2, 1, 1, 1, 1, 2,                                          // counts
    872       parameters);                                               // parameter
    873 }
    874 
    875 const Operator* JSOperatorBuilder::CreateWithContext(
    876     const Handle<ScopeInfo>& scope_info) {
    877   return new (zone()) Operator1<Handle<ScopeInfo>>(
    878       IrOpcode::kJSCreateWithContext, Operator::kNoProperties,  // opcode
    879       "JSCreateWithContext",                                    // name
    880       2, 1, 1, 1, 1, 2,                                         // counts
    881       scope_info);                                              // parameter
    882 }
    883 
    884 const Operator* JSOperatorBuilder::CreateBlockContext(
    885     const Handle<ScopeInfo>& scpope_info) {
    886   return new (zone()) Operator1<Handle<ScopeInfo>>(              // --
    887       IrOpcode::kJSCreateBlockContext, Operator::kNoProperties,  // opcode
    888       "JSCreateBlockContext",                                    // name
    889       1, 1, 1, 1, 1, 2,                                          // counts
    890       scpope_info);                                              // parameter
    891 }
    892 
    893 
    894 const Operator* JSOperatorBuilder::CreateScriptContext(
    895     const Handle<ScopeInfo>& scpope_info) {
    896   return new (zone()) Operator1<Handle<ScopeInfo>>(               // --
    897       IrOpcode::kJSCreateScriptContext, Operator::kNoProperties,  // opcode
    898       "JSCreateScriptContext",                                    // name
    899       1, 1, 1, 1, 1, 2,                                           // counts
    900       scpope_info);                                               // parameter
    901 }
    902 
    903 }  // namespace compiler
    904 }  // namespace internal
    905 }  // namespace v8
    906