• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "typing.h"
29 
30 #include "parser.h"  // for CompileTimeValue; TODO(rossberg): should move
31 #include "scopes.h"
32 
33 namespace v8 {
34 namespace internal {
35 
36 
AstTyper(CompilationInfo * info)37 AstTyper::AstTyper(CompilationInfo* info)
38     : info_(info),
39       oracle_(
40           Handle<Code>(info->closure()->shared()->code()),
41           Handle<Context>(info->closure()->context()->native_context()),
42           info->isolate(),
43           info->zone()),
44       store_(info->zone()) {
45   InitializeAstVisitor(info->isolate());
46 }
47 
48 
49 #define RECURSE(call)                         \
50   do {                                        \
51     ASSERT(!visitor->HasStackOverflow());     \
52     call;                                     \
53     if (visitor->HasStackOverflow()) return;  \
54   } while (false)
55 
Run(CompilationInfo * info)56 void AstTyper::Run(CompilationInfo* info) {
57   AstTyper* visitor = new(info->zone()) AstTyper(info);
58   Scope* scope = info->scope();
59 
60   // Handle implicit declaration of the function name in named function
61   // expressions before other declarations.
62   if (scope->is_function_scope() && scope->function() != NULL) {
63     RECURSE(visitor->VisitVariableDeclaration(scope->function()));
64   }
65   RECURSE(visitor->VisitDeclarations(scope->declarations()));
66   RECURSE(visitor->VisitStatements(info->function()->body()));
67 }
68 
69 #undef RECURSE
70 
71 #define RECURSE(call)                \
72   do {                               \
73     ASSERT(!HasStackOverflow());     \
74     call;                            \
75     if (HasStackOverflow()) return;  \
76   } while (false)
77 
78 
VisitStatements(ZoneList<Statement * > * stmts)79 void AstTyper::VisitStatements(ZoneList<Statement*>* stmts) {
80   for (int i = 0; i < stmts->length(); ++i) {
81     Statement* stmt = stmts->at(i);
82     RECURSE(Visit(stmt));
83     if (stmt->IsJump()) break;
84   }
85 }
86 
87 
VisitBlock(Block * stmt)88 void AstTyper::VisitBlock(Block* stmt) {
89   RECURSE(VisitStatements(stmt->statements()));
90   if (stmt->labels() != NULL) {
91     store_.Forget();  // Control may transfer here via 'break l'.
92   }
93 }
94 
95 
VisitExpressionStatement(ExpressionStatement * stmt)96 void AstTyper::VisitExpressionStatement(ExpressionStatement* stmt) {
97   RECURSE(Visit(stmt->expression()));
98 }
99 
100 
VisitEmptyStatement(EmptyStatement * stmt)101 void AstTyper::VisitEmptyStatement(EmptyStatement* stmt) {
102 }
103 
104 
VisitIfStatement(IfStatement * stmt)105 void AstTyper::VisitIfStatement(IfStatement* stmt) {
106   // Collect type feedback.
107   if (!stmt->condition()->ToBooleanIsTrue() &&
108       !stmt->condition()->ToBooleanIsFalse()) {
109     stmt->condition()->RecordToBooleanTypeFeedback(oracle());
110   }
111 
112   RECURSE(Visit(stmt->condition()));
113   Effects then_effects = EnterEffects();
114   RECURSE(Visit(stmt->then_statement()));
115   ExitEffects();
116   Effects else_effects = EnterEffects();
117   RECURSE(Visit(stmt->else_statement()));
118   ExitEffects();
119   then_effects.Alt(else_effects);
120   store_.Seq(then_effects);
121 }
122 
123 
VisitContinueStatement(ContinueStatement * stmt)124 void AstTyper::VisitContinueStatement(ContinueStatement* stmt) {
125   // TODO(rossberg): is it worth having a non-termination effect?
126 }
127 
128 
VisitBreakStatement(BreakStatement * stmt)129 void AstTyper::VisitBreakStatement(BreakStatement* stmt) {
130   // TODO(rossberg): is it worth having a non-termination effect?
131 }
132 
133 
VisitReturnStatement(ReturnStatement * stmt)134 void AstTyper::VisitReturnStatement(ReturnStatement* stmt) {
135   // Collect type feedback.
136   // TODO(rossberg): we only need this for inlining into test contexts...
137   stmt->expression()->RecordToBooleanTypeFeedback(oracle());
138 
139   RECURSE(Visit(stmt->expression()));
140   // TODO(rossberg): is it worth having a non-termination effect?
141 }
142 
143 
VisitWithStatement(WithStatement * stmt)144 void AstTyper::VisitWithStatement(WithStatement* stmt) {
145   RECURSE(stmt->expression());
146   RECURSE(stmt->statement());
147 }
148 
149 
VisitSwitchStatement(SwitchStatement * stmt)150 void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) {
151   RECURSE(Visit(stmt->tag()));
152 
153   ZoneList<CaseClause*>* clauses = stmt->cases();
154   SwitchStatement::SwitchType switch_type = stmt->switch_type();
155   Effects local_effects(zone());
156   bool complex_effects = false;  // True for label effects or fall-through.
157 
158   for (int i = 0; i < clauses->length(); ++i) {
159     CaseClause* clause = clauses->at(i);
160     Effects clause_effects = EnterEffects();
161 
162     if (!clause->is_default()) {
163       Expression* label = clause->label();
164       SwitchStatement::SwitchType label_switch_type =
165           label->IsSmiLiteral() ? SwitchStatement::SMI_SWITCH :
166           label->IsStringLiteral() ? SwitchStatement::STRING_SWITCH :
167               SwitchStatement::GENERIC_SWITCH;
168       if (switch_type == SwitchStatement::UNKNOWN_SWITCH)
169         switch_type = label_switch_type;
170       else if (switch_type != label_switch_type)
171         switch_type = SwitchStatement::GENERIC_SWITCH;
172 
173       RECURSE(Visit(label));
174       if (!clause_effects.IsEmpty()) complex_effects = true;
175     }
176 
177     ZoneList<Statement*>* stmts = clause->statements();
178     RECURSE(VisitStatements(stmts));
179     ExitEffects();
180     if (stmts->is_empty() || stmts->last()->IsJump()) {
181       local_effects.Alt(clause_effects);
182     } else {
183       complex_effects = true;
184     }
185   }
186 
187   if (complex_effects) {
188     store_.Forget();  // Reached this in unknown state.
189   } else {
190     store_.Seq(local_effects);
191   }
192 
193   if (switch_type == SwitchStatement::UNKNOWN_SWITCH)
194     switch_type = SwitchStatement::GENERIC_SWITCH;
195   stmt->set_switch_type(switch_type);
196 
197   // Collect type feedback.
198   // TODO(rossberg): can we eliminate this special case and extra loop?
199   if (switch_type == SwitchStatement::SMI_SWITCH) {
200     for (int i = 0; i < clauses->length(); ++i) {
201       CaseClause* clause = clauses->at(i);
202       if (!clause->is_default())
203         clause->set_compare_type(oracle()->ClauseType(clause->CompareId()));
204     }
205   }
206 }
207 
208 
VisitCaseClause(CaseClause * clause)209 void AstTyper::VisitCaseClause(CaseClause* clause) {
210   UNREACHABLE();
211 }
212 
213 
VisitDoWhileStatement(DoWhileStatement * stmt)214 void AstTyper::VisitDoWhileStatement(DoWhileStatement* stmt) {
215   // Collect type feedback.
216   if (!stmt->cond()->ToBooleanIsTrue()) {
217     stmt->cond()->RecordToBooleanTypeFeedback(oracle());
218   }
219 
220   // TODO(rossberg): refine the unconditional Forget (here and elsewhere) by
221   // computing the set of variables assigned in only some of the origins of the
222   // control transfer (such as the loop body here).
223   store_.Forget();  // Control may transfer here via looping or 'continue'.
224   RECURSE(Visit(stmt->body()));
225   RECURSE(Visit(stmt->cond()));
226   store_.Forget();  // Control may transfer here via 'break'.
227 }
228 
229 
VisitWhileStatement(WhileStatement * stmt)230 void AstTyper::VisitWhileStatement(WhileStatement* stmt) {
231   // Collect type feedback.
232   if (!stmt->cond()->ToBooleanIsTrue()) {
233     stmt->cond()->RecordToBooleanTypeFeedback(oracle());
234   }
235 
236   store_.Forget();  // Control may transfer here via looping or 'continue'.
237   RECURSE(Visit(stmt->cond()));
238   RECURSE(Visit(stmt->body()));
239   store_.Forget();  // Control may transfer here via termination or 'break'.
240 }
241 
242 
VisitForStatement(ForStatement * stmt)243 void AstTyper::VisitForStatement(ForStatement* stmt) {
244   if (stmt->init() != NULL) {
245     RECURSE(Visit(stmt->init()));
246   }
247   store_.Forget();  // Control may transfer here via looping.
248   if (stmt->cond() != NULL) {
249     // Collect type feedback.
250     stmt->cond()->RecordToBooleanTypeFeedback(oracle());
251 
252     RECURSE(Visit(stmt->cond()));
253   }
254   RECURSE(Visit(stmt->body()));
255   if (stmt->next() != NULL) {
256     store_.Forget();  // Control may transfer here via 'continue'.
257     RECURSE(Visit(stmt->next()));
258   }
259   store_.Forget();  // Control may transfer here via termination or 'break'.
260 }
261 
262 
VisitForInStatement(ForInStatement * stmt)263 void AstTyper::VisitForInStatement(ForInStatement* stmt) {
264   // Collect type feedback.
265   stmt->set_for_in_type(static_cast<ForInStatement::ForInType>(
266       oracle()->ForInType(stmt->ForInFeedbackId())));
267 
268   RECURSE(Visit(stmt->enumerable()));
269   store_.Forget();  // Control may transfer here via looping or 'continue'.
270   RECURSE(Visit(stmt->body()));
271   store_.Forget();  // Control may transfer here via 'break'.
272 }
273 
274 
VisitForOfStatement(ForOfStatement * stmt)275 void AstTyper::VisitForOfStatement(ForOfStatement* stmt) {
276   RECURSE(Visit(stmt->iterable()));
277   store_.Forget();  // Control may transfer here via looping or 'continue'.
278   RECURSE(Visit(stmt->body()));
279   store_.Forget();  // Control may transfer here via 'break'.
280 }
281 
282 
VisitTryCatchStatement(TryCatchStatement * stmt)283 void AstTyper::VisitTryCatchStatement(TryCatchStatement* stmt) {
284   Effects try_effects = EnterEffects();
285   RECURSE(Visit(stmt->try_block()));
286   ExitEffects();
287   Effects catch_effects = EnterEffects();
288   store_.Forget();  // Control may transfer here via 'throw'.
289   RECURSE(Visit(stmt->catch_block()));
290   ExitEffects();
291   try_effects.Alt(catch_effects);
292   store_.Seq(try_effects);
293   // At this point, only variables that were reassigned in the catch block are
294   // still remembered.
295 }
296 
297 
VisitTryFinallyStatement(TryFinallyStatement * stmt)298 void AstTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
299   RECURSE(Visit(stmt->try_block()));
300   store_.Forget();  // Control may transfer here via 'throw'.
301   RECURSE(Visit(stmt->finally_block()));
302 }
303 
304 
VisitDebuggerStatement(DebuggerStatement * stmt)305 void AstTyper::VisitDebuggerStatement(DebuggerStatement* stmt) {
306   store_.Forget();  // May do whatever.
307 }
308 
309 
VisitFunctionLiteral(FunctionLiteral * expr)310 void AstTyper::VisitFunctionLiteral(FunctionLiteral* expr) {
311 }
312 
313 
VisitNativeFunctionLiteral(NativeFunctionLiteral * expr)314 void AstTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
315 }
316 
317 
VisitConditional(Conditional * expr)318 void AstTyper::VisitConditional(Conditional* expr) {
319   // Collect type feedback.
320   expr->condition()->RecordToBooleanTypeFeedback(oracle());
321 
322   RECURSE(Visit(expr->condition()));
323   Effects then_effects = EnterEffects();
324   RECURSE(Visit(expr->then_expression()));
325   ExitEffects();
326   Effects else_effects = EnterEffects();
327   RECURSE(Visit(expr->else_expression()));
328   ExitEffects();
329   then_effects.Alt(else_effects);
330   store_.Seq(then_effects);
331 
332   NarrowType(expr, Bounds::Either(
333       expr->then_expression()->bounds(),
334       expr->else_expression()->bounds(), isolate_));
335 }
336 
337 
VisitVariableProxy(VariableProxy * expr)338 void AstTyper::VisitVariableProxy(VariableProxy* expr) {
339   Variable* var = expr->var();
340   if (var->IsStackAllocated()) {
341     NarrowType(expr, store_.LookupBounds(variable_index(var)));
342   }
343 }
344 
345 
VisitLiteral(Literal * expr)346 void AstTyper::VisitLiteral(Literal* expr) {
347   Type* type = Type::Constant(expr->value(), isolate_);
348   NarrowType(expr, Bounds(type, isolate_));
349 }
350 
351 
VisitRegExpLiteral(RegExpLiteral * expr)352 void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) {
353   NarrowType(expr, Bounds(Type::RegExp(), isolate_));
354 }
355 
356 
VisitObjectLiteral(ObjectLiteral * expr)357 void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) {
358   ZoneList<ObjectLiteral::Property*>* properties = expr->properties();
359   for (int i = 0; i < properties->length(); ++i) {
360     ObjectLiteral::Property* prop = properties->at(i);
361 
362     // Collect type feedback.
363     if ((prop->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL &&
364         !CompileTimeValue::IsCompileTimeValue(prop->value())) ||
365         prop->kind() == ObjectLiteral::Property::COMPUTED) {
366       if (prop->key()->value()->IsInternalizedString() && prop->emit_store()) {
367         prop->RecordTypeFeedback(oracle());
368       }
369     }
370 
371     RECURSE(Visit(prop->value()));
372   }
373 
374   NarrowType(expr, Bounds(Type::Object(), isolate_));
375 }
376 
377 
VisitArrayLiteral(ArrayLiteral * expr)378 void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) {
379   ZoneList<Expression*>* values = expr->values();
380   for (int i = 0; i < values->length(); ++i) {
381     Expression* value = values->at(i);
382     RECURSE(Visit(value));
383   }
384 
385   NarrowType(expr, Bounds(Type::Array(), isolate_));
386 }
387 
388 
VisitAssignment(Assignment * expr)389 void AstTyper::VisitAssignment(Assignment* expr) {
390   // Collect type feedback.
391   Property* prop = expr->target()->AsProperty();
392   if (prop != NULL) {
393     TypeFeedbackId id = expr->AssignmentFeedbackId();
394     expr->set_is_uninitialized(oracle()->StoreIsUninitialized(id));
395     if (!expr->IsUninitialized()) {
396       expr->set_is_pre_monomorphic(oracle()->StoreIsPreMonomorphic(id));
397       if (prop->key()->IsPropertyName()) {
398         Literal* lit_key = prop->key()->AsLiteral();
399         ASSERT(lit_key != NULL && lit_key->value()->IsString());
400         Handle<String> name = Handle<String>::cast(lit_key->value());
401         oracle()->AssignmentReceiverTypes(id, name, expr->GetReceiverTypes());
402       } else {
403         KeyedAccessStoreMode store_mode;
404         oracle()->KeyedAssignmentReceiverTypes(
405             id, expr->GetReceiverTypes(), &store_mode);
406         expr->set_store_mode(store_mode);
407       }
408       ASSERT(!expr->IsPreMonomorphic() || !expr->IsMonomorphic());
409     }
410   }
411 
412   Expression* rhs =
413       expr->is_compound() ? expr->binary_operation() : expr->value();
414   RECURSE(Visit(expr->target()));
415   RECURSE(Visit(rhs));
416   NarrowType(expr, rhs->bounds());
417 
418   VariableProxy* proxy = expr->target()->AsVariableProxy();
419   if (proxy != NULL && proxy->var()->IsStackAllocated()) {
420     store_.Seq(variable_index(proxy->var()), Effect(expr->bounds()));
421   }
422 }
423 
424 
VisitYield(Yield * expr)425 void AstTyper::VisitYield(Yield* expr) {
426   RECURSE(Visit(expr->generator_object()));
427   RECURSE(Visit(expr->expression()));
428 
429   // We don't know anything about the result type.
430 }
431 
432 
VisitThrow(Throw * expr)433 void AstTyper::VisitThrow(Throw* expr) {
434   RECURSE(Visit(expr->exception()));
435   // TODO(rossberg): is it worth having a non-termination effect?
436 
437   NarrowType(expr, Bounds(Type::None(), isolate_));
438 }
439 
440 
VisitProperty(Property * expr)441 void AstTyper::VisitProperty(Property* expr) {
442   // Collect type feedback.
443   TypeFeedbackId id = expr->PropertyFeedbackId();
444   expr->set_is_uninitialized(oracle()->LoadIsUninitialized(id));
445   if (!expr->IsUninitialized()) {
446     expr->set_is_pre_monomorphic(oracle()->LoadIsPreMonomorphic(id));
447     if (expr->key()->IsPropertyName()) {
448       Literal* lit_key = expr->key()->AsLiteral();
449       ASSERT(lit_key != NULL && lit_key->value()->IsString());
450       Handle<String> name = Handle<String>::cast(lit_key->value());
451       bool is_prototype;
452       oracle()->PropertyReceiverTypes(
453           id, name, expr->GetReceiverTypes(), &is_prototype);
454       expr->set_is_function_prototype(is_prototype);
455     } else {
456       bool is_string;
457       oracle()->KeyedPropertyReceiverTypes(
458           id, expr->GetReceiverTypes(), &is_string);
459       expr->set_is_string_access(is_string);
460     }
461     ASSERT(!expr->IsPreMonomorphic() || !expr->IsMonomorphic());
462   }
463 
464   RECURSE(Visit(expr->obj()));
465   RECURSE(Visit(expr->key()));
466 
467   // We don't know anything about the result type.
468 }
469 
470 
VisitCall(Call * expr)471 void AstTyper::VisitCall(Call* expr) {
472   // Collect type feedback.
473   Expression* callee = expr->expression();
474   Property* prop = callee->AsProperty();
475   if (prop != NULL) {
476     expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD);
477   } else {
478     expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION);
479   }
480 
481   RECURSE(Visit(expr->expression()));
482   ZoneList<Expression*>* args = expr->arguments();
483   for (int i = 0; i < args->length(); ++i) {
484     Expression* arg = args->at(i);
485     RECURSE(Visit(arg));
486   }
487 
488   VariableProxy* proxy = expr->expression()->AsVariableProxy();
489   if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
490     store_.Forget();  // Eval could do whatever to local variables.
491   }
492 
493   // We don't know anything about the result type.
494 }
495 
496 
VisitCallNew(CallNew * expr)497 void AstTyper::VisitCallNew(CallNew* expr) {
498   // Collect type feedback.
499   expr->RecordTypeFeedback(oracle());
500 
501   RECURSE(Visit(expr->expression()));
502   ZoneList<Expression*>* args = expr->arguments();
503   for (int i = 0; i < args->length(); ++i) {
504     Expression* arg = args->at(i);
505     RECURSE(Visit(arg));
506   }
507 
508   // We don't know anything about the result type.
509 }
510 
511 
VisitCallRuntime(CallRuntime * expr)512 void AstTyper::VisitCallRuntime(CallRuntime* expr) {
513   ZoneList<Expression*>* args = expr->arguments();
514   for (int i = 0; i < args->length(); ++i) {
515     Expression* arg = args->at(i);
516     RECURSE(Visit(arg));
517   }
518 
519   // We don't know anything about the result type.
520 }
521 
522 
VisitUnaryOperation(UnaryOperation * expr)523 void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
524   // Collect type feedback.
525   if (expr->op() == Token::NOT) {
526     // TODO(rossberg): only do in test or value context.
527     expr->expression()->RecordToBooleanTypeFeedback(oracle());
528   }
529 
530   RECURSE(Visit(expr->expression()));
531 
532   switch (expr->op()) {
533     case Token::NOT:
534     case Token::DELETE:
535       NarrowType(expr, Bounds(Type::Boolean(), isolate_));
536       break;
537     case Token::VOID:
538       NarrowType(expr, Bounds(Type::Undefined(), isolate_));
539       break;
540     case Token::TYPEOF:
541       NarrowType(expr, Bounds(Type::InternalizedString(), isolate_));
542       break;
543     default:
544       UNREACHABLE();
545   }
546 }
547 
548 
VisitCountOperation(CountOperation * expr)549 void AstTyper::VisitCountOperation(CountOperation* expr) {
550   // Collect type feedback.
551   TypeFeedbackId store_id = expr->CountStoreFeedbackId();
552   expr->set_store_mode(oracle()->GetStoreMode(store_id));
553   oracle()->CountReceiverTypes(store_id, expr->GetReceiverTypes());
554   expr->set_type(oracle()->CountType(expr->CountBinOpFeedbackId()));
555   // TODO(rossberg): merge the count type with the generic expression type.
556 
557   RECURSE(Visit(expr->expression()));
558 
559   NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
560 
561   VariableProxy* proxy = expr->expression()->AsVariableProxy();
562   if (proxy != NULL && proxy->var()->IsStackAllocated()) {
563     store_.Seq(variable_index(proxy->var()), Effect(expr->bounds()));
564   }
565 }
566 
567 
VisitBinaryOperation(BinaryOperation * expr)568 void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
569   // Collect type feedback.
570   Handle<Type> type, left_type, right_type;
571   Maybe<int> fixed_right_arg;
572   oracle()->BinaryType(expr->BinaryOperationFeedbackId(),
573       &left_type, &right_type, &type, &fixed_right_arg, expr->op());
574   NarrowLowerType(expr, type);
575   NarrowLowerType(expr->left(), left_type);
576   NarrowLowerType(expr->right(), right_type);
577   expr->set_fixed_right_arg(fixed_right_arg);
578   if (expr->op() == Token::OR || expr->op() == Token::AND) {
579     expr->left()->RecordToBooleanTypeFeedback(oracle());
580   }
581 
582   switch (expr->op()) {
583     case Token::COMMA:
584       RECURSE(Visit(expr->left()));
585       RECURSE(Visit(expr->right()));
586       NarrowType(expr, expr->right()->bounds());
587       break;
588     case Token::OR:
589     case Token::AND: {
590       Effects left_effects = EnterEffects();
591       RECURSE(Visit(expr->left()));
592       ExitEffects();
593       Effects right_effects = EnterEffects();
594       RECURSE(Visit(expr->right()));
595       ExitEffects();
596       left_effects.Alt(right_effects);
597       store_.Seq(left_effects);
598 
599       NarrowType(expr, Bounds::Either(
600           expr->left()->bounds(), expr->right()->bounds(), isolate_));
601       break;
602     }
603     case Token::BIT_OR:
604     case Token::BIT_AND: {
605       RECURSE(Visit(expr->left()));
606       RECURSE(Visit(expr->right()));
607       Handle<Type> upper(
608           Type::Union(
609               expr->left()->bounds().upper, expr->right()->bounds().upper),
610           isolate_);
611       if (!upper->Is(Type::Signed32()))
612         upper = handle(Type::Signed32(), isolate_);
613       Handle<Type> lower(Type::Intersect(
614           handle(Type::Smi(), isolate_), upper), isolate_);
615       NarrowType(expr, Bounds(lower, upper));
616       break;
617     }
618     case Token::BIT_XOR:
619     case Token::SHL:
620     case Token::SAR:
621       RECURSE(Visit(expr->left()));
622       RECURSE(Visit(expr->right()));
623       NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_));
624       break;
625     case Token::SHR:
626       RECURSE(Visit(expr->left()));
627       RECURSE(Visit(expr->right()));
628       // TODO(rossberg): The upper bound would be Unsigned32, but since there
629       // is no 'positive Smi' type for the lower bound, we use the smallest
630       // union of Smi and Unsigned32 as upper bound instead.
631       NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
632       break;
633     case Token::ADD: {
634       RECURSE(Visit(expr->left()));
635       RECURSE(Visit(expr->right()));
636       Bounds l = expr->left()->bounds();
637       Bounds r = expr->right()->bounds();
638       Type* lower =
639           l.lower->Is(Type::None()) || r.lower->Is(Type::None()) ?
640               Type::None() :
641           l.lower->Is(Type::String()) || r.lower->Is(Type::String()) ?
642               Type::String() :
643           l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) ?
644               Type::Smi() : Type::None();
645       Type* upper =
646           l.upper->Is(Type::String()) || r.upper->Is(Type::String()) ?
647               Type::String() :
648           l.upper->Is(Type::Number()) && r.upper->Is(Type::Number()) ?
649               Type::Number() : Type::NumberOrString();
650       NarrowType(expr, Bounds(lower, upper, isolate_));
651       break;
652     }
653     case Token::SUB:
654     case Token::MUL:
655     case Token::DIV:
656     case Token::MOD:
657       RECURSE(Visit(expr->left()));
658       RECURSE(Visit(expr->right()));
659       NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
660       break;
661     default:
662       UNREACHABLE();
663   }
664 }
665 
666 
VisitCompareOperation(CompareOperation * expr)667 void AstTyper::VisitCompareOperation(CompareOperation* expr) {
668   // Collect type feedback.
669   Handle<Type> left_type, right_type, combined_type;
670   oracle()->CompareType(expr->CompareOperationFeedbackId(),
671       &left_type, &right_type, &combined_type);
672   NarrowLowerType(expr->left(), left_type);
673   NarrowLowerType(expr->right(), right_type);
674   expr->set_combined_type(combined_type);
675 
676   RECURSE(Visit(expr->left()));
677   RECURSE(Visit(expr->right()));
678 
679   NarrowType(expr, Bounds(Type::Boolean(), isolate_));
680 }
681 
682 
VisitThisFunction(ThisFunction * expr)683 void AstTyper::VisitThisFunction(ThisFunction* expr) {
684 }
685 
686 
VisitDeclarations(ZoneList<Declaration * > * decls)687 void AstTyper::VisitDeclarations(ZoneList<Declaration*>* decls) {
688   for (int i = 0; i < decls->length(); ++i) {
689     Declaration* decl = decls->at(i);
690     RECURSE(Visit(decl));
691   }
692 }
693 
694 
VisitVariableDeclaration(VariableDeclaration * declaration)695 void AstTyper::VisitVariableDeclaration(VariableDeclaration* declaration) {
696 }
697 
698 
VisitFunctionDeclaration(FunctionDeclaration * declaration)699 void AstTyper::VisitFunctionDeclaration(FunctionDeclaration* declaration) {
700   RECURSE(Visit(declaration->fun()));
701 }
702 
703 
VisitModuleDeclaration(ModuleDeclaration * declaration)704 void AstTyper::VisitModuleDeclaration(ModuleDeclaration* declaration) {
705   RECURSE(Visit(declaration->module()));
706 }
707 
708 
VisitImportDeclaration(ImportDeclaration * declaration)709 void AstTyper::VisitImportDeclaration(ImportDeclaration* declaration) {
710   RECURSE(Visit(declaration->module()));
711 }
712 
713 
VisitExportDeclaration(ExportDeclaration * declaration)714 void AstTyper::VisitExportDeclaration(ExportDeclaration* declaration) {
715 }
716 
717 
VisitModuleLiteral(ModuleLiteral * module)718 void AstTyper::VisitModuleLiteral(ModuleLiteral* module) {
719   RECURSE(Visit(module->body()));
720 }
721 
722 
VisitModuleVariable(ModuleVariable * module)723 void AstTyper::VisitModuleVariable(ModuleVariable* module) {
724 }
725 
726 
VisitModulePath(ModulePath * module)727 void AstTyper::VisitModulePath(ModulePath* module) {
728   RECURSE(Visit(module->module()));
729 }
730 
731 
VisitModuleUrl(ModuleUrl * module)732 void AstTyper::VisitModuleUrl(ModuleUrl* module) {
733 }
734 
735 
VisitModuleStatement(ModuleStatement * stmt)736 void AstTyper::VisitModuleStatement(ModuleStatement* stmt) {
737   RECURSE(Visit(stmt->body()));
738 }
739 
740 
741 } }  // namespace v8::internal
742