• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Typer(Zone * zone)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:
Visitor(Typer * typer,MaybeHandle<Context> context)67   Visitor(Typer* typer, MaybeHandle<Context> context)
68       : typer_(typer), context_(context) {}
69 
TypeNode(Node * node)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)
VALUE_OP_LIST(DECLARE_METHOD)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 
ContextType(Node * node)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 
zone()108   Zone* zone() { return typer_->zone(); }
isolate()109   Isolate* isolate() { return typer_->isolate(); }
context()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:
RunVisitor(Typer * typer,MaybeHandle<Context> context)120   RunVisitor(Typer* typer, MaybeHandle<Context> context)
121       : Visitor(typer, context),
122         redo(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {}
123 
Post(Node * node)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:
NarrowVisitor(Typer * typer,MaybeHandle<Context> context)148   NarrowVisitor(Typer* typer, MaybeHandle<Context> context)
149       : Visitor(typer, context) {}
150 
Pre(Node * node)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 
Post(Node * node)165   GenericGraphVisit::Control Post(Node* node) {
166     return GenericGraphVisit::REENTER;
167   }
168 };
169 
170 
171 class Typer::WidenVisitor : public Typer::Visitor {
172  public:
WidenVisitor(Typer * typer,MaybeHandle<Context> context)173   WidenVisitor(Typer* typer, MaybeHandle<Context> context)
174       : Visitor(typer, context) {}
175 
Pre(Node * node)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 
Post(Node * node)191   GenericGraphVisit::Control Post(Node* node) {
192     return GenericGraphVisit::REENTER;
193   }
194 };
195 
196 
Run(Graph * graph,MaybeHandle<Context> context)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 
Narrow(Graph * graph,Node * start,MaybeHandle<Context> context)207 void Typer::Narrow(Graph* graph, Node* start, MaybeHandle<Context> context) {
208   NarrowVisitor typing(this, context);
209   graph->VisitNodeUsesFrom(start, &typing);
210 }
211 
212 
Widen(Graph * graph,Node * start,MaybeHandle<Context> context)213 void Typer::Widen(Graph* graph, Node* start, MaybeHandle<Context> context) {
214   WidenVisitor typing(this, context);
215   graph->VisitNodeUsesFrom(start, &typing);
216 }
217 
218 
Init(Node * node)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 
TypeStart(Node * node)233 Bounds Typer::Visitor::TypeStart(Node* node) {
234   return Bounds(Type::Internal(zone()));
235 }
236 
237 
238 // Common operators.
239 
TypeParameter(Node * node)240 Bounds Typer::Visitor::TypeParameter(Node* node) {
241   return Bounds::Unbounded(zone());
242 }
243 
244 
TypeInt32Constant(Node * node)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 
TypeInt64Constant(Node * node)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 
TypeFloat32Constant(Node * node)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 
TypeFloat64Constant(Node * node)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 
TypeNumberConstant(Node * node)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 
TypeHeapConstant(Node * node)276 Bounds Typer::Visitor::TypeHeapConstant(Node* node) {
277   return Bounds(TypeConstant(OpParameter<Unique<Object> >(node).handle()));
278 }
279 
280 
TypeExternalConstant(Node * node)281 Bounds Typer::Visitor::TypeExternalConstant(Node* node) {
282   return Bounds(Type::Internal(zone()));
283 }
284 
285 
TypePhi(Node * node)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 
TypeEffectPhi(Node * node)296 Bounds Typer::Visitor::TypeEffectPhi(Node* node) {
297   UNREACHABLE();
298   return Bounds();
299 }
300 
301 
TypeControlEffect(Node * node)302 Bounds Typer::Visitor::TypeControlEffect(Node* node) {
303   UNREACHABLE();
304   return Bounds();
305 }
306 
307 
TypeValueEffect(Node * node)308 Bounds Typer::Visitor::TypeValueEffect(Node* node) {
309   UNREACHABLE();
310   return Bounds();
311 }
312 
313 
TypeFinish(Node * node)314 Bounds Typer::Visitor::TypeFinish(Node* node) {
315   return OperandType(node, 0);
316 }
317 
318 
TypeFrameState(Node * node)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 
TypeStateValues(Node * node)325 Bounds Typer::Visitor::TypeStateValues(Node* node) {
326   return Bounds(Type::Internal(zone()));
327 }
328 
329 
TypeCall(Node * node)330 Bounds Typer::Visitor::TypeCall(Node* node) {
331   return Bounds::Unbounded(zone());
332 }
333 
334 
TypeProjection(Node * node)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   }
JS_COMPARE_BINOP_LIST(DEFINE_METHOD)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 
TypeJSBitwiseAnd(Node * node)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 
TypeJSBitwiseXor(Node * node)373 Bounds Typer::Visitor::TypeJSBitwiseXor(Node* node) {
374   return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone()));
375 }
376 
377 
TypeJSShiftLeft(Node * node)378 Bounds Typer::Visitor::TypeJSShiftLeft(Node* node) {
379   return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone()));
380 }
381 
382 
TypeJSShiftRight(Node * node)383 Bounds Typer::Visitor::TypeJSShiftRight(Node* node) {
384   return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone()));
385 }
386 
387 
TypeJSShiftRightLogical(Node * node)388 Bounds Typer::Visitor::TypeJSShiftRightLogical(Node* node) {
389   return Bounds(Type::UnsignedSmall(zone()), Type::Unsigned32(zone()));
390 }
391 
392 
393 // JS arithmetic operators.
394 
TypeJSAdd(Node * node)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 
TypeJSSubtract(Node * node)416 Bounds Typer::Visitor::TypeJSSubtract(Node* node) {
417   return Bounds(Type::SignedSmall(zone()), Type::Number(zone()));
418 }
419 
420 
TypeJSMultiply(Node * node)421 Bounds Typer::Visitor::TypeJSMultiply(Node* node) {
422   return Bounds(Type::SignedSmall(zone()), Type::Number(zone()));
423 }
424 
425 
TypeJSDivide(Node * node)426 Bounds Typer::Visitor::TypeJSDivide(Node* node) {
427   return Bounds(Type::SignedSmall(zone()), Type::Number(zone()));
428 }
429 
430 
TypeJSModulus(Node * node)431 Bounds Typer::Visitor::TypeJSModulus(Node* node) {
432   return Bounds(Type::SignedSmall(zone()), Type::Number(zone()));
433 }
434 
435 
436 // JS unary operators.
437 
TypeJSUnaryNot(Node * node)438 Bounds Typer::Visitor::TypeJSUnaryNot(Node* node) {
439   return Bounds(Type::Boolean(zone()));
440 }
441 
442 
TypeJSTypeOf(Node * node)443 Bounds Typer::Visitor::TypeJSTypeOf(Node* node) {
444   return Bounds(Type::InternalizedString(zone()));
445 }
446 
447 
448 // JS conversion operators.
449 
TypeJSToBoolean(Node * node)450 Bounds Typer::Visitor::TypeJSToBoolean(Node* node) {
451   return Bounds(Type::Boolean(zone()));
452 }
453 
454 
TypeJSToNumber(Node * node)455 Bounds Typer::Visitor::TypeJSToNumber(Node* node) {
456   return Bounds(Type::SignedSmall(zone()), Type::Number(zone()));
457 }
458 
459 
TypeJSToString(Node * node)460 Bounds Typer::Visitor::TypeJSToString(Node* node) {
461   return Bounds(Type::None(zone()), Type::String(zone()));
462 }
463 
464 
TypeJSToName(Node * node)465 Bounds Typer::Visitor::TypeJSToName(Node* node) {
466   return Bounds(Type::None(zone()), Type::Name(zone()));
467 }
468 
469 
TypeJSToObject(Node * node)470 Bounds Typer::Visitor::TypeJSToObject(Node* node) {
471   return Bounds(Type::None(zone()), Type::Receiver(zone()));
472 }
473 
474 
475 // JS object operators.
476 
TypeJSCreate(Node * node)477 Bounds Typer::Visitor::TypeJSCreate(Node* node) {
478   return Bounds(Type::None(zone()), Type::Object(zone()));
479 }
480 
481 
TypeJSLoadProperty(Node * node)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 
TypeJSLoadNamed(Node * node)499 Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) {
500   return Bounds::Unbounded(zone());
501 }
502 
503 
TypeJSStoreProperty(Node * node)504 Bounds Typer::Visitor::TypeJSStoreProperty(Node* node) {
505   UNREACHABLE();
506   return Bounds();
507 }
508 
509 
TypeJSStoreNamed(Node * node)510 Bounds Typer::Visitor::TypeJSStoreNamed(Node* node) {
511   UNREACHABLE();
512   return Bounds();
513 }
514 
515 
TypeJSDeleteProperty(Node * node)516 Bounds Typer::Visitor::TypeJSDeleteProperty(Node* node) {
517   return Bounds(Type::Boolean(zone()));
518 }
519 
520 
TypeJSHasProperty(Node * node)521 Bounds Typer::Visitor::TypeJSHasProperty(Node* node) {
522   return Bounds(Type::Boolean(zone()));
523 }
524 
525 
TypeJSInstanceOf(Node * node)526 Bounds Typer::Visitor::TypeJSInstanceOf(Node* node) {
527   return Bounds(Type::Boolean(zone()));
528 }
529 
530 
531 // JS context operators.
532 
TypeJSLoadContext(Node * node)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 
TypeJSStoreContext(Node * node)571 Bounds Typer::Visitor::TypeJSStoreContext(Node* node) {
572   UNREACHABLE();
573   return Bounds();
574 }
575 
576 
TypeJSCreateFunctionContext(Node * node)577 Bounds Typer::Visitor::TypeJSCreateFunctionContext(Node* node) {
578   Type* outer = ContextType(node);
579   return Bounds(Type::Context(outer, zone()));
580 }
581 
582 
TypeJSCreateCatchContext(Node * node)583 Bounds Typer::Visitor::TypeJSCreateCatchContext(Node* node) {
584   Type* outer = ContextType(node);
585   return Bounds(Type::Context(outer, zone()));
586 }
587 
588 
TypeJSCreateWithContext(Node * node)589 Bounds Typer::Visitor::TypeJSCreateWithContext(Node* node) {
590   Type* outer = ContextType(node);
591   return Bounds(Type::Context(outer, zone()));
592 }
593 
594 
TypeJSCreateBlockContext(Node * node)595 Bounds Typer::Visitor::TypeJSCreateBlockContext(Node* node) {
596   Type* outer = ContextType(node);
597   return Bounds(Type::Context(outer, zone()));
598 }
599 
600 
TypeJSCreateModuleContext(Node * node)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 
TypeJSCreateGlobalContext(Node * node)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 
TypeJSYield(Node * node)616 Bounds Typer::Visitor::TypeJSYield(Node* node) {
617   return Bounds::Unbounded(zone());
618 }
619 
620 
TypeJSCallConstruct(Node * node)621 Bounds Typer::Visitor::TypeJSCallConstruct(Node* node) {
622   return Bounds(Type::None(zone()), Type::Receiver(zone()));
623 }
624 
625 
TypeJSCallFunction(Node * node)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 
TypeJSCallRuntime(Node * node)636 Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) {
637   return Bounds::Unbounded(zone());
638 }
639 
640 
TypeJSDebugger(Node * node)641 Bounds Typer::Visitor::TypeJSDebugger(Node* node) {
642   return Bounds::Unbounded(zone());
643 }
644 
645 
646 // Simplified operators.
647 
TypeBooleanNot(Node * node)648 Bounds Typer::Visitor::TypeBooleanNot(Node* node) {
649   return Bounds(Type::Boolean(zone()));
650 }
651 
652 
TypeBooleanToNumber(Node * node)653 Bounds Typer::Visitor::TypeBooleanToNumber(Node* node) {
654   return Bounds(Type::Number(zone()));
655 }
656 
657 
TypeNumberEqual(Node * node)658 Bounds Typer::Visitor::TypeNumberEqual(Node* node) {
659   return Bounds(Type::Boolean(zone()));
660 }
661 
662 
TypeNumberLessThan(Node * node)663 Bounds Typer::Visitor::TypeNumberLessThan(Node* node) {
664   return Bounds(Type::Boolean(zone()));
665 }
666 
667 
TypeNumberLessThanOrEqual(Node * node)668 Bounds Typer::Visitor::TypeNumberLessThanOrEqual(Node* node) {
669   return Bounds(Type::Boolean(zone()));
670 }
671 
672 
TypeNumberAdd(Node * node)673 Bounds Typer::Visitor::TypeNumberAdd(Node* node) {
674   return Bounds(Type::Number(zone()));
675 }
676 
677 
TypeNumberSubtract(Node * node)678 Bounds Typer::Visitor::TypeNumberSubtract(Node* node) {
679   return Bounds(Type::Number(zone()));
680 }
681 
682 
TypeNumberMultiply(Node * node)683 Bounds Typer::Visitor::TypeNumberMultiply(Node* node) {
684   return Bounds(Type::Number(zone()));
685 }
686 
687 
TypeNumberDivide(Node * node)688 Bounds Typer::Visitor::TypeNumberDivide(Node* node) {
689   return Bounds(Type::Number(zone()));
690 }
691 
692 
TypeNumberModulus(Node * node)693 Bounds Typer::Visitor::TypeNumberModulus(Node* node) {
694   return Bounds(Type::Number(zone()));
695 }
696 
697 
TypeNumberToInt32(Node * node)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 
TypeNumberToUint32(Node * node)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 
TypeReferenceEqual(Node * node)716 Bounds Typer::Visitor::TypeReferenceEqual(Node* node) {
717   return Bounds(Type::Boolean(zone()));
718 }
719 
720 
TypeStringEqual(Node * node)721 Bounds Typer::Visitor::TypeStringEqual(Node* node) {
722   return Bounds(Type::Boolean(zone()));
723 }
724 
725 
TypeStringLessThan(Node * node)726 Bounds Typer::Visitor::TypeStringLessThan(Node* node) {
727   return Bounds(Type::Boolean(zone()));
728 }
729 
730 
TypeStringLessThanOrEqual(Node * node)731 Bounds Typer::Visitor::TypeStringLessThanOrEqual(Node* node) {
732   return Bounds(Type::Boolean(zone()));
733 }
734 
735 
TypeStringAdd(Node * node)736 Bounds Typer::Visitor::TypeStringAdd(Node* node) {
737   return Bounds(Type::String(zone()));
738 }
739 
740 
TypeChangeTaggedToInt32(Node * node)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 
TypeChangeTaggedToUint32(Node * node)747 Bounds Typer::Visitor::TypeChangeTaggedToUint32(Node* node) {
748   return Bounds(Type::Integral32());  // TODO(titzer): add appropriate rep
749 }
750 
751 
TypeChangeTaggedToFloat64(Node * node)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 
TypeChangeInt32ToTagged(Node * node)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 
TypeChangeUint32ToTagged(Node * node)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 
TypeChangeFloat64ToTagged(Node * node)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 
TypeChangeBoolToBit(Node * node)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 
TypeChangeBitToBool(Node * node)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 
TypeLoadField(Node * node)788 Bounds Typer::Visitor::TypeLoadField(Node* node) {
789   return Bounds(FieldAccessOf(node->op()).type);
790 }
791 
792 
TypeLoadElement(Node * node)793 Bounds Typer::Visitor::TypeLoadElement(Node* node) {
794   return Bounds(ElementAccessOf(node->op()).type);
795 }
796 
797 
TypeStoreField(Node * node)798 Bounds Typer::Visitor::TypeStoreField(Node* node) {
799   UNREACHABLE();
800   return Bounds();
801 }
802 
803 
TypeStoreElement(Node * node)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()); }
MACHINE_OP_LIST(DEFINE_METHOD)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:
TyperDecorator(Typer * typer)888   explicit TyperDecorator(Typer* typer) : typer_(typer) {}
Decorate(Node * node)889   virtual void Decorate(Node* node) { typer_->Init(node); }
890 
891  private:
892   Typer* typer_;
893 };
894 
895 }
896 
897 
DecorateGraph(Graph * graph)898 void Typer::DecorateGraph(Graph* graph) {
899   graph->AddDecorator(new (zone()) TyperDecorator(this));
900 }
901 
902 }
903 }
904 }  // namespace v8::internal::compiler
905