| OLD | NEW | 
|---|
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. | 
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without | 
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are | 
| 4 // met: | 4 // met: | 
| 5 // | 5 // | 
| 6 //     * Redistributions of source code must retain the above copyright | 6 //     * Redistributions of source code must retain the above copyright | 
| 7 //       notice, this list of conditions and the following disclaimer. | 7 //       notice, this list of conditions and the following disclaimer. | 
| 8 //     * Redistributions in binary form must reproduce the above | 8 //     * Redistributions in binary form must reproduce the above | 
| 9 //       copyright notice, this list of conditions and the following | 9 //       copyright notice, this list of conditions and the following | 
| 10 //       disclaimer in the documentation and/or other materials provided | 10 //       disclaimer in the documentation and/or other materials provided | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
| 33 namespace v8 { | 33 namespace v8 { | 
| 34 namespace internal { | 34 namespace internal { | 
| 35 | 35 | 
| 36 | 36 | 
| 37 AstTyper::AstTyper(CompilationInfo* info) | 37 AstTyper::AstTyper(CompilationInfo* info) | 
| 38     : info_(info), | 38     : info_(info), | 
| 39       oracle_( | 39       oracle_( | 
| 40           Handle<Code>(info->closure()->shared()->code()), | 40           Handle<Code>(info->closure()->shared()->code()), | 
| 41           Handle<Context>(info->closure()->context()->native_context()), | 41           Handle<Context>(info->closure()->context()->native_context()), | 
| 42           info->isolate(), | 42           info->isolate(), | 
| 43           info->zone()) { | 43           info->zone()), | 
|  | 44       store_(info->zone()) { | 
| 44   InitializeAstVisitor(); | 45   InitializeAstVisitor(); | 
| 45 } | 46 } | 
| 46 | 47 | 
| 47 | 48 | 
| 48 #define RECURSE(call)                         \ | 49 #define RECURSE(call)                         \ | 
| 49   do {                                        \ | 50   do {                                        \ | 
| 50     ASSERT(!visitor->HasStackOverflow());     \ | 51     ASSERT(!visitor->HasStackOverflow());     \ | 
| 51     call;                                     \ | 52     call;                                     \ | 
| 52     if (visitor->HasStackOverflow()) return;  \ | 53     if (visitor->HasStackOverflow()) return;  \ | 
| 53   } while (false) | 54   } while (false) | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
| 78 void AstTyper::VisitStatements(ZoneList<Statement*>* stmts) { | 79 void AstTyper::VisitStatements(ZoneList<Statement*>* stmts) { | 
| 79   for (int i = 0; i < stmts->length(); ++i) { | 80   for (int i = 0; i < stmts->length(); ++i) { | 
| 80     Statement* stmt = stmts->at(i); | 81     Statement* stmt = stmts->at(i); | 
| 81     RECURSE(Visit(stmt)); | 82     RECURSE(Visit(stmt)); | 
| 82   } | 83   } | 
| 83 } | 84 } | 
| 84 | 85 | 
| 85 | 86 | 
| 86 void AstTyper::VisitBlock(Block* stmt) { | 87 void AstTyper::VisitBlock(Block* stmt) { | 
| 87   RECURSE(VisitStatements(stmt->statements())); | 88   RECURSE(VisitStatements(stmt->statements())); | 
|  | 89   if (stmt->labels() != NULL) { | 
|  | 90     store_.Forget();  // Control may transfer here via 'break l'. | 
|  | 91   } | 
| 88 } | 92 } | 
| 89 | 93 | 
| 90 | 94 | 
| 91 void AstTyper::VisitExpressionStatement(ExpressionStatement* stmt) { | 95 void AstTyper::VisitExpressionStatement(ExpressionStatement* stmt) { | 
| 92   RECURSE(Visit(stmt->expression())); | 96   RECURSE(Visit(stmt->expression())); | 
| 93 } | 97 } | 
| 94 | 98 | 
| 95 | 99 | 
| 96 void AstTyper::VisitEmptyStatement(EmptyStatement* stmt) { | 100 void AstTyper::VisitEmptyStatement(EmptyStatement* stmt) { | 
| 97 } | 101 } | 
| 98 | 102 | 
| 99 | 103 | 
| 100 void AstTyper::VisitIfStatement(IfStatement* stmt) { | 104 void AstTyper::VisitIfStatement(IfStatement* stmt) { | 
| 101   RECURSE(Visit(stmt->condition())); | 105   // Collect type feedback. | 
| 102   RECURSE(Visit(stmt->then_statement())); |  | 
| 103   RECURSE(Visit(stmt->else_statement())); |  | 
| 104 |  | 
| 105   if (!stmt->condition()->ToBooleanIsTrue() && | 106   if (!stmt->condition()->ToBooleanIsTrue() && | 
| 106       !stmt->condition()->ToBooleanIsFalse()) { | 107       !stmt->condition()->ToBooleanIsFalse()) { | 
| 107     stmt->condition()->RecordToBooleanTypeFeedback(oracle()); | 108     stmt->condition()->RecordToBooleanTypeFeedback(oracle()); | 
| 108   } | 109   } | 
|  | 110 | 
|  | 111   RECURSE(Visit(stmt->condition())); | 
|  | 112   Effects then_effects = EnterEffects(); | 
|  | 113   RECURSE(Visit(stmt->then_statement())); | 
|  | 114   ExitEffects(); | 
|  | 115   Effects else_effects = EnterEffects(); | 
|  | 116   RECURSE(Visit(stmt->else_statement())); | 
|  | 117   ExitEffects(); | 
|  | 118   then_effects.Alt(else_effects); | 
|  | 119   store_.Seq(then_effects); | 
| 109 } | 120 } | 
| 110 | 121 | 
| 111 | 122 | 
| 112 void AstTyper::VisitContinueStatement(ContinueStatement* stmt) { | 123 void AstTyper::VisitContinueStatement(ContinueStatement* stmt) { | 
|  | 124   // TODO(rossberg): is it worth having a non-termination effect? | 
| 113 } | 125 } | 
| 114 | 126 | 
| 115 | 127 | 
| 116 void AstTyper::VisitBreakStatement(BreakStatement* stmt) { | 128 void AstTyper::VisitBreakStatement(BreakStatement* stmt) { | 
|  | 129   // TODO(rossberg): is it worth having a non-termination effect? | 
| 117 } | 130 } | 
| 118 | 131 | 
| 119 | 132 | 
| 120 void AstTyper::VisitReturnStatement(ReturnStatement* stmt) { | 133 void AstTyper::VisitReturnStatement(ReturnStatement* stmt) { | 
| 121   RECURSE(Visit(stmt->expression())); | 134   // Collect type feedback. | 
| 122 |  | 
| 123   // TODO(rossberg): we only need this for inlining into test contexts... | 135   // TODO(rossberg): we only need this for inlining into test contexts... | 
| 124   stmt->expression()->RecordToBooleanTypeFeedback(oracle()); | 136   stmt->expression()->RecordToBooleanTypeFeedback(oracle()); | 
|  | 137 | 
|  | 138   RECURSE(Visit(stmt->expression())); | 
|  | 139   // TODO(rossberg): is it worth having a non-termination effect? | 
| 125 } | 140 } | 
| 126 | 141 | 
| 127 | 142 | 
| 128 void AstTyper::VisitWithStatement(WithStatement* stmt) { | 143 void AstTyper::VisitWithStatement(WithStatement* stmt) { | 
| 129   RECURSE(stmt->expression()); | 144   RECURSE(stmt->expression()); | 
| 130   RECURSE(stmt->statement()); | 145   RECURSE(stmt->statement()); | 
| 131 } | 146 } | 
| 132 | 147 | 
| 133 | 148 | 
| 134 void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) { | 149 void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) { | 
| 135   RECURSE(Visit(stmt->tag())); | 150   RECURSE(Visit(stmt->tag())); | 
|  | 151 | 
| 136   ZoneList<CaseClause*>* clauses = stmt->cases(); | 152   ZoneList<CaseClause*>* clauses = stmt->cases(); | 
| 137   SwitchStatement::SwitchType switch_type = stmt->switch_type(); | 153   SwitchStatement::SwitchType switch_type = stmt->switch_type(); | 
| 138   for (int i = 0; i < clauses->length(); ++i) { | 154   for (int i = 0; i < clauses->length(); ++i) { | 
| 139     CaseClause* clause = clauses->at(i); | 155     CaseClause* clause = clauses->at(i); | 
| 140     if (!clause->is_default()) { | 156     if (!clause->is_default()) { | 
| 141       Expression* label = clause->label(); | 157       Expression* label = clause->label(); | 
| 142       RECURSE(Visit(label)); |  | 
| 143 |  | 
| 144       SwitchStatement::SwitchType label_switch_type = | 158       SwitchStatement::SwitchType label_switch_type = | 
| 145           label->IsSmiLiteral() ? SwitchStatement::SMI_SWITCH : | 159           label->IsSmiLiteral() ? SwitchStatement::SMI_SWITCH : | 
| 146           label->IsStringLiteral() ? SwitchStatement::STRING_SWITCH : | 160           label->IsStringLiteral() ? SwitchStatement::STRING_SWITCH : | 
| 147               SwitchStatement::GENERIC_SWITCH; | 161               SwitchStatement::GENERIC_SWITCH; | 
| 148       if (switch_type == SwitchStatement::UNKNOWN_SWITCH) | 162       if (switch_type == SwitchStatement::UNKNOWN_SWITCH) | 
| 149         switch_type = label_switch_type; | 163         switch_type = label_switch_type; | 
| 150       else if (switch_type != label_switch_type) | 164       else if (switch_type != label_switch_type) | 
| 151         switch_type = SwitchStatement::GENERIC_SWITCH; | 165         switch_type = SwitchStatement::GENERIC_SWITCH; | 
|  | 166 | 
|  | 167       RECURSE(Visit(label)); | 
| 152     } | 168     } | 
| 153     RECURSE(VisitStatements(clause->statements())); | 169     RECURSE(VisitStatements(clause->statements())); | 
| 154   } | 170   } | 
|  | 171 | 
|  | 172   // TODO(rossberg): handle switch effects | 
|  | 173   store_.Forget(); | 
|  | 174 | 
| 155   if (switch_type == SwitchStatement::UNKNOWN_SWITCH) | 175   if (switch_type == SwitchStatement::UNKNOWN_SWITCH) | 
| 156     switch_type = SwitchStatement::GENERIC_SWITCH; | 176     switch_type = SwitchStatement::GENERIC_SWITCH; | 
| 157   stmt->set_switch_type(switch_type); | 177   stmt->set_switch_type(switch_type); | 
| 158 | 178 | 
|  | 179   // Collect type feedback. | 
| 159   // TODO(rossberg): can we eliminate this special case and extra loop? | 180   // TODO(rossberg): can we eliminate this special case and extra loop? | 
| 160   if (switch_type == SwitchStatement::SMI_SWITCH) { | 181   if (switch_type == SwitchStatement::SMI_SWITCH) { | 
| 161     for (int i = 0; i < clauses->length(); ++i) { | 182     for (int i = 0; i < clauses->length(); ++i) { | 
| 162       CaseClause* clause = clauses->at(i); | 183       CaseClause* clause = clauses->at(i); | 
| 163       if (!clause->is_default()) | 184       if (!clause->is_default()) | 
| 164         clause->RecordTypeFeedback(oracle()); | 185         clause->RecordTypeFeedback(oracle()); | 
| 165     } | 186     } | 
| 166   } | 187   } | 
| 167 } | 188 } | 
| 168 | 189 | 
| 169 | 190 | 
| 170 void AstTyper::VisitDoWhileStatement(DoWhileStatement* stmt) { | 191 void AstTyper::VisitDoWhileStatement(DoWhileStatement* stmt) { | 
| 171   RECURSE(Visit(stmt->body())); | 192   // Collect type feedback. | 
| 172   RECURSE(Visit(stmt->cond())); |  | 
| 173 |  | 
| 174   if (!stmt->cond()->ToBooleanIsTrue()) { | 193   if (!stmt->cond()->ToBooleanIsTrue()) { | 
| 175     stmt->cond()->RecordToBooleanTypeFeedback(oracle()); | 194     stmt->cond()->RecordToBooleanTypeFeedback(oracle()); | 
| 176   } | 195   } | 
|  | 196 | 
|  | 197   // TODO(rossberg): we could refine the unconditional Forget if we computed the | 
|  | 198   // set of variables assigned to in the loop. Same for other control transfers. | 
|  | 199   store_.Forget();  // Control may transfer here via looping or 'continue'. | 
|  | 200   RECURSE(Visit(stmt->body())); | 
|  | 201   RECURSE(Visit(stmt->cond())); | 
|  | 202   store_.Forget();  // Control may transfer here via 'break'. | 
| 177 } | 203 } | 
| 178 | 204 | 
| 179 | 205 | 
| 180 void AstTyper::VisitWhileStatement(WhileStatement* stmt) { | 206 void AstTyper::VisitWhileStatement(WhileStatement* stmt) { | 
| 181   RECURSE(Visit(stmt->cond())); | 207   // Collect type feedback. | 
| 182   RECURSE(Visit(stmt->body())); |  | 
| 183 |  | 
| 184   if (!stmt->cond()->ToBooleanIsTrue()) { | 208   if (!stmt->cond()->ToBooleanIsTrue()) { | 
| 185     stmt->cond()->RecordToBooleanTypeFeedback(oracle()); | 209     stmt->cond()->RecordToBooleanTypeFeedback(oracle()); | 
| 186   } | 210   } | 
|  | 211 | 
|  | 212   store_.Forget();  // Control may transfer here via looping or 'continue'. | 
|  | 213   RECURSE(Visit(stmt->cond())); | 
|  | 214   RECURSE(Visit(stmt->body())); | 
|  | 215   store_.Forget();  // Control may transfer here via termination or 'break'. | 
| 187 } | 216 } | 
| 188 | 217 | 
| 189 | 218 | 
| 190 void AstTyper::VisitForStatement(ForStatement* stmt) { | 219 void AstTyper::VisitForStatement(ForStatement* stmt) { | 
| 191   if (stmt->init() != NULL) { | 220   if (stmt->init() != NULL) { | 
| 192     RECURSE(Visit(stmt->init())); | 221     RECURSE(Visit(stmt->init())); | 
| 193   } | 222   } | 
|  | 223   store_.Forget();  // Control may transfer here via looping. | 
| 194   if (stmt->cond() != NULL) { | 224   if (stmt->cond() != NULL) { | 
|  | 225     // Collect type feedback. | 
|  | 226     stmt->cond()->RecordToBooleanTypeFeedback(oracle()); | 
|  | 227 | 
| 195     RECURSE(Visit(stmt->cond())); | 228     RECURSE(Visit(stmt->cond())); | 
| 196 |  | 
| 197     stmt->cond()->RecordToBooleanTypeFeedback(oracle()); |  | 
| 198   } | 229   } | 
| 199   RECURSE(Visit(stmt->body())); | 230   RECURSE(Visit(stmt->body())); | 
|  | 231   store_.Forget();  // Control may transfer here via 'continue'. | 
| 200   if (stmt->next() != NULL) { | 232   if (stmt->next() != NULL) { | 
| 201     RECURSE(Visit(stmt->next())); | 233     RECURSE(Visit(stmt->next())); | 
| 202   } | 234   } | 
|  | 235   store_.Forget();  // Control may transfer here via termination or 'break'. | 
| 203 } | 236 } | 
| 204 | 237 | 
| 205 | 238 | 
| 206 void AstTyper::VisitForInStatement(ForInStatement* stmt) { | 239 void AstTyper::VisitForInStatement(ForInStatement* stmt) { | 
|  | 240   // Collect type feedback. | 
|  | 241   stmt->RecordTypeFeedback(oracle()); | 
|  | 242 | 
| 207   RECURSE(Visit(stmt->enumerable())); | 243   RECURSE(Visit(stmt->enumerable())); | 
|  | 244   store_.Forget();  // Control may transfer here via looping or 'continue'. | 
| 208   RECURSE(Visit(stmt->body())); | 245   RECURSE(Visit(stmt->body())); | 
| 209 | 246   store_.Forget();  // Control may transfer here via 'break'. | 
| 210   stmt->RecordTypeFeedback(oracle()); |  | 
| 211 } | 247 } | 
| 212 | 248 | 
| 213 | 249 | 
| 214 void AstTyper::VisitForOfStatement(ForOfStatement* stmt) { | 250 void AstTyper::VisitForOfStatement(ForOfStatement* stmt) { | 
| 215   RECURSE(Visit(stmt->iterable())); | 251   RECURSE(Visit(stmt->iterable())); | 
|  | 252   store_.Forget();  // Control may transfer here via looping or 'continue'. | 
| 216   RECURSE(Visit(stmt->body())); | 253   RECURSE(Visit(stmt->body())); | 
|  | 254   store_.Forget();  // Control may transfer here via 'break'. | 
| 217 } | 255 } | 
| 218 | 256 | 
| 219 | 257 | 
| 220 void AstTyper::VisitTryCatchStatement(TryCatchStatement* stmt) { | 258 void AstTyper::VisitTryCatchStatement(TryCatchStatement* stmt) { | 
|  | 259   Effects try_effects = EnterEffects(); | 
| 221   RECURSE(Visit(stmt->try_block())); | 260   RECURSE(Visit(stmt->try_block())); | 
|  | 261   ExitEffects(); | 
|  | 262   Effects catch_effects = EnterEffects(); | 
|  | 263   store_.Forget();  // Control may transfer here via 'throw'. | 
| 222   RECURSE(Visit(stmt->catch_block())); | 264   RECURSE(Visit(stmt->catch_block())); | 
|  | 265   ExitEffects(); | 
|  | 266   try_effects.Alt(catch_effects); | 
|  | 267   store_.Seq(try_effects); | 
|  | 268   // At this point, only variables that were reassigned in the catch block are | 
|  | 269   // still remembered. | 
| 223 } | 270 } | 
| 224 | 271 | 
| 225 | 272 | 
| 226 void AstTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 273 void AstTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 
| 227   RECURSE(Visit(stmt->try_block())); | 274   RECURSE(Visit(stmt->try_block())); | 
|  | 275   store_.Forget();  // Control may transfer here via 'throw'. | 
| 228   RECURSE(Visit(stmt->finally_block())); | 276   RECURSE(Visit(stmt->finally_block())); | 
| 229 } | 277 } | 
| 230 | 278 | 
| 231 | 279 | 
| 232 void AstTyper::VisitDebuggerStatement(DebuggerStatement* stmt) { | 280 void AstTyper::VisitDebuggerStatement(DebuggerStatement* stmt) { | 
|  | 281   store_.Forget();  // May do whatever. | 
| 233 } | 282 } | 
| 234 | 283 | 
| 235 | 284 | 
| 236 void AstTyper::VisitFunctionLiteral(FunctionLiteral* expr) { | 285 void AstTyper::VisitFunctionLiteral(FunctionLiteral* expr) { | 
| 237 } | 286 } | 
| 238 | 287 | 
| 239 | 288 | 
| 240 void AstTyper::VisitSharedFunctionInfoLiteral(SharedFunctionInfoLiteral* expr) { | 289 void AstTyper::VisitSharedFunctionInfoLiteral(SharedFunctionInfoLiteral* expr) { | 
| 241 } | 290 } | 
| 242 | 291 | 
| 243 | 292 | 
| 244 void AstTyper::VisitConditional(Conditional* expr) { | 293 void AstTyper::VisitConditional(Conditional* expr) { | 
|  | 294   // Collect type feedback. | 
|  | 295   expr->condition()->RecordToBooleanTypeFeedback(oracle()); | 
|  | 296 | 
| 245   RECURSE(Visit(expr->condition())); | 297   RECURSE(Visit(expr->condition())); | 
|  | 298   Effects then_effects = EnterEffects(); | 
| 246   RECURSE(Visit(expr->then_expression())); | 299   RECURSE(Visit(expr->then_expression())); | 
|  | 300   ExitEffects(); | 
|  | 301   Effects else_effects = EnterEffects(); | 
| 247   RECURSE(Visit(expr->else_expression())); | 302   RECURSE(Visit(expr->else_expression())); | 
| 248 | 303   ExitEffects(); | 
| 249   expr->condition()->RecordToBooleanTypeFeedback(oracle()); | 304   then_effects.Alt(else_effects); | 
|  | 305   store_.Seq(then_effects); | 
| 250 | 306 | 
| 251   NarrowType(expr, Bounds::Either( | 307   NarrowType(expr, Bounds::Either( | 
| 252       expr->then_expression()->bounds(), | 308       expr->then_expression()->bounds(), | 
| 253       expr->else_expression()->bounds(), isolate_)); | 309       expr->else_expression()->bounds(), isolate_)); | 
| 254 } | 310 } | 
| 255 | 311 | 
| 256 | 312 | 
| 257 void AstTyper::VisitVariableProxy(VariableProxy* expr) { | 313 void AstTyper::VisitVariableProxy(VariableProxy* expr) { | 
| 258   // TODO(rossberg): typing of variables | 314   Variable* var = expr->var(); | 
|  | 315   if (var->IsStackAllocated()) { | 
|  | 316     NarrowType(expr, store_.LookupBounds(variable_index(var))); | 
|  | 317   } | 
| 259 } | 318 } | 
| 260 | 319 | 
| 261 | 320 | 
| 262 void AstTyper::VisitLiteral(Literal* expr) { | 321 void AstTyper::VisitLiteral(Literal* expr) { | 
| 263   Type* type = Type::Constant(expr->value(), isolate_); | 322   Type* type = Type::Constant(expr->value(), isolate_); | 
| 264   NarrowType(expr, Bounds(type, isolate_)); | 323   NarrowType(expr, Bounds(type, isolate_)); | 
| 265 } | 324 } | 
| 266 | 325 | 
| 267 | 326 | 
| 268 void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) { | 327 void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) { | 
| 269   NarrowType(expr, Bounds(Type::RegExp(), isolate_)); | 328   NarrowType(expr, Bounds(Type::RegExp(), isolate_)); | 
| 270 } | 329 } | 
| 271 | 330 | 
| 272 | 331 | 
| 273 void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) { | 332 void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) { | 
| 274   ZoneList<ObjectLiteral::Property*>* properties = expr->properties(); | 333   ZoneList<ObjectLiteral::Property*>* properties = expr->properties(); | 
| 275   for (int i = 0; i < properties->length(); ++i) { | 334   for (int i = 0; i < properties->length(); ++i) { | 
| 276     ObjectLiteral::Property* prop = properties->at(i); | 335     ObjectLiteral::Property* prop = properties->at(i); | 
| 277     RECURSE(Visit(prop->value())); |  | 
| 278 | 336 | 
|  | 337     // Collect type feedback. | 
| 279     if ((prop->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL && | 338     if ((prop->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL && | 
| 280         !CompileTimeValue::IsCompileTimeValue(prop->value())) || | 339         !CompileTimeValue::IsCompileTimeValue(prop->value())) || | 
| 281         prop->kind() == ObjectLiteral::Property::COMPUTED) { | 340         prop->kind() == ObjectLiteral::Property::COMPUTED) { | 
| 282       if (prop->key()->value()->IsInternalizedString() && prop->emit_store()) { | 341       if (prop->key()->value()->IsInternalizedString() && prop->emit_store()) { | 
| 283         prop->RecordTypeFeedback(oracle()); | 342         prop->RecordTypeFeedback(oracle()); | 
| 284       } | 343       } | 
| 285     } | 344     } | 
|  | 345 | 
|  | 346     RECURSE(Visit(prop->value())); | 
| 286   } | 347   } | 
| 287 | 348 | 
| 288   NarrowType(expr, Bounds(Type::Object(), isolate_)); | 349   NarrowType(expr, Bounds(Type::Object(), isolate_)); | 
| 289 } | 350 } | 
| 290 | 351 | 
| 291 | 352 | 
| 292 void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) { | 353 void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) { | 
| 293   ZoneList<Expression*>* values = expr->values(); | 354   ZoneList<Expression*>* values = expr->values(); | 
| 294   for (int i = 0; i < values->length(); ++i) { | 355   for (int i = 0; i < values->length(); ++i) { | 
| 295     Expression* value = values->at(i); | 356     Expression* value = values->at(i); | 
| 296     RECURSE(Visit(value)); | 357     RECURSE(Visit(value)); | 
| 297   } | 358   } | 
| 298 | 359 | 
| 299   NarrowType(expr, Bounds(Type::Array(), isolate_)); | 360   NarrowType(expr, Bounds(Type::Array(), isolate_)); | 
| 300 } | 361 } | 
| 301 | 362 | 
| 302 | 363 | 
| 303 void AstTyper::VisitAssignment(Assignment* expr) { | 364 void AstTyper::VisitAssignment(Assignment* expr) { | 
| 304   // TODO(rossberg): Can we clean this up? | 365   // TODO(rossberg): Can we clean this up? | 
| 305   if (expr->is_compound()) { | 366   if (expr->is_compound()) { | 
| 306     RECURSE(Visit(expr->binary_operation())); | 367     // Collect type feedback. | 
| 307 |  | 
| 308     Expression* target = expr->target(); | 368     Expression* target = expr->target(); | 
| 309     Property* prop = target->AsProperty(); | 369     Property* prop = target->AsProperty(); | 
| 310     if (prop != NULL) { | 370     if (prop != NULL) { | 
| 311       prop->RecordTypeFeedback(oracle(), zone()); | 371       prop->RecordTypeFeedback(oracle(), zone()); | 
| 312       if (!prop->key()->IsPropertyName()) {  // i.e., keyed | 372       if (!prop->key()->IsPropertyName()) {  // i.e., keyed | 
| 313         expr->RecordTypeFeedback(oracle(), zone()); | 373         expr->RecordTypeFeedback(oracle(), zone()); | 
| 314       } | 374       } | 
| 315     } | 375     } | 
| 316 | 376 | 
|  | 377     RECURSE(Visit(expr->binary_operation())); | 
|  | 378 | 
| 317     NarrowType(expr, expr->binary_operation()->bounds()); | 379     NarrowType(expr, expr->binary_operation()->bounds()); | 
| 318   } else { | 380   } else { | 
| 319     RECURSE(Visit(expr->target())); | 381     // Collect type feedback. | 
| 320     RECURSE(Visit(expr->value())); |  | 
| 321 |  | 
| 322     if (expr->target()->AsProperty()) { | 382     if (expr->target()->AsProperty()) { | 
| 323       expr->RecordTypeFeedback(oracle(), zone()); | 383       expr->RecordTypeFeedback(oracle(), zone()); | 
| 324     } | 384     } | 
| 325 | 385 | 
|  | 386     RECURSE(Visit(expr->target())); | 
|  | 387     RECURSE(Visit(expr->value())); | 
|  | 388 | 
| 326     NarrowType(expr, expr->value()->bounds()); | 389     NarrowType(expr, expr->value()->bounds()); | 
| 327   } | 390   } | 
| 328   // TODO(rossberg): handle target variables | 391 | 
|  | 392   if (expr->target()->AsVariableProxy()) { | 
|  | 393     Variable* var = expr->target()->AsVariableProxy()->var(); | 
|  | 394     if (var->IsStackAllocated()) { | 
|  | 395       store_.Seq(variable_index(var), Effect(expr->bounds())); | 
|  | 396     } | 
|  | 397   } | 
| 329 } | 398 } | 
| 330 | 399 | 
| 331 | 400 | 
| 332 void AstTyper::VisitYield(Yield* expr) { | 401 void AstTyper::VisitYield(Yield* expr) { | 
| 333   RECURSE(Visit(expr->generator_object())); | 402   RECURSE(Visit(expr->generator_object())); | 
| 334   RECURSE(Visit(expr->expression())); | 403   RECURSE(Visit(expr->expression())); | 
| 335 | 404 | 
| 336   // We don't know anything about the type. | 405   // We don't know anything about the result type. | 
| 337 } | 406 } | 
| 338 | 407 | 
| 339 | 408 | 
| 340 void AstTyper::VisitThrow(Throw* expr) { | 409 void AstTyper::VisitThrow(Throw* expr) { | 
| 341   RECURSE(Visit(expr->exception())); | 410   RECURSE(Visit(expr->exception())); | 
|  | 411   // TODO(rossberg): is it worth having a non-termination effect? | 
| 342 | 412 | 
| 343   NarrowType(expr, Bounds(Type::None(), isolate_)); | 413   NarrowType(expr, Bounds(Type::None(), isolate_)); | 
| 344 } | 414 } | 
| 345 | 415 | 
| 346 | 416 | 
| 347 void AstTyper::VisitProperty(Property* expr) { | 417 void AstTyper::VisitProperty(Property* expr) { | 
|  | 418   // Collect type feedback. | 
|  | 419   expr->RecordTypeFeedback(oracle(), zone()); | 
|  | 420 | 
| 348   RECURSE(Visit(expr->obj())); | 421   RECURSE(Visit(expr->obj())); | 
| 349   RECURSE(Visit(expr->key())); | 422   RECURSE(Visit(expr->key())); | 
| 350 | 423 | 
| 351   expr->RecordTypeFeedback(oracle(), zone()); | 424   // We don't know anything about the result type. | 
| 352 |  | 
| 353   // We don't know anything about the type. |  | 
| 354 } | 425 } | 
| 355 | 426 | 
| 356 | 427 | 
| 357 void AstTyper::VisitCall(Call* expr) { | 428 void AstTyper::VisitCall(Call* expr) { | 
| 358   RECURSE(Visit(expr->expression())); | 429   // Collect type feedback. | 
| 359   ZoneList<Expression*>* args = expr->arguments(); |  | 
| 360   for (int i = 0; i < args->length(); ++i) { |  | 
| 361     Expression* arg = args->at(i); |  | 
| 362     RECURSE(Visit(arg)); |  | 
| 363   } |  | 
| 364 |  | 
| 365   Expression* callee = expr->expression(); | 430   Expression* callee = expr->expression(); | 
| 366   Property* prop = callee->AsProperty(); | 431   Property* prop = callee->AsProperty(); | 
| 367   if (prop != NULL) { | 432   if (prop != NULL) { | 
| 368     if (prop->key()->IsPropertyName()) | 433     if (prop->key()->IsPropertyName()) | 
| 369       expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD); | 434       expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD); | 
| 370   } else { | 435   } else { | 
| 371     expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION); | 436     expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION); | 
| 372   } | 437   } | 
| 373 | 438 | 
| 374   // We don't know anything about the type. | 439   RECURSE(Visit(expr->expression())); | 
|  | 440   ZoneList<Expression*>* args = expr->arguments(); | 
|  | 441   for (int i = 0; i < args->length(); ++i) { | 
|  | 442     Expression* arg = args->at(i); | 
|  | 443     RECURSE(Visit(arg)); | 
|  | 444   } | 
|  | 445 | 
|  | 446   VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 
|  | 447   if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { | 
|  | 448     store_.Forget();  // Eval could do whatever to local variables. | 
|  | 449   } | 
|  | 450 | 
|  | 451   // We don't know anything about the result type. | 
| 375 } | 452 } | 
| 376 | 453 | 
| 377 | 454 | 
| 378 void AstTyper::VisitCallNew(CallNew* expr) { | 455 void AstTyper::VisitCallNew(CallNew* expr) { | 
|  | 456   // Collect type feedback. | 
|  | 457   expr->RecordTypeFeedback(oracle()); | 
|  | 458 | 
| 379   RECURSE(Visit(expr->expression())); | 459   RECURSE(Visit(expr->expression())); | 
| 380   ZoneList<Expression*>* args = expr->arguments(); | 460   ZoneList<Expression*>* args = expr->arguments(); | 
| 381   for (int i = 0; i < args->length(); ++i) { | 461   for (int i = 0; i < args->length(); ++i) { | 
| 382     Expression* arg = args->at(i); | 462     Expression* arg = args->at(i); | 
| 383     RECURSE(Visit(arg)); | 463     RECURSE(Visit(arg)); | 
| 384   } | 464   } | 
| 385 | 465 | 
| 386   expr->RecordTypeFeedback(oracle()); | 466   // We don't know anything about the result type. | 
| 387 |  | 
| 388   // We don't know anything about the type. |  | 
| 389 } | 467 } | 
| 390 | 468 | 
| 391 | 469 | 
| 392 void AstTyper::VisitCallRuntime(CallRuntime* expr) { | 470 void AstTyper::VisitCallRuntime(CallRuntime* expr) { | 
| 393   ZoneList<Expression*>* args = expr->arguments(); | 471   ZoneList<Expression*>* args = expr->arguments(); | 
| 394   for (int i = 0; i < args->length(); ++i) { | 472   for (int i = 0; i < args->length(); ++i) { | 
| 395     Expression* arg = args->at(i); | 473     Expression* arg = args->at(i); | 
| 396     RECURSE(Visit(arg)); | 474     RECURSE(Visit(arg)); | 
| 397   } | 475   } | 
| 398 | 476 | 
| 399   // We don't know anything about the type. | 477   // We don't know anything about the result type. | 
| 400 } | 478 } | 
| 401 | 479 | 
| 402 | 480 | 
| 403 void AstTyper::VisitUnaryOperation(UnaryOperation* expr) { | 481 void AstTyper::VisitUnaryOperation(UnaryOperation* expr) { | 
| 404   RECURSE(Visit(expr->expression())); |  | 
| 405 |  | 
| 406   // Collect type feedback. | 482   // Collect type feedback. | 
| 407   Handle<Type> op_type = oracle()->UnaryType(expr->UnaryOperationFeedbackId()); | 483   Handle<Type> op_type = oracle()->UnaryType(expr->UnaryOperationFeedbackId()); | 
| 408   NarrowLowerType(expr->expression(), op_type); | 484   NarrowLowerType(expr->expression(), op_type); | 
| 409   if (expr->op() == Token::NOT) { | 485   if (expr->op() == Token::NOT) { | 
| 410     // TODO(rossberg): only do in test or value context. | 486     // TODO(rossberg): only do in test or value context. | 
| 411     expr->expression()->RecordToBooleanTypeFeedback(oracle()); | 487     expr->expression()->RecordToBooleanTypeFeedback(oracle()); | 
| 412   } | 488   } | 
| 413 | 489 | 
|  | 490   RECURSE(Visit(expr->expression())); | 
|  | 491 | 
| 414   switch (expr->op()) { | 492   switch (expr->op()) { | 
| 415     case Token::NOT: | 493     case Token::NOT: | 
| 416     case Token::DELETE: | 494     case Token::DELETE: | 
| 417       NarrowType(expr, Bounds(Type::Boolean(), isolate_)); | 495       NarrowType(expr, Bounds(Type::Boolean(), isolate_)); | 
| 418       break; | 496       break; | 
| 419     case Token::VOID: | 497     case Token::VOID: | 
| 420       NarrowType(expr, Bounds(Type::Undefined(), isolate_)); | 498       NarrowType(expr, Bounds(Type::Undefined(), isolate_)); | 
| 421       break; | 499       break; | 
| 422     case Token::ADD: | 500     case Token::ADD: | 
| 423     case Token::SUB: { | 501     case Token::SUB: { | 
| 424       Type* upper = *expr->expression()->bounds().upper; | 502       Type* upper = *expr->expression()->bounds().upper; | 
| 425       if (!upper->Is(Type::Number())) upper = Type::Number(); | 503       if (!upper->Is(Type::Number())) upper = Type::Number(); | 
| 426       NarrowType(expr, Bounds(Type::Smi(), upper, isolate_)); | 504       NarrowType(expr, Bounds(Type::Smi(), upper, isolate_)); | 
| 427       break; | 505       break; | 
| 428     } | 506     } | 
| 429     case Token::BIT_NOT: | 507     case Token::BIT_NOT: | 
| 430       NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_)); | 508       NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_)); | 
| 431       break; | 509       break; | 
| 432     case Token::TYPEOF: | 510     case Token::TYPEOF: | 
| 433       NarrowType(expr, Bounds(Type::InternalizedString(), isolate_)); | 511       NarrowType(expr, Bounds(Type::InternalizedString(), isolate_)); | 
| 434       break; | 512       break; | 
| 435     default: | 513     default: | 
| 436       UNREACHABLE(); | 514       UNREACHABLE(); | 
| 437   } | 515   } | 
| 438 } | 516 } | 
| 439 | 517 | 
| 440 | 518 | 
| 441 void AstTyper::VisitCountOperation(CountOperation* expr) { | 519 void AstTyper::VisitCountOperation(CountOperation* expr) { | 
| 442   RECURSE(Visit(expr->expression())); | 520   // Collect type feedback. | 
| 443 |  | 
| 444   expr->RecordTypeFeedback(oracle(), zone()); | 521   expr->RecordTypeFeedback(oracle(), zone()); | 
| 445   Property* prop = expr->expression()->AsProperty(); | 522   Property* prop = expr->expression()->AsProperty(); | 
| 446   if (prop != NULL) { | 523   if (prop != NULL) { | 
| 447     prop->RecordTypeFeedback(oracle(), zone()); | 524     prop->RecordTypeFeedback(oracle(), zone()); | 
| 448   } | 525   } | 
| 449 | 526 | 
|  | 527   RECURSE(Visit(expr->expression())); | 
|  | 528 | 
| 450   NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_)); | 529   NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_)); | 
|  | 530 | 
|  | 531   if (expr->expression()->AsVariableProxy()) { | 
|  | 532     Variable* var = expr->expression()->AsVariableProxy()->var(); | 
|  | 533     if (var->IsStackAllocated()) { | 
|  | 534       store_.Seq(variable_index(var), Effect(expr->bounds())); | 
|  | 535     } | 
|  | 536   } | 
| 451 } | 537 } | 
| 452 | 538 | 
| 453 | 539 | 
| 454 void AstTyper::VisitBinaryOperation(BinaryOperation* expr) { | 540 void AstTyper::VisitBinaryOperation(BinaryOperation* expr) { | 
| 455   RECURSE(Visit(expr->left())); |  | 
| 456   RECURSE(Visit(expr->right())); |  | 
| 457 |  | 
| 458   // Collect type feedback. | 541   // Collect type feedback. | 
| 459   Handle<Type> type, left_type, right_type; | 542   Handle<Type> type, left_type, right_type; | 
| 460   Maybe<int> fixed_right_arg; | 543   Maybe<int> fixed_right_arg; | 
| 461   oracle()->BinaryType(expr->BinaryOperationFeedbackId(), | 544   oracle()->BinaryType(expr->BinaryOperationFeedbackId(), | 
| 462       &left_type, &right_type, &type, &fixed_right_arg); | 545       &left_type, &right_type, &type, &fixed_right_arg); | 
| 463   NarrowLowerType(expr, type); | 546   NarrowLowerType(expr, type); | 
| 464   NarrowLowerType(expr->left(), left_type); | 547   NarrowLowerType(expr->left(), left_type); | 
| 465   NarrowLowerType(expr->right(), right_type); | 548   NarrowLowerType(expr->right(), right_type); | 
| 466   expr->set_fixed_right_arg(fixed_right_arg); | 549   expr->set_fixed_right_arg(fixed_right_arg); | 
| 467   if (expr->op() == Token::OR || expr->op() == Token::AND) { | 550   if (expr->op() == Token::OR || expr->op() == Token::AND) { | 
| 468     expr->left()->RecordToBooleanTypeFeedback(oracle()); | 551     expr->left()->RecordToBooleanTypeFeedback(oracle()); | 
| 469   } | 552   } | 
| 470 | 553 | 
| 471   switch (expr->op()) { | 554   switch (expr->op()) { | 
| 472     case Token::COMMA: | 555     case Token::COMMA: | 
|  | 556       RECURSE(Visit(expr->left())); | 
|  | 557       RECURSE(Visit(expr->right())); | 
| 473       NarrowType(expr, expr->right()->bounds()); | 558       NarrowType(expr, expr->right()->bounds()); | 
| 474       break; | 559       break; | 
| 475     case Token::OR: | 560     case Token::OR: | 
| 476     case Token::AND: | 561     case Token::AND: { | 
|  | 562       Effects left_effects = EnterEffects(); | 
|  | 563       RECURSE(Visit(expr->left())); | 
|  | 564       ExitEffects(); | 
|  | 565       Effects right_effects = EnterEffects(); | 
|  | 566       RECURSE(Visit(expr->right())); | 
|  | 567       ExitEffects(); | 
|  | 568       left_effects.Alt(right_effects); | 
|  | 569       store_.Seq(left_effects); | 
|  | 570 | 
| 477       NarrowType(expr, Bounds::Either( | 571       NarrowType(expr, Bounds::Either( | 
| 478           expr->left()->bounds(), expr->right()->bounds(), isolate_)); | 572           expr->left()->bounds(), expr->right()->bounds(), isolate_)); | 
| 479       break; | 573       break; | 
|  | 574     } | 
| 480     case Token::BIT_OR: | 575     case Token::BIT_OR: | 
| 481     case Token::BIT_AND: { | 576     case Token::BIT_AND: { | 
|  | 577       RECURSE(Visit(expr->left())); | 
|  | 578       RECURSE(Visit(expr->right())); | 
| 482       Type* upper = Type::Union( | 579       Type* upper = Type::Union( | 
| 483           expr->left()->bounds().upper, expr->right()->bounds().upper); | 580           expr->left()->bounds().upper, expr->right()->bounds().upper); | 
| 484       if (!upper->Is(Type::Signed32())) upper = Type::Signed32(); | 581       if (!upper->Is(Type::Signed32())) upper = Type::Signed32(); | 
| 485       NarrowType(expr, Bounds(Type::Smi(), upper, isolate_)); | 582       NarrowType(expr, Bounds(Type::Smi(), upper, isolate_)); | 
| 486       break; | 583       break; | 
| 487     } | 584     } | 
| 488     case Token::BIT_XOR: | 585     case Token::BIT_XOR: | 
| 489     case Token::SHL: | 586     case Token::SHL: | 
| 490     case Token::SAR: | 587     case Token::SAR: | 
|  | 588       RECURSE(Visit(expr->left())); | 
|  | 589       RECURSE(Visit(expr->right())); | 
| 491       NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_)); | 590       NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_)); | 
| 492       break; | 591       break; | 
| 493     case Token::SHR: | 592     case Token::SHR: | 
|  | 593       RECURSE(Visit(expr->left())); | 
|  | 594       RECURSE(Visit(expr->right())); | 
| 494       NarrowType(expr, Bounds(Type::Smi(), Type::Unsigned32(), isolate_)); | 595       NarrowType(expr, Bounds(Type::Smi(), Type::Unsigned32(), isolate_)); | 
| 495       break; | 596       break; | 
| 496     case Token::ADD: { | 597     case Token::ADD: { | 
|  | 598       RECURSE(Visit(expr->left())); | 
|  | 599       RECURSE(Visit(expr->right())); | 
| 497       Bounds l = expr->left()->bounds(); | 600       Bounds l = expr->left()->bounds(); | 
| 498       Bounds r = expr->right()->bounds(); | 601       Bounds r = expr->right()->bounds(); | 
| 499       Type* lower = | 602       Type* lower = | 
| 500           l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) ? | 603           l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) ? | 
| 501               Type::Smi() : | 604               Type::Smi() : | 
| 502           l.lower->Is(Type::String()) || r.lower->Is(Type::String()) ? | 605           l.lower->Is(Type::String()) || r.lower->Is(Type::String()) ? | 
| 503               Type::String() : Type::None(); | 606               Type::String() : Type::None(); | 
| 504       Type* upper = | 607       Type* upper = | 
| 505           l.upper->Is(Type::Number()) && r.upper->Is(Type::Number()) ? | 608           l.upper->Is(Type::Number()) && r.upper->Is(Type::Number()) ? | 
| 506               Type::Number() : | 609               Type::Number() : | 
| 507           l.upper->Is(Type::String()) || r.upper->Is(Type::String()) ? | 610           l.upper->Is(Type::String()) || r.upper->Is(Type::String()) ? | 
| 508               Type::String() : Type::NumberOrString(); | 611               Type::String() : Type::NumberOrString(); | 
| 509       NarrowType(expr, Bounds(lower, upper, isolate_)); | 612       NarrowType(expr, Bounds(lower, upper, isolate_)); | 
| 510       break; | 613       break; | 
| 511     } | 614     } | 
| 512     case Token::SUB: | 615     case Token::SUB: | 
| 513     case Token::MUL: | 616     case Token::MUL: | 
| 514     case Token::DIV: | 617     case Token::DIV: | 
| 515     case Token::MOD: | 618     case Token::MOD: | 
|  | 619       RECURSE(Visit(expr->left())); | 
|  | 620       RECURSE(Visit(expr->right())); | 
| 516       NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_)); | 621       NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_)); | 
| 517       break; | 622       break; | 
| 518     default: | 623     default: | 
| 519       UNREACHABLE(); | 624       UNREACHABLE(); | 
| 520   } | 625   } | 
| 521 } | 626 } | 
| 522 | 627 | 
| 523 | 628 | 
| 524 void AstTyper::VisitCompareOperation(CompareOperation* expr) { | 629 void AstTyper::VisitCompareOperation(CompareOperation* expr) { | 
| 525   RECURSE(Visit(expr->left())); |  | 
| 526   RECURSE(Visit(expr->right())); |  | 
| 527 |  | 
| 528   // Collect type feedback. | 630   // Collect type feedback. | 
| 529   Handle<Type> left_type, right_type, combined_type; | 631   Handle<Type> left_type, right_type, combined_type; | 
| 530   oracle()->CompareType(expr->CompareOperationFeedbackId(), | 632   oracle()->CompareType(expr->CompareOperationFeedbackId(), | 
| 531       &left_type, &right_type, &combined_type); | 633       &left_type, &right_type, &combined_type); | 
| 532   NarrowLowerType(expr->left(), left_type); | 634   NarrowLowerType(expr->left(), left_type); | 
| 533   NarrowLowerType(expr->right(), right_type); | 635   NarrowLowerType(expr->right(), right_type); | 
| 534   expr->set_combined_type(combined_type); | 636   expr->set_combined_type(combined_type); | 
| 535 | 637 | 
|  | 638   RECURSE(Visit(expr->left())); | 
|  | 639   RECURSE(Visit(expr->right())); | 
|  | 640 | 
| 536   NarrowType(expr, Bounds(Type::Boolean(), isolate_)); | 641   NarrowType(expr, Bounds(Type::Boolean(), isolate_)); | 
| 537 } | 642 } | 
| 538 | 643 | 
| 539 | 644 | 
| 540 void AstTyper::VisitThisFunction(ThisFunction* expr) { | 645 void AstTyper::VisitThisFunction(ThisFunction* expr) { | 
| 541 } | 646 } | 
| 542 | 647 | 
| 543 | 648 | 
| 544 void AstTyper::VisitDeclarations(ZoneList<Declaration*>* decls) { | 649 void AstTyper::VisitDeclarations(ZoneList<Declaration*>* decls) { | 
| 545   for (int i = 0; i < decls->length(); ++i) { | 650   for (int i = 0; i < decls->length(); ++i) { | 
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 589 void AstTyper::VisitModuleUrl(ModuleUrl* module) { | 694 void AstTyper::VisitModuleUrl(ModuleUrl* module) { | 
| 590 } | 695 } | 
| 591 | 696 | 
| 592 | 697 | 
| 593 void AstTyper::VisitModuleStatement(ModuleStatement* stmt) { | 698 void AstTyper::VisitModuleStatement(ModuleStatement* stmt) { | 
| 594   RECURSE(Visit(stmt->body())); | 699   RECURSE(Visit(stmt->body())); | 
| 595 } | 700 } | 
| 596 | 701 | 
| 597 | 702 | 
| 598 } }  // namespace v8::internal | 703 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|