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