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.
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"
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);
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);
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);
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);
65 class Typer::Visitor : public NullNodeVisitor {
67 Visitor(Typer* typer, MaybeHandle<Context> context)
68 : typer_(typer), context_(context) {}
70 Bounds TypeNode(Node* node) {
71 switch (node->opcode()) {
72 #define DECLARE_CASE(x) case IrOpcode::k##x: return Type##x(node);
74 VALUE_OP_LIST(DECLARE_CASE)
77 #define DECLARE_CASE(x) case IrOpcode::k##x:
79 INNER_CONTROL_OP_LIST(DECLARE_CASE)
87 Type* TypeConstant(Handle<Object> value);
90 #define DECLARE_METHOD(x) inline Bounds Type##x(Node* node);
92 VALUE_OP_LIST(DECLARE_METHOD)
95 Bounds OperandType(Node* node, int i) {
96 return NodeProperties::GetBounds(NodeProperties::GetValueInput(node, i));
99 Type* ContextType(Node* node) {
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.
108 Zone* zone() { return typer_->zone(); }
109 Isolate* isolate() { return typer_->isolate(); }
110 MaybeHandle<Context> context() { return context_; }
114 MaybeHandle<Context> context_;
118 class Typer::RunVisitor : public Typer::Visitor {
120 RunVisitor(Typer* typer, MaybeHandle<Context> context)
121 : Visitor(typer, context),
122 redo(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {}
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())) {
139 return GenericGraphVisit::CONTINUE;
146 class Typer::NarrowVisitor : public Typer::Visitor {
148 NarrowVisitor(Typer* typer, MaybeHandle<Context> context)
149 : Visitor(typer, context) {}
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;
161 return GenericGraphVisit::SKIP;
165 GenericGraphVisit::Control Post(Node* node) {
166 return GenericGraphVisit::REENTER;
171 class Typer::WidenVisitor : public Typer::Visitor {
173 WidenVisitor(Typer* typer, MaybeHandle<Context> context)
174 : Visitor(typer, context) {}
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;
187 return GenericGraphVisit::SKIP;
191 GenericGraphVisit::Control Post(Node* node) {
192 return GenericGraphVisit::REENTER;
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);
207 void Typer::Narrow(Graph* graph, Node* start, MaybeHandle<Context> context) {
208 NarrowVisitor typing(this, context);
209 graph->VisitNodeUsesFrom(start, &typing);
213 void Typer::Widen(Graph* graph, Node* start, MaybeHandle<Context> context) {
214 WidenVisitor typing(this, context);
215 graph->VisitNodeUsesFrom(start, &typing);
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);
228 // -----------------------------------------------------------------------------
231 // Control operators.
233 Bounds Typer::Visitor::TypeStart(Node* node) {
234 return Bounds(Type::Internal(zone()));
240 Bounds Typer::Visitor::TypeParameter(Node* node) {
241 return Bounds::Unbounded(zone());
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()));
251 Bounds Typer::Visitor::TypeInt64Constant(Node* node) {
252 // TODO(titzer): only call Type::Of() if the type is not already known.
254 Type::Of(static_cast<double>(OpParameter<int64_t>(node)), zone()));
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()));
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()));
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()));
276 Bounds Typer::Visitor::TypeHeapConstant(Node* node) {
277 return Bounds(TypeConstant(OpParameter<Unique<Object> >(node).handle()));
281 Bounds Typer::Visitor::TypeExternalConstant(Node* node) {
282 return Bounds(Type::Internal(zone()));
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());
296 Bounds Typer::Visitor::TypeEffectPhi(Node* node) {
302 Bounds Typer::Visitor::TypeControlEffect(Node* node) {
308 Bounds Typer::Visitor::TypeValueEffect(Node* node) {
314 Bounds Typer::Visitor::TypeFinish(Node* node) {
315 return OperandType(node, 0);
319 Bounds Typer::Visitor::TypeFrameState(Node* node) {
320 // TODO(rossberg): Ideally FrameState wouldn't have a value output.
321 return Bounds(Type::Internal(zone()));
325 Bounds Typer::Visitor::TypeStateValues(Node* node) {
326 return Bounds(Type::Internal(zone()));
330 Bounds Typer::Visitor::TypeCall(Node* node) {
331 return Bounds::Unbounded(zone());
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());
341 // JS comparison operators.
343 #define DEFINE_METHOD(x) \
344 Bounds Typer::Visitor::Type##x(Node* node) { \
345 return Bounds(Type::Boolean(zone())); \
347 JS_COMPARE_BINOP_LIST(DEFINE_METHOD)
351 // JS bitwise operators.
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);
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);
373 Bounds Typer::Visitor::TypeJSBitwiseXor(Node* node) {
374 return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone()));
378 Bounds Typer::Visitor::TypeJSShiftLeft(Node* node) {
379 return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone()));
383 Bounds Typer::Visitor::TypeJSShiftRight(Node* node) {
384 return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone()));
388 Bounds Typer::Visitor::TypeJSShiftRightLogical(Node* node) {
389 return Bounds(Type::UnsignedSmall(zone()), Type::Unsigned32(zone()));
393 // JS arithmetic operators.
395 Bounds Typer::Visitor::TypeJSAdd(Node* node) {
396 Bounds left = OperandType(node, 0);
397 Bounds right = OperandType(node, 1);
399 left.lower->Is(Type::None()) || right.lower->Is(Type::None()) ?
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());
406 left.upper->Is(Type::None()) && right.upper->Is(Type::None()) ?
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);
416 Bounds Typer::Visitor::TypeJSSubtract(Node* node) {
417 return Bounds(Type::SignedSmall(zone()), Type::Number(zone()));
421 Bounds Typer::Visitor::TypeJSMultiply(Node* node) {
422 return Bounds(Type::SignedSmall(zone()), Type::Number(zone()));
426 Bounds Typer::Visitor::TypeJSDivide(Node* node) {
427 return Bounds(Type::SignedSmall(zone()), Type::Number(zone()));
431 Bounds Typer::Visitor::TypeJSModulus(Node* node) {
432 return Bounds(Type::SignedSmall(zone()), Type::Number(zone()));
436 // JS unary operators.
438 Bounds Typer::Visitor::TypeJSUnaryNot(Node* node) {
439 return Bounds(Type::Boolean(zone()));
443 Bounds Typer::Visitor::TypeJSTypeOf(Node* node) {
444 return Bounds(Type::InternalizedString(zone()));
448 // JS conversion operators.
450 Bounds Typer::Visitor::TypeJSToBoolean(Node* node) {
451 return Bounds(Type::Boolean(zone()));
455 Bounds Typer::Visitor::TypeJSToNumber(Node* node) {
456 return Bounds(Type::SignedSmall(zone()), Type::Number(zone()));
460 Bounds Typer::Visitor::TypeJSToString(Node* node) {
461 return Bounds(Type::None(zone()), Type::String(zone()));
465 Bounds Typer::Visitor::TypeJSToName(Node* node) {
466 return Bounds(Type::None(zone()), Type::Name(zone()));
470 Bounds Typer::Visitor::TypeJSToObject(Node* node) {
471 return Bounds(Type::None(zone()), Type::Receiver(zone()));
475 // JS object operators.
477 Bounds Typer::Visitor::TypeJSCreate(Node* node) {
478 return Bounds(Type::None(zone()), Type::Object(zone()));
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());
491 if (object.upper->IsArray() && name.upper->Is(Type::Integral32())) {
492 result.upper = Type::Union(
493 object.upper->AsArray()->Element(), Type::Undefined(zone()), zone());
499 Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) {
500 return Bounds::Unbounded(zone());
504 Bounds Typer::Visitor::TypeJSStoreProperty(Node* node) {
510 Bounds Typer::Visitor::TypeJSStoreNamed(Node* node) {
516 Bounds Typer::Visitor::TypeJSDeleteProperty(Node* node) {
517 return Bounds(Type::Boolean(zone()));
521 Bounds Typer::Visitor::TypeJSHasProperty(Node* node) {
522 return Bounds(Type::Boolean(zone()));
526 Bounds Typer::Visitor::TypeJSInstanceOf(Node* node) {
527 return Bounds(Type::Boolean(zone()));
531 // JS context operators.
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.
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());
545 // Walk context chain (as far as known), mirroring dynamic lookup.
546 // Since contexts are mutable, the information is only useful as a lower
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());
556 } else if (!context.is_null()) {
557 context = handle(context.ToHandleChecked()->previous(), isolate());
560 if (context.is_null()) {
561 return Bounds::Unbounded(zone());
563 Handle<Object> value =
564 handle(context.ToHandleChecked()->get(access.index()), isolate());
565 Type* lower = TypeConstant(value);
566 return Bounds(lower, Type::Any(zone()));
571 Bounds Typer::Visitor::TypeJSStoreContext(Node* node) {
577 Bounds Typer::Visitor::TypeJSCreateFunctionContext(Node* node) {
578 Type* outer = ContextType(node);
579 return Bounds(Type::Context(outer, zone()));
583 Bounds Typer::Visitor::TypeJSCreateCatchContext(Node* node) {
584 Type* outer = ContextType(node);
585 return Bounds(Type::Context(outer, zone()));
589 Bounds Typer::Visitor::TypeJSCreateWithContext(Node* node) {
590 Type* outer = ContextType(node);
591 return Bounds(Type::Context(outer, zone()));
595 Bounds Typer::Visitor::TypeJSCreateBlockContext(Node* node) {
596 Type* outer = ContextType(node);
597 return Bounds(Type::Context(outer, zone()));
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()));
608 Bounds Typer::Visitor::TypeJSCreateGlobalContext(Node* node) {
609 Type* outer = ContextType(node);
610 return Bounds(Type::Context(outer, zone()));
614 // JS other operators.
616 Bounds Typer::Visitor::TypeJSYield(Node* node) {
617 return Bounds::Unbounded(zone());
621 Bounds Typer::Visitor::TypeJSCallConstruct(Node* node) {
622 return Bounds(Type::None(zone()), Type::Receiver(zone()));
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);
636 Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) {
637 return Bounds::Unbounded(zone());
641 Bounds Typer::Visitor::TypeJSDebugger(Node* node) {
642 return Bounds::Unbounded(zone());
646 // Simplified operators.
648 Bounds Typer::Visitor::TypeBooleanNot(Node* node) {
649 return Bounds(Type::Boolean(zone()));
653 Bounds Typer::Visitor::TypeBooleanToNumber(Node* node) {
654 return Bounds(Type::Number(zone()));
658 Bounds Typer::Visitor::TypeNumberEqual(Node* node) {
659 return Bounds(Type::Boolean(zone()));
663 Bounds Typer::Visitor::TypeNumberLessThan(Node* node) {
664 return Bounds(Type::Boolean(zone()));
668 Bounds Typer::Visitor::TypeNumberLessThanOrEqual(Node* node) {
669 return Bounds(Type::Boolean(zone()));
673 Bounds Typer::Visitor::TypeNumberAdd(Node* node) {
674 return Bounds(Type::Number(zone()));
678 Bounds Typer::Visitor::TypeNumberSubtract(Node* node) {
679 return Bounds(Type::Number(zone()));
683 Bounds Typer::Visitor::TypeNumberMultiply(Node* node) {
684 return Bounds(Type::Number(zone()));
688 Bounds Typer::Visitor::TypeNumberDivide(Node* node) {
689 return Bounds(Type::Number(zone()));
693 Bounds Typer::Visitor::TypeNumberModulus(Node* node) {
694 return Bounds(Type::Number(zone()));
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);
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);
716 Bounds Typer::Visitor::TypeReferenceEqual(Node* node) {
717 return Bounds(Type::Boolean(zone()));
721 Bounds Typer::Visitor::TypeStringEqual(Node* node) {
722 return Bounds(Type::Boolean(zone()));
726 Bounds Typer::Visitor::TypeStringLessThan(Node* node) {
727 return Bounds(Type::Boolean(zone()));
731 Bounds Typer::Visitor::TypeStringLessThanOrEqual(Node* node) {
732 return Bounds(Type::Boolean(zone()));
736 Bounds Typer::Visitor::TypeStringAdd(Node* node) {
737 return Bounds(Type::String(zone()));
741 Bounds Typer::Visitor::TypeChangeTaggedToInt32(Node* node) {
742 // TODO(titzer): type is type of input, representation is Word32.
743 return Bounds(Type::Integral32());
747 Bounds Typer::Visitor::TypeChangeTaggedToUint32(Node* node) {
748 return Bounds(Type::Integral32()); // TODO(titzer): add appropriate rep
752 Bounds Typer::Visitor::TypeChangeTaggedToFloat64(Node* node) {
753 // TODO(titzer): type is type of input, representation is Float64.
754 return Bounds(Type::Number());
758 Bounds Typer::Visitor::TypeChangeInt32ToTagged(Node* node) {
759 // TODO(titzer): type is type of input, representation is Tagged.
760 return Bounds(Type::Integral32());
764 Bounds Typer::Visitor::TypeChangeUint32ToTagged(Node* node) {
765 // TODO(titzer): type is type of input, representation is Tagged.
766 return Bounds(Type::Unsigned32());
770 Bounds Typer::Visitor::TypeChangeFloat64ToTagged(Node* node) {
771 // TODO(titzer): type is type of input, representation is Tagged.
772 return Bounds(Type::Number());
776 Bounds Typer::Visitor::TypeChangeBoolToBit(Node* node) {
777 // TODO(titzer): type is type of input, representation is Bit.
778 return Bounds(Type::Boolean());
782 Bounds Typer::Visitor::TypeChangeBitToBool(Node* node) {
783 // TODO(titzer): type is type of input, representation is Tagged.
784 return Bounds(Type::Boolean());
788 Bounds Typer::Visitor::TypeLoadField(Node* node) {
789 return Bounds(FieldAccessOf(node->op()).type);
793 Bounds Typer::Visitor::TypeLoadElement(Node* node) {
794 return Bounds(ElementAccessOf(node->op()).type);
798 Bounds Typer::Visitor::TypeStoreField(Node* node) {
804 Bounds Typer::Visitor::TypeStoreElement(Node* node) {
810 // Machine operators.
812 // TODO(rossberg): implement
813 #define DEFINE_METHOD(x) \
814 Bounds Typer::Visitor::Type##x(Node* node) { return Bounds(Type::None()); }
815 MACHINE_OP_LIST(DEFINE_METHOD)
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_;
880 return Type::Constant(value, zone());
886 class TyperDecorator : public GraphDecorator {
888 explicit TyperDecorator(Typer* typer) : typer_(typer) {}
889 virtual void Decorate(Node* node) { typer_->Init(node); }
898 void Typer::DecorateGraph(Graph* graph) {
899 graph->AddDecorator(new (zone()) TyperDecorator(this));
904 } // namespace v8::internal::compiler