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/graph-inl.h"
      6 #include "src/compiler/js-operator.h"
      7 #include "src/compiler/node.h"
      8 #include "src/compiler/node-properties-inl.h"
      9 #include "src/compiler/node-properties.h"
     10 #include "src/compiler/simplified-operator.h"
     11 #include "src/compiler/typer.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 namespace compiler {
     16 
     17 Typer::Typer(Zone* zone) : zone_(zone) {
     18   Type* number = Type::Number(zone);
     19   Type* signed32 = Type::Signed32(zone);
     20   Type* unsigned32 = Type::Unsigned32(zone);
     21   Type* integral32 = Type::Integral32(zone);
     22   Type* object = Type::Object(zone);
     23   Type* undefined = Type::Undefined(zone);
     24   number_fun0_ = Type::Function(number, zone);
     25   number_fun1_ = Type::Function(number, number, zone);
     26   number_fun2_ = Type::Function(number, number, number, zone);
     27   imul_fun_ = Type::Function(signed32, integral32, integral32, zone);
     28 
     29 #define NATIVE_TYPE(sem, rep) \
     30   Type::Intersect(Type::sem(zone), Type::rep(zone), zone)
     31   // TODO(rossberg): Use range types for more precision, once we have them.
     32   Type* int8 = NATIVE_TYPE(SignedSmall, UntaggedInt8);
     33   Type* int16 = NATIVE_TYPE(SignedSmall, UntaggedInt16);
     34   Type* int32 = NATIVE_TYPE(Signed32, UntaggedInt32);
     35   Type* uint8 = NATIVE_TYPE(UnsignedSmall, UntaggedInt8);
     36   Type* uint16 = NATIVE_TYPE(UnsignedSmall, UntaggedInt16);
     37   Type* uint32 = NATIVE_TYPE(Unsigned32, UntaggedInt32);
     38   Type* float32 = NATIVE_TYPE(Number, UntaggedFloat32);
     39   Type* float64 = NATIVE_TYPE(Number, UntaggedFloat64);
     40 #undef NATIVE_TYPE
     41   Type* buffer = Type::Buffer(zone);
     42   Type* int8_array = Type::Array(int8, zone);
     43   Type* int16_array = Type::Array(int16, zone);
     44   Type* int32_array = Type::Array(int32, zone);
     45   Type* uint8_array = Type::Array(uint8, zone);
     46   Type* uint16_array = Type::Array(uint16, zone);
     47   Type* uint32_array = Type::Array(uint32, zone);
     48   Type* float32_array = Type::Array(float32, zone);
     49   Type* float64_array = Type::Array(float64, zone);
     50   Type* arg1 = Type::Union(unsigned32, object, zone);
     51   Type* arg2 = Type::Union(unsigned32, undefined, zone);
     52   Type* arg3 = arg2;
     53   array_buffer_fun_ = Type::Function(buffer, unsigned32, zone);
     54   int8_array_fun_ = Type::Function(int8_array, arg1, arg2, arg3, zone);
     55   int16_array_fun_ = Type::Function(int16_array, arg1, arg2, arg3, zone);
     56   int32_array_fun_ = Type::Function(int32_array, arg1, arg2, arg3, zone);
     57   uint8_array_fun_ = Type::Function(uint8_array, arg1, arg2, arg3, zone);
     58   uint16_array_fun_ = Type::Function(uint16_array, arg1, arg2, arg3, zone);
     59   uint32_array_fun_ = Type::Function(uint32_array, arg1, arg2, arg3, zone);
     60   float32_array_fun_ = Type::Function(float32_array, arg1, arg2, arg3, zone);
     61   float64_array_fun_ = Type::Function(float64_array, arg1, arg2, arg3, zone);
     62 }
     63 
     64 
     65 class Typer::Visitor : public NullNodeVisitor {
     66  public:
     67   Visitor(Typer* typer, MaybeHandle<Context> context)
     68       : typer_(typer), context_(context) {}
     69 
     70   Bounds TypeNode(Node* node) {
     71     switch (node->opcode()) {
     72 #define DECLARE_CASE(x) case IrOpcode::k##x: return Type##x(node);
     73       DECLARE_CASE(Start)
     74       VALUE_OP_LIST(DECLARE_CASE)
     75 #undef DECLARE_CASE
     76 
     77 #define DECLARE_CASE(x) case IrOpcode::k##x:
     78       DECLARE_CASE(End)
     79       INNER_CONTROL_OP_LIST(DECLARE_CASE)
     80 #undef DECLARE_CASE
     81       break;
     82     }
     83     UNREACHABLE();
     84     return Bounds();
     85   }
     86 
     87   Type* TypeConstant(Handle<Object> value);
     88 
     89  protected:
     90 #define DECLARE_METHOD(x) inline Bounds Type##x(Node* node);
     91   DECLARE_METHOD(Start)
     92   VALUE_OP_LIST(DECLARE_METHOD)
     93 #undef DECLARE_METHOD
     94 
     95   Bounds OperandType(Node* node, int i) {
     96     return NodeProperties::GetBounds(NodeProperties::GetValueInput(node, i));
     97   }
     98 
     99   Type* ContextType(Node* node) {
    100     Bounds result =
    101         NodeProperties::GetBounds(NodeProperties::GetContextInput(node));
    102     DCHECK(result.upper->Maybe(Type::Internal()));
    103     // TODO(rossberg): More precisely, instead of the above assertion, we should
    104     // back-propagate the constraint that it has to be a subtype of Internal.
    105     return result.upper;
    106   }
    107 
    108   Zone* zone() { return typer_->zone(); }
    109   Isolate* isolate() { return typer_->isolate(); }
    110   MaybeHandle<Context> context() { return context_; }
    111 
    112  private:
    113   Typer* typer_;
    114   MaybeHandle<Context> context_;
    115 };
    116 
    117 
    118 class Typer::RunVisitor : public Typer::Visitor {
    119  public:
    120   RunVisitor(Typer* typer, MaybeHandle<Context> context)
    121       : Visitor(typer, context),
    122         redo(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {}
    123 
    124   GenericGraphVisit::Control Post(Node* node) {
    125     if (OperatorProperties::HasValueOutput(node->op())) {
    126       Bounds bounds = TypeNode(node);
    127       NodeProperties::SetBounds(node, bounds);
    128       // Remember incompletely typed nodes for least fixpoint iteration.
    129       int arity = OperatorProperties::GetValueInputCount(node->op());
    130       for (int i = 0; i < arity; ++i) {
    131         // TODO(rossberg): change once IsTyped is available.
    132         // if (!NodeProperties::IsTyped(NodeProperties::GetValueInput(node, i)))
    133         if (OperandType(node, i).upper->Is(Type::None())) {
    134           redo.insert(node);
    135           break;
    136         }
    137       }
    138     }
    139     return GenericGraphVisit::CONTINUE;
    140   }
    141 
    142   NodeSet redo;
    143 };
    144 
    145 
    146 class Typer::NarrowVisitor : public Typer::Visitor {
    147  public:
    148   NarrowVisitor(Typer* typer, MaybeHandle<Context> context)
    149       : Visitor(typer, context) {}
    150 
    151   GenericGraphVisit::Control Pre(Node* node) {
    152     if (OperatorProperties::HasValueOutput(node->op())) {
    153       Bounds previous = NodeProperties::GetBounds(node);
    154       Bounds bounds = TypeNode(node);
    155       NodeProperties::SetBounds(node, Bounds::Both(bounds, previous, zone()));
    156       DCHECK(bounds.Narrows(previous));
    157       // Stop when nothing changed (but allow re-entry in case it does later).
    158       return previous.Narrows(bounds)
    159           ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER;
    160     } else {
    161       return GenericGraphVisit::SKIP;
    162     }
    163   }
    164 
    165   GenericGraphVisit::Control Post(Node* node) {
    166     return GenericGraphVisit::REENTER;
    167   }
    168 };
    169 
    170 
    171 class Typer::WidenVisitor : public Typer::Visitor {
    172  public:
    173   WidenVisitor(Typer* typer, MaybeHandle<Context> context)
    174       : Visitor(typer, context) {}
    175 
    176   GenericGraphVisit::Control Pre(Node* node) {
    177     if (OperatorProperties::HasValueOutput(node->op())) {
    178       Bounds previous = NodeProperties::GetBounds(node);
    179       Bounds bounds = TypeNode(node);
    180       DCHECK(previous.lower->Is(bounds.lower));
    181       DCHECK(previous.upper->Is(bounds.upper));
    182       NodeProperties::SetBounds(node, bounds);  // TODO(rossberg): Either?
    183       // Stop when nothing changed (but allow re-entry in case it does later).
    184       return bounds.Narrows(previous)
    185           ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER;
    186     } else {
    187       return GenericGraphVisit::SKIP;
    188     }
    189   }
    190 
    191   GenericGraphVisit::Control Post(Node* node) {
    192     return GenericGraphVisit::REENTER;
    193   }
    194 };
    195 
    196 
    197 void Typer::Run(Graph* graph, MaybeHandle<Context> context) {
    198   RunVisitor typing(this, context);
    199   graph->VisitNodeInputsFromEnd(&typing);
    200   // Find least fixpoint.
    201   for (NodeSetIter i = typing.redo.begin(); i != typing.redo.end(); ++i) {
    202     Widen(graph, *i, context);
    203   }
    204 }
    205 
    206 
    207 void Typer::Narrow(Graph* graph, Node* start, MaybeHandle<Context> context) {
    208   NarrowVisitor typing(this, context);
    209   graph->VisitNodeUsesFrom(start, &typing);
    210 }
    211 
    212 
    213 void Typer::Widen(Graph* graph, Node* start, MaybeHandle<Context> context) {
    214   WidenVisitor typing(this, context);
    215   graph->VisitNodeUsesFrom(start, &typing);
    216 }
    217 
    218 
    219 void Typer::Init(Node* node) {
    220   if (OperatorProperties::HasValueOutput(node->op())) {
    221     Visitor typing(this, MaybeHandle<Context>());
    222     Bounds bounds = typing.TypeNode(node);
    223     NodeProperties::SetBounds(node, bounds);
    224   }
    225 }
    226 
    227 
    228 // -----------------------------------------------------------------------------
    229 
    230 
    231 // Control operators.
    232 
    233 Bounds Typer::Visitor::TypeStart(Node* node) {
    234   return Bounds(Type::Internal(zone()));
    235 }
    236 
    237 
    238 // Common operators.
    239 
    240 Bounds Typer::Visitor::TypeParameter(Node* node) {
    241   return Bounds::Unbounded(zone());
    242 }
    243 
    244 
    245 Bounds Typer::Visitor::TypeInt32Constant(Node* node) {
    246   // TODO(titzer): only call Type::Of() if the type is not already known.
    247   return Bounds(Type::Of(OpParameter<int32_t>(node), zone()));
    248 }
    249 
    250 
    251 Bounds Typer::Visitor::TypeInt64Constant(Node* node) {
    252   // TODO(titzer): only call Type::Of() if the type is not already known.
    253   return Bounds(
    254       Type::Of(static_cast<double>(OpParameter<int64_t>(node)), zone()));
    255 }
    256 
    257 
    258 Bounds Typer::Visitor::TypeFloat32Constant(Node* node) {
    259   // TODO(titzer): only call Type::Of() if the type is not already known.
    260   return Bounds(Type::Of(OpParameter<float>(node), zone()));
    261 }
    262 
    263 
    264 Bounds Typer::Visitor::TypeFloat64Constant(Node* node) {
    265   // TODO(titzer): only call Type::Of() if the type is not already known.
    266   return Bounds(Type::Of(OpParameter<double>(node), zone()));
    267 }
    268 
    269 
    270 Bounds Typer::Visitor::TypeNumberConstant(Node* node) {
    271   // TODO(titzer): only call Type::Of() if the type is not already known.
    272   return Bounds(Type::Of(OpParameter<double>(node), zone()));
    273 }
    274 
    275 
    276 Bounds Typer::Visitor::TypeHeapConstant(Node* node) {
    277   return Bounds(TypeConstant(OpParameter<Unique<Object> >(node).handle()));
    278 }
    279 
    280 
    281 Bounds Typer::Visitor::TypeExternalConstant(Node* node) {
    282   return Bounds(Type::Internal(zone()));
    283 }
    284 
    285 
    286 Bounds Typer::Visitor::TypePhi(Node* node) {
    287   int arity = OperatorProperties::GetValueInputCount(node->op());
    288   Bounds bounds = OperandType(node, 0);
    289   for (int i = 1; i < arity; ++i) {
    290     bounds = Bounds::Either(bounds, OperandType(node, i), zone());
    291   }
    292   return bounds;
    293 }
    294 
    295 
    296 Bounds Typer::Visitor::TypeEffectPhi(Node* node) {
    297   UNREACHABLE();
    298   return Bounds();
    299 }
    300 
    301 
    302 Bounds Typer::Visitor::TypeControlEffect(Node* node) {
    303   UNREACHABLE();
    304   return Bounds();
    305 }
    306 
    307 
    308 Bounds Typer::Visitor::TypeValueEffect(Node* node) {
    309   UNREACHABLE();
    310   return Bounds();
    311 }
    312 
    313 
    314 Bounds Typer::Visitor::TypeFinish(Node* node) {
    315   return OperandType(node, 0);
    316 }
    317 
    318 
    319 Bounds Typer::Visitor::TypeFrameState(Node* node) {
    320   // TODO(rossberg): Ideally FrameState wouldn't have a value output.
    321   return Bounds(Type::Internal(zone()));
    322 }
    323 
    324 
    325 Bounds Typer::Visitor::TypeStateValues(Node* node) {
    326   return Bounds(Type::Internal(zone()));
    327 }
    328 
    329 
    330 Bounds Typer::Visitor::TypeCall(Node* node) {
    331   return Bounds::Unbounded(zone());
    332 }
    333 
    334 
    335 Bounds Typer::Visitor::TypeProjection(Node* node) {
    336   // TODO(titzer): use the output type of the input to determine the bounds.
    337   return Bounds::Unbounded(zone());
    338 }
    339 
    340 
    341 // JS comparison operators.
    342 
    343 #define DEFINE_METHOD(x)                       \
    344   Bounds Typer::Visitor::Type##x(Node* node) { \
    345     return Bounds(Type::Boolean(zone()));      \
    346   }
    347 JS_COMPARE_BINOP_LIST(DEFINE_METHOD)
    348 #undef DEFINE_METHOD
    349 
    350 
    351 // JS bitwise operators.
    352 
    353 Bounds Typer::Visitor::TypeJSBitwiseOr(Node* node) {
    354   Bounds left = OperandType(node, 0);
    355   Bounds right = OperandType(node, 1);
    356   Type* upper = Type::Union(left.upper, right.upper, zone());
    357   if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone());
    358   Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone());
    359   return Bounds(lower, upper);
    360 }
    361 
    362 
    363 Bounds Typer::Visitor::TypeJSBitwiseAnd(Node* node) {
    364   Bounds left = OperandType(node, 0);
    365   Bounds right = OperandType(node, 1);
    366   Type* upper = Type::Union(left.upper, right.upper, zone());
    367   if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone());
    368   Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone());
    369   return Bounds(lower, upper);
    370 }
    371 
    372 
    373 Bounds Typer::Visitor::TypeJSBitwiseXor(Node* node) {
    374   return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone()));
    375 }
    376 
    377 
    378 Bounds Typer::Visitor::TypeJSShiftLeft(Node* node) {
    379   return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone()));
    380 }
    381 
    382 
    383 Bounds Typer::Visitor::TypeJSShiftRight(Node* node) {
    384   return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone()));
    385 }
    386 
    387 
    388 Bounds Typer::Visitor::TypeJSShiftRightLogical(Node* node) {
    389   return Bounds(Type::UnsignedSmall(zone()), Type::Unsigned32(zone()));
    390 }
    391 
    392 
    393 // JS arithmetic operators.
    394 
    395 Bounds Typer::Visitor::TypeJSAdd(Node* node) {
    396   Bounds left = OperandType(node, 0);
    397   Bounds right = OperandType(node, 1);
    398   Type* lower =
    399       left.lower->Is(Type::None()) || right.lower->Is(Type::None()) ?
    400           Type::None(zone()) :
    401       left.lower->Is(Type::Number()) && right.lower->Is(Type::Number()) ?
    402           Type::SignedSmall(zone()) :
    403       left.lower->Is(Type::String()) || right.lower->Is(Type::String()) ?
    404           Type::String(zone()) : Type::None(zone());
    405   Type* upper =
    406       left.upper->Is(Type::None()) && right.upper->Is(Type::None()) ?
    407           Type::None(zone()) :
    408       left.upper->Is(Type::Number()) && right.upper->Is(Type::Number()) ?
    409           Type::Number(zone()) :
    410       left.upper->Is(Type::String()) || right.upper->Is(Type::String()) ?
    411           Type::String(zone()) : Type::NumberOrString(zone());
    412   return Bounds(lower, upper);
    413 }
    414 
    415 
    416 Bounds Typer::Visitor::TypeJSSubtract(Node* node) {
    417   return Bounds(Type::SignedSmall(zone()), Type::Number(zone()));
    418 }
    419 
    420 
    421 Bounds Typer::Visitor::TypeJSMultiply(Node* node) {
    422   return Bounds(Type::SignedSmall(zone()), Type::Number(zone()));
    423 }
    424 
    425 
    426 Bounds Typer::Visitor::TypeJSDivide(Node* node) {
    427   return Bounds(Type::SignedSmall(zone()), Type::Number(zone()));
    428 }
    429 
    430 
    431 Bounds Typer::Visitor::TypeJSModulus(Node* node) {
    432   return Bounds(Type::SignedSmall(zone()), Type::Number(zone()));
    433 }
    434 
    435 
    436 // JS unary operators.
    437 
    438 Bounds Typer::Visitor::TypeJSUnaryNot(Node* node) {
    439   return Bounds(Type::Boolean(zone()));
    440 }
    441 
    442 
    443 Bounds Typer::Visitor::TypeJSTypeOf(Node* node) {
    444   return Bounds(Type::InternalizedString(zone()));
    445 }
    446 
    447 
    448 // JS conversion operators.
    449 
    450 Bounds Typer::Visitor::TypeJSToBoolean(Node* node) {
    451   return Bounds(Type::Boolean(zone()));
    452 }
    453 
    454 
    455 Bounds Typer::Visitor::TypeJSToNumber(Node* node) {
    456   return Bounds(Type::SignedSmall(zone()), Type::Number(zone()));
    457 }
    458 
    459 
    460 Bounds Typer::Visitor::TypeJSToString(Node* node) {
    461   return Bounds(Type::None(zone()), Type::String(zone()));
    462 }
    463 
    464 
    465 Bounds Typer::Visitor::TypeJSToName(Node* node) {
    466   return Bounds(Type::None(zone()), Type::Name(zone()));
    467 }
    468 
    469 
    470 Bounds Typer::Visitor::TypeJSToObject(Node* node) {
    471   return Bounds(Type::None(zone()), Type::Receiver(zone()));
    472 }
    473 
    474 
    475 // JS object operators.
    476 
    477 Bounds Typer::Visitor::TypeJSCreate(Node* node) {
    478   return Bounds(Type::None(zone()), Type::Object(zone()));
    479 }
    480 
    481 
    482 Bounds Typer::Visitor::TypeJSLoadProperty(Node* node) {
    483   Bounds object = OperandType(node, 0);
    484   Bounds name = OperandType(node, 1);
    485   Bounds result = Bounds::Unbounded(zone());
    486   // TODO(rossberg): Use range types and sized array types to filter undefined.
    487   if (object.lower->IsArray() && name.lower->Is(Type::Integral32())) {
    488     result.lower = Type::Union(
    489         object.lower->AsArray()->Element(), Type::Undefined(zone()), zone());
    490   }
    491   if (object.upper->IsArray() && name.upper->Is(Type::Integral32())) {
    492     result.upper = Type::Union(
    493         object.upper->AsArray()->Element(),  Type::Undefined(zone()), zone());
    494   }
    495   return result;
    496 }
    497 
    498 
    499 Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) {
    500   return Bounds::Unbounded(zone());
    501 }
    502 
    503 
    504 Bounds Typer::Visitor::TypeJSStoreProperty(Node* node) {
    505   UNREACHABLE();
    506   return Bounds();
    507 }
    508 
    509 
    510 Bounds Typer::Visitor::TypeJSStoreNamed(Node* node) {
    511   UNREACHABLE();
    512   return Bounds();
    513 }
    514 
    515 
    516 Bounds Typer::Visitor::TypeJSDeleteProperty(Node* node) {
    517   return Bounds(Type::Boolean(zone()));
    518 }
    519 
    520 
    521 Bounds Typer::Visitor::TypeJSHasProperty(Node* node) {
    522   return Bounds(Type::Boolean(zone()));
    523 }
    524 
    525 
    526 Bounds Typer::Visitor::TypeJSInstanceOf(Node* node) {
    527   return Bounds(Type::Boolean(zone()));
    528 }
    529 
    530 
    531 // JS context operators.
    532 
    533 Bounds Typer::Visitor::TypeJSLoadContext(Node* node) {
    534   Bounds outer = OperandType(node, 0);
    535   DCHECK(outer.upper->Maybe(Type::Internal()));
    536   // TODO(rossberg): More precisely, instead of the above assertion, we should
    537   // back-propagate the constraint that it has to be a subtype of Internal.
    538 
    539   ContextAccess access = OpParameter<ContextAccess>(node);
    540   Type* context_type = outer.upper;
    541   MaybeHandle<Context> context;
    542   if (context_type->IsConstant()) {
    543     context = Handle<Context>::cast(context_type->AsConstant()->Value());
    544   }
    545   // Walk context chain (as far as known), mirroring dynamic lookup.
    546   // Since contexts are mutable, the information is only useful as a lower
    547   // bound.
    548   // TODO(rossberg): Could use scope info to fix upper bounds for constant
    549   // bindings if we know that this code is never shared.
    550   for (int i = access.depth(); i > 0; --i) {
    551     if (context_type->IsContext()) {
    552       context_type = context_type->AsContext()->Outer();
    553       if (context_type->IsConstant()) {
    554         context = Handle<Context>::cast(context_type->AsConstant()->Value());
    555       }
    556     } else if (!context.is_null()) {
    557       context = handle(context.ToHandleChecked()->previous(), isolate());
    558     }
    559   }
    560   if (context.is_null()) {
    561     return Bounds::Unbounded(zone());
    562   } else {
    563     Handle<Object> value =
    564         handle(context.ToHandleChecked()->get(access.index()), isolate());
    565     Type* lower = TypeConstant(value);
    566     return Bounds(lower, Type::Any(zone()));
    567   }
    568 }
    569 
    570 
    571 Bounds Typer::Visitor::TypeJSStoreContext(Node* node) {
    572   UNREACHABLE();
    573   return Bounds();
    574 }
    575 
    576 
    577 Bounds Typer::Visitor::TypeJSCreateFunctionContext(Node* node) {
    578   Type* outer = ContextType(node);
    579   return Bounds(Type::Context(outer, zone()));
    580 }
    581 
    582 
    583 Bounds Typer::Visitor::TypeJSCreateCatchContext(Node* node) {
    584   Type* outer = ContextType(node);
    585   return Bounds(Type::Context(outer, zone()));
    586 }
    587 
    588 
    589 Bounds Typer::Visitor::TypeJSCreateWithContext(Node* node) {
    590   Type* outer = ContextType(node);
    591   return Bounds(Type::Context(outer, zone()));
    592 }
    593 
    594 
    595 Bounds Typer::Visitor::TypeJSCreateBlockContext(Node* node) {
    596   Type* outer = ContextType(node);
    597   return Bounds(Type::Context(outer, zone()));
    598 }
    599 
    600 
    601 Bounds Typer::Visitor::TypeJSCreateModuleContext(Node* node) {
    602   // TODO(rossberg): this is probably incorrect
    603   Type* outer = ContextType(node);
    604   return Bounds(Type::Context(outer, zone()));
    605 }
    606 
    607 
    608 Bounds Typer::Visitor::TypeJSCreateGlobalContext(Node* node) {
    609   Type* outer = ContextType(node);
    610   return Bounds(Type::Context(outer, zone()));
    611 }
    612 
    613 
    614 // JS other operators.
    615 
    616 Bounds Typer::Visitor::TypeJSYield(Node* node) {
    617   return Bounds::Unbounded(zone());
    618 }
    619 
    620 
    621 Bounds Typer::Visitor::TypeJSCallConstruct(Node* node) {
    622   return Bounds(Type::None(zone()), Type::Receiver(zone()));
    623 }
    624 
    625 
    626 Bounds Typer::Visitor::TypeJSCallFunction(Node* node) {
    627   Bounds fun = OperandType(node, 0);
    628   Type* lower = fun.lower->IsFunction()
    629       ? fun.lower->AsFunction()->Result() : Type::None(zone());
    630   Type* upper = fun.upper->IsFunction()
    631       ? fun.upper->AsFunction()->Result() : Type::Any(zone());
    632   return Bounds(lower, upper);
    633 }
    634 
    635 
    636 Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) {
    637   return Bounds::Unbounded(zone());
    638 }
    639 
    640 
    641 Bounds Typer::Visitor::TypeJSDebugger(Node* node) {
    642   return Bounds::Unbounded(zone());
    643 }
    644 
    645 
    646 // Simplified operators.
    647 
    648 Bounds Typer::Visitor::TypeBooleanNot(Node* node) {
    649   return Bounds(Type::Boolean(zone()));
    650 }
    651 
    652 
    653 Bounds Typer::Visitor::TypeBooleanToNumber(Node* node) {
    654   return Bounds(Type::Number(zone()));
    655 }
    656 
    657 
    658 Bounds Typer::Visitor::TypeNumberEqual(Node* node) {
    659   return Bounds(Type::Boolean(zone()));
    660 }
    661 
    662 
    663 Bounds Typer::Visitor::TypeNumberLessThan(Node* node) {
    664   return Bounds(Type::Boolean(zone()));
    665 }
    666 
    667 
    668 Bounds Typer::Visitor::TypeNumberLessThanOrEqual(Node* node) {
    669   return Bounds(Type::Boolean(zone()));
    670 }
    671 
    672 
    673 Bounds Typer::Visitor::TypeNumberAdd(Node* node) {
    674   return Bounds(Type::Number(zone()));
    675 }
    676 
    677 
    678 Bounds Typer::Visitor::TypeNumberSubtract(Node* node) {
    679   return Bounds(Type::Number(zone()));
    680 }
    681 
    682 
    683 Bounds Typer::Visitor::TypeNumberMultiply(Node* node) {
    684   return Bounds(Type::Number(zone()));
    685 }
    686 
    687 
    688 Bounds Typer::Visitor::TypeNumberDivide(Node* node) {
    689   return Bounds(Type::Number(zone()));
    690 }
    691 
    692 
    693 Bounds Typer::Visitor::TypeNumberModulus(Node* node) {
    694   return Bounds(Type::Number(zone()));
    695 }
    696 
    697 
    698 Bounds Typer::Visitor::TypeNumberToInt32(Node* node) {
    699   Bounds arg = OperandType(node, 0);
    700   Type* s32 = Type::Signed32(zone());
    701   Type* lower = arg.lower->Is(s32) ? arg.lower : s32;
    702   Type* upper = arg.upper->Is(s32) ? arg.upper : s32;
    703   return Bounds(lower, upper);
    704 }
    705 
    706 
    707 Bounds Typer::Visitor::TypeNumberToUint32(Node* node) {
    708   Bounds arg = OperandType(node, 0);
    709   Type* u32 = Type::Unsigned32(zone());
    710   Type* lower = arg.lower->Is(u32) ? arg.lower : u32;
    711   Type* upper = arg.upper->Is(u32) ? arg.upper : u32;
    712   return Bounds(lower, upper);
    713 }
    714 
    715 
    716 Bounds Typer::Visitor::TypeReferenceEqual(Node* node) {
    717   return Bounds(Type::Boolean(zone()));
    718 }
    719 
    720 
    721 Bounds Typer::Visitor::TypeStringEqual(Node* node) {
    722   return Bounds(Type::Boolean(zone()));
    723 }
    724 
    725 
    726 Bounds Typer::Visitor::TypeStringLessThan(Node* node) {
    727   return Bounds(Type::Boolean(zone()));
    728 }
    729 
    730 
    731 Bounds Typer::Visitor::TypeStringLessThanOrEqual(Node* node) {
    732   return Bounds(Type::Boolean(zone()));
    733 }
    734 
    735 
    736 Bounds Typer::Visitor::TypeStringAdd(Node* node) {
    737   return Bounds(Type::String(zone()));
    738 }
    739 
    740 
    741 Bounds Typer::Visitor::TypeChangeTaggedToInt32(Node* node) {
    742   // TODO(titzer): type is type of input, representation is Word32.
    743   return Bounds(Type::Integral32());
    744 }
    745 
    746 
    747 Bounds Typer::Visitor::TypeChangeTaggedToUint32(Node* node) {
    748   return Bounds(Type::Integral32());  // TODO(titzer): add appropriate rep
    749 }
    750 
    751 
    752 Bounds Typer::Visitor::TypeChangeTaggedToFloat64(Node* node) {
    753   // TODO(titzer): type is type of input, representation is Float64.
    754   return Bounds(Type::Number());
    755 }
    756 
    757 
    758 Bounds Typer::Visitor::TypeChangeInt32ToTagged(Node* node) {
    759   // TODO(titzer): type is type of input, representation is Tagged.
    760   return Bounds(Type::Integral32());
    761 }
    762 
    763 
    764 Bounds Typer::Visitor::TypeChangeUint32ToTagged(Node* node) {
    765   // TODO(titzer): type is type of input, representation is Tagged.
    766   return Bounds(Type::Unsigned32());
    767 }
    768 
    769 
    770 Bounds Typer::Visitor::TypeChangeFloat64ToTagged(Node* node) {
    771   // TODO(titzer): type is type of input, representation is Tagged.
    772   return Bounds(Type::Number());
    773 }
    774 
    775 
    776 Bounds Typer::Visitor::TypeChangeBoolToBit(Node* node) {
    777   // TODO(titzer): type is type of input, representation is Bit.
    778   return Bounds(Type::Boolean());
    779 }
    780 
    781 
    782 Bounds Typer::Visitor::TypeChangeBitToBool(Node* node) {
    783   // TODO(titzer): type is type of input, representation is Tagged.
    784   return Bounds(Type::Boolean());
    785 }
    786 
    787 
    788 Bounds Typer::Visitor::TypeLoadField(Node* node) {
    789   return Bounds(FieldAccessOf(node->op()).type);
    790 }
    791 
    792 
    793 Bounds Typer::Visitor::TypeLoadElement(Node* node) {
    794   return Bounds(ElementAccessOf(node->op()).type);
    795 }
    796 
    797 
    798 Bounds Typer::Visitor::TypeStoreField(Node* node) {
    799   UNREACHABLE();
    800   return Bounds();
    801 }
    802 
    803 
    804 Bounds Typer::Visitor::TypeStoreElement(Node* node) {
    805   UNREACHABLE();
    806   return Bounds();
    807 }
    808 
    809 
    810 // Machine operators.
    811 
    812 // TODO(rossberg): implement
    813 #define DEFINE_METHOD(x) \
    814     Bounds Typer::Visitor::Type##x(Node* node) { return Bounds(Type::None()); }
    815 MACHINE_OP_LIST(DEFINE_METHOD)
    816 #undef DEFINE_METHOD
    817 
    818 
    819 // Heap constants.
    820 
    821 Type* Typer::Visitor::TypeConstant(Handle<Object> value) {
    822   if (value->IsJSFunction() && JSFunction::cast(*value)->IsBuiltin() &&
    823       !context().is_null()) {
    824     Handle<Context> native =
    825         handle(context().ToHandleChecked()->native_context(), isolate());
    826     if (*value == native->math_abs_fun()) {
    827       return typer_->number_fun1_;  // TODO(rossberg): can't express overloading
    828     } else if (*value == native->math_acos_fun()) {
    829       return typer_->number_fun1_;
    830     } else if (*value == native->math_asin_fun()) {
    831       return typer_->number_fun1_;
    832     } else if (*value == native->math_atan_fun()) {
    833       return typer_->number_fun1_;
    834     } else if (*value == native->math_atan2_fun()) {
    835       return typer_->number_fun2_;
    836     } else if (*value == native->math_ceil_fun()) {
    837       return typer_->number_fun1_;
    838     } else if (*value == native->math_cos_fun()) {
    839       return typer_->number_fun1_;
    840     } else if (*value == native->math_exp_fun()) {
    841       return typer_->number_fun1_;
    842     } else if (*value == native->math_floor_fun()) {
    843       return typer_->number_fun1_;
    844     } else if (*value == native->math_imul_fun()) {
    845       return typer_->imul_fun_;
    846     } else if (*value == native->math_log_fun()) {
    847       return typer_->number_fun1_;
    848     } else if (*value == native->math_pow_fun()) {
    849       return typer_->number_fun2_;
    850     } else if (*value == native->math_random_fun()) {
    851       return typer_->number_fun0_;
    852     } else if (*value == native->math_round_fun()) {
    853       return typer_->number_fun1_;
    854     } else if (*value == native->math_sin_fun()) {
    855       return typer_->number_fun1_;
    856     } else if (*value == native->math_sqrt_fun()) {
    857       return typer_->number_fun1_;
    858     } else if (*value == native->math_tan_fun()) {
    859       return typer_->number_fun1_;
    860     } else if (*value == native->array_buffer_fun()) {
    861       return typer_->array_buffer_fun_;
    862     } else if (*value == native->int8_array_fun()) {
    863       return typer_->int8_array_fun_;
    864     } else if (*value == native->int16_array_fun()) {
    865       return typer_->int16_array_fun_;
    866     } else if (*value == native->int32_array_fun()) {
    867       return typer_->int32_array_fun_;
    868     } else if (*value == native->uint8_array_fun()) {
    869       return typer_->uint8_array_fun_;
    870     } else if (*value == native->uint16_array_fun()) {
    871       return typer_->uint16_array_fun_;
    872     } else if (*value == native->uint32_array_fun()) {
    873       return typer_->uint32_array_fun_;
    874     } else if (*value == native->float32_array_fun()) {
    875       return typer_->float32_array_fun_;
    876     } else if (*value == native->float64_array_fun()) {
    877       return typer_->float64_array_fun_;
    878     }
    879   }
    880   return Type::Constant(value, zone());
    881 }
    882 
    883 
    884 namespace {
    885 
    886 class TyperDecorator : public GraphDecorator {
    887  public:
    888   explicit TyperDecorator(Typer* typer) : typer_(typer) {}
    889   virtual void Decorate(Node* node) { typer_->Init(node); }
    890 
    891  private:
    892   Typer* typer_;
    893 };
    894 
    895 }
    896 
    897 
    898 void Typer::DecorateGraph(Graph* graph) {
    899   graph->AddDecorator(new (zone()) TyperDecorator(this));
    900 }
    901 
    902 }
    903 }
    904 }  // namespace v8::internal::compiler
    905