Home | History | Annotate | Download | only in compiler
      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/compiler/linkage.h"
      9 #include "src/compiler/opcodes.h"
     10 #include "src/compiler/operator.h"
     11 #include "src/unique.h"
     12 #include "src/zone.h"
     13 
     14 namespace v8 {
     15 namespace internal {
     16 namespace compiler {
     17 
     18 // Defines the location of a context slot relative to a specific scope. This is
     19 // used as a parameter by JSLoadContext and JSStoreContext operators and allows
     20 // accessing a context-allocated variable without keeping track of the scope.
     21 class ContextAccess {
     22  public:
     23   ContextAccess(int depth, int index, bool immutable)
     24       : immutable_(immutable), depth_(depth), index_(index) {
     25     DCHECK(0 <= depth && depth <= kMaxUInt16);
     26     DCHECK(0 <= index && static_cast<uint32_t>(index) <= kMaxUInt32);
     27   }
     28   int depth() const { return depth_; }
     29   int index() const { return index_; }
     30   bool immutable() const { return immutable_; }
     31 
     32  private:
     33   // For space reasons, we keep this tightly packed, otherwise we could just use
     34   // a simple int/int/bool POD.
     35   const bool immutable_;
     36   const uint16_t depth_;
     37   const uint32_t index_;
     38 };
     39 
     40 // Defines the property being loaded from an object by a named load. This is
     41 // used as a parameter by JSLoadNamed operators.
     42 struct LoadNamedParameters {
     43   Unique<Name> name;
     44   ContextualMode contextual_mode;
     45 };
     46 
     47 // Defines the arity and the call flags for a JavaScript function call. This is
     48 // used as a parameter by JSCall operators.
     49 struct CallParameters {
     50   int arity;
     51   CallFunctionFlags flags;
     52 };
     53 
     54 // Defines the property being stored to an object by a named store. This is
     55 // used as a parameter by JSStoreNamed operators.
     56 struct StoreNamedParameters {
     57   StrictMode strict_mode;
     58   Unique<Name> name;
     59 };
     60 
     61 // Interface for building JavaScript-level operators, e.g. directly from the
     62 // AST. Most operators have no parameters, thus can be globally shared for all
     63 // graphs.
     64 class JSOperatorBuilder {
     65  public:
     66   explicit JSOperatorBuilder(Zone* zone) : zone_(zone) {}
     67 
     68 #define SIMPLE(name, properties, inputs, outputs) \
     69   return new (zone_)                              \
     70       SimpleOperator(IrOpcode::k##name, properties, inputs, outputs, #name);
     71 
     72 #define NOPROPS(name, inputs, outputs) \
     73   SIMPLE(name, Operator::kNoProperties, inputs, outputs)
     74 
     75 #define OP1(name, ptype, pname, properties, inputs, outputs)                 \
     76   return new (zone_) Operator1<ptype>(IrOpcode::k##name, properties, inputs, \
     77                                       outputs, #name, pname)
     78 
     79 #define BINOP(name) NOPROPS(name, 2, 1)
     80 #define UNOP(name) NOPROPS(name, 1, 1)
     81 
     82 #define PURE_BINOP(name) SIMPLE(name, Operator::kPure, 2, 1)
     83 
     84   const Operator* Equal() { BINOP(JSEqual); }
     85   const Operator* NotEqual() { BINOP(JSNotEqual); }
     86   const Operator* StrictEqual() { PURE_BINOP(JSStrictEqual); }
     87   const Operator* StrictNotEqual() { PURE_BINOP(JSStrictNotEqual); }
     88   const Operator* LessThan() { BINOP(JSLessThan); }
     89   const Operator* GreaterThan() { BINOP(JSGreaterThan); }
     90   const Operator* LessThanOrEqual() { BINOP(JSLessThanOrEqual); }
     91   const Operator* GreaterThanOrEqual() { BINOP(JSGreaterThanOrEqual); }
     92   const Operator* BitwiseOr() { BINOP(JSBitwiseOr); }
     93   const Operator* BitwiseXor() { BINOP(JSBitwiseXor); }
     94   const Operator* BitwiseAnd() { BINOP(JSBitwiseAnd); }
     95   const Operator* ShiftLeft() { BINOP(JSShiftLeft); }
     96   const Operator* ShiftRight() { BINOP(JSShiftRight); }
     97   const Operator* ShiftRightLogical() { BINOP(JSShiftRightLogical); }
     98   const Operator* Add() { BINOP(JSAdd); }
     99   const Operator* Subtract() { BINOP(JSSubtract); }
    100   const Operator* Multiply() { BINOP(JSMultiply); }
    101   const Operator* Divide() { BINOP(JSDivide); }
    102   const Operator* Modulus() { BINOP(JSModulus); }
    103 
    104   const Operator* UnaryNot() { UNOP(JSUnaryNot); }
    105   const Operator* ToBoolean() { UNOP(JSToBoolean); }
    106   const Operator* ToNumber() { UNOP(JSToNumber); }
    107   const Operator* ToString() { UNOP(JSToString); }
    108   const Operator* ToName() { UNOP(JSToName); }
    109   const Operator* ToObject() { UNOP(JSToObject); }
    110   const Operator* Yield() { UNOP(JSYield); }
    111 
    112   const Operator* Create() { SIMPLE(JSCreate, Operator::kEliminatable, 0, 1); }
    113 
    114   const Operator* Call(int arguments, CallFunctionFlags flags) {
    115     CallParameters parameters = {arguments, flags};
    116     OP1(JSCallFunction, CallParameters, parameters, Operator::kNoProperties,
    117         arguments, 1);
    118   }
    119 
    120   const Operator* CallNew(int arguments) {
    121     return new (zone_)
    122         Operator1<int>(IrOpcode::kJSCallConstruct, Operator::kNoProperties,
    123                        arguments, 1, "JSCallConstruct", arguments);
    124   }
    125 
    126   const Operator* LoadProperty() { BINOP(JSLoadProperty); }
    127   const Operator* LoadNamed(Unique<Name> name,
    128                             ContextualMode contextual_mode = NOT_CONTEXTUAL) {
    129     LoadNamedParameters parameters = {name, contextual_mode};
    130     OP1(JSLoadNamed, LoadNamedParameters, parameters, Operator::kNoProperties,
    131         1, 1);
    132   }
    133 
    134   const Operator* StoreProperty(StrictMode strict_mode) {
    135     OP1(JSStoreProperty, StrictMode, strict_mode, Operator::kNoProperties, 3,
    136         0);
    137   }
    138 
    139   const Operator* StoreNamed(StrictMode strict_mode, Unique<Name> name) {
    140     StoreNamedParameters parameters = {strict_mode, name};
    141     OP1(JSStoreNamed, StoreNamedParameters, parameters, Operator::kNoProperties,
    142         2, 0);
    143   }
    144 
    145   const Operator* DeleteProperty(StrictMode strict_mode) {
    146     OP1(JSDeleteProperty, StrictMode, strict_mode, Operator::kNoProperties, 2,
    147         1);
    148   }
    149 
    150   const Operator* HasProperty() { NOPROPS(JSHasProperty, 2, 1); }
    151 
    152   const Operator* LoadContext(uint16_t depth, uint32_t index, bool immutable) {
    153     ContextAccess access(depth, index, immutable);
    154     OP1(JSLoadContext, ContextAccess, access,
    155         Operator::kEliminatable | Operator::kNoWrite, 1, 1);
    156   }
    157   const Operator* StoreContext(uint16_t depth, uint32_t index) {
    158     ContextAccess access(depth, index, false);
    159     OP1(JSStoreContext, ContextAccess, access, Operator::kNoProperties, 2, 0);
    160   }
    161 
    162   const Operator* TypeOf() { SIMPLE(JSTypeOf, Operator::kPure, 1, 1); }
    163   const Operator* InstanceOf() { NOPROPS(JSInstanceOf, 2, 1); }
    164   const Operator* Debugger() { NOPROPS(JSDebugger, 0, 0); }
    165 
    166   // TODO(titzer): nail down the static parts of each of these context flavors.
    167   const Operator* CreateFunctionContext() {
    168     NOPROPS(JSCreateFunctionContext, 1, 1);
    169   }
    170   const Operator* CreateCatchContext(Unique<String> name) {
    171     OP1(JSCreateCatchContext, Unique<String>, name, Operator::kNoProperties, 1,
    172         1);
    173   }
    174   const Operator* CreateWithContext() { NOPROPS(JSCreateWithContext, 2, 1); }
    175   const Operator* CreateBlockContext() { NOPROPS(JSCreateBlockContext, 2, 1); }
    176   const Operator* CreateModuleContext() {
    177     NOPROPS(JSCreateModuleContext, 2, 1);
    178   }
    179   const Operator* CreateGlobalContext() {
    180     NOPROPS(JSCreateGlobalContext, 2, 1);
    181   }
    182 
    183   const Operator* Runtime(Runtime::FunctionId function, int arguments) {
    184     const Runtime::Function* f = Runtime::FunctionForId(function);
    185     DCHECK(f->nargs == -1 || f->nargs == arguments);
    186     OP1(JSCallRuntime, Runtime::FunctionId, function, Operator::kNoProperties,
    187         arguments, f->result_size);
    188   }
    189 
    190 #undef SIMPLE
    191 #undef NOPROPS
    192 #undef OP1
    193 #undef BINOP
    194 #undef UNOP
    195 
    196  private:
    197   Zone* zone_;
    198 };
    199 
    200 // Specialization for static parameters of type {ContextAccess}.
    201 template <>
    202 struct StaticParameterTraits<ContextAccess> {
    203   static OStream& PrintTo(OStream& os, ContextAccess val) {  // NOLINT
    204     return os << val.depth() << "," << val.index()
    205               << (val.immutable() ? ",imm" : "");
    206   }
    207   static int HashCode(ContextAccess val) {
    208     return (val.depth() << 16) | (val.index() & 0xffff);
    209   }
    210   static bool Equals(ContextAccess a, ContextAccess b) {
    211     return a.immutable() == b.immutable() && a.depth() == b.depth() &&
    212            a.index() == b.index();
    213   }
    214 };
    215 
    216 // Specialization for static parameters of type {Runtime::FunctionId}.
    217 template <>
    218 struct StaticParameterTraits<Runtime::FunctionId> {
    219   static OStream& PrintTo(OStream& os, Runtime::FunctionId val) {  // NOLINT
    220     const Runtime::Function* f = Runtime::FunctionForId(val);
    221     return os << (f->name ? f->name : "?Runtime?");
    222   }
    223   static int HashCode(Runtime::FunctionId val) { return static_cast<int>(val); }
    224   static bool Equals(Runtime::FunctionId a, Runtime::FunctionId b) {
    225     return a == b;
    226   }
    227 };
    228 
    229 }  // namespace compiler
    230 }  // namespace internal
    231 }  // namespace v8
    232 
    233 #endif  // V8_COMPILER_JS_OPERATOR_H_
    234