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