Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: src/compiler/typer.cc

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

Powered by Google App Engine
This is Rietveld 408576698