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

Side by Side Diff: src/typing.cc

Issue 14990014: Collect type feedback in separate pass and store it in AST (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Consistent check-alive Created 7 years, 7 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/typing.h ('k') | tools/gyp/v8.gyp » ('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 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 "v8.h"
31 #include "parser.h" // for CompileTimeValue; TODO(rossberg): should move
32 #include "scopes.h"
33
34 namespace v8 {
35 namespace internal {
36
37
38 AstTyper::AstTyper(CompilationInfo* info)
39 : info_(info),
40 oracle_(
41 Handle<Code>(info->closure()->shared()->code()),
42 Handle<Context>(info->closure()->context()->native_context()),
43 info->isolate(),
44 info->zone()) {
45 InitializeAstVisitor();
46 }
47
48
49 #define CHECK_ALIVE(call) \
50 do { \
51 call; \
52 if (HasStackOverflow()) return; \
53 } while (false)
54
55
56 void AstTyper::Type(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 CHECK_ALIVE(visitor->VisitVariableDeclaration(scope->function()));
64 }
65 CHECK_ALIVE(visitor->VisitDeclarations(scope->declarations()));
66 CHECK_ALIVE(visitor->VisitStatements(info->function()->body()));
67 }
68
69
70 void AstTyper::VisitStatements(ZoneList<Statement*>* stmts) {
71 ASSERT(!HasStackOverflow());
72 for (int i = 0; i < stmts->length(); ++i) {
73 Statement* stmt = stmts->at(i);
74 CHECK_ALIVE(Visit(stmt));
75 }
76 }
77
78
79 void AstTyper::VisitBlock(Block* stmt) {
80 ASSERT(!HasStackOverflow());
81 CHECK_ALIVE(VisitStatements(stmt->statements()));
82 }
83
84
85 void AstTyper::VisitExpressionStatement(ExpressionStatement* stmt) {
86 ASSERT(!HasStackOverflow());
87 CHECK_ALIVE(Visit(stmt->expression()));
88 }
89
90
91 void AstTyper::VisitEmptyStatement(EmptyStatement* stmt) {
92 ASSERT(!HasStackOverflow());
93 }
94
95
96 void AstTyper::VisitIfStatement(IfStatement* stmt) {
97 ASSERT(!HasStackOverflow());
98 CHECK_ALIVE(Visit(stmt->condition()));
99 CHECK_ALIVE(Visit(stmt->then_statement()));
100 CHECK_ALIVE(Visit(stmt->else_statement()));
101
102 if (!stmt->condition()->ToBooleanIsTrue() &&
103 !stmt->condition()->ToBooleanIsFalse()) {
104 stmt->condition()->RecordToBooleanTypeFeedback(oracle());
105 }
106 }
107
108
109 void AstTyper::VisitContinueStatement(ContinueStatement* stmt) {
110 ASSERT(!HasStackOverflow());
111 }
112
113
114 void AstTyper::VisitBreakStatement(BreakStatement* stmt) {
115 ASSERT(!HasStackOverflow());
116 }
117
118
119 void AstTyper::VisitReturnStatement(ReturnStatement* stmt) {
120 ASSERT(!HasStackOverflow());
121 CHECK_ALIVE(Visit(stmt->expression()));
122
123 // TODO(rossberg): we only need this for inlining into test contexts...
124 stmt->expression()->RecordToBooleanTypeFeedback(oracle());
125 }
126
127
128 void AstTyper::VisitWithStatement(WithStatement* stmt) {
129 ASSERT(!HasStackOverflow());
130 CHECK_ALIVE(stmt->expression());
131 CHECK_ALIVE(stmt->statement());
132 }
133
134
135 void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) {
136 ASSERT(!HasStackOverflow());
137 CHECK_ALIVE(Visit(stmt->tag()));
138 ZoneList<CaseClause*>* clauses = stmt->cases();
139 SwitchStatement::SwitchType switch_type = stmt->switch_type();
140 for (int i = 0; i < clauses->length(); ++i) {
141 CaseClause* clause = clauses->at(i);
142 if (!clause->is_default()) {
143 Expression* label = clause->label();
144 CHECK_ALIVE(Visit(label));
145
146 SwitchStatement::SwitchType label_switch_type =
147 label->IsSmiLiteral() ? SwitchStatement::SMI_SWITCH :
148 label->IsStringLiteral() ? SwitchStatement::STRING_SWITCH :
149 SwitchStatement::GENERIC_SWITCH;
150 if (switch_type == SwitchStatement::UNKNOWN_SWITCH)
151 switch_type = label_switch_type;
152 else if (switch_type != label_switch_type)
153 switch_type = SwitchStatement::GENERIC_SWITCH;
154 }
155 CHECK_ALIVE(VisitStatements(clause->statements()));
156 }
157 if (switch_type == SwitchStatement::UNKNOWN_SWITCH)
158 switch_type = SwitchStatement::GENERIC_SWITCH;
159 stmt->set_switch_type(switch_type);
160
161 // TODO(rossberg): can we eliminate this special case and extra loop?
162 if (switch_type == SwitchStatement::SMI_SWITCH) {
163 for (int i = 0; i < clauses->length(); ++i) {
164 CaseClause* clause = clauses->at(i);
165 if (!clause->is_default())
166 clause->RecordTypeFeedback(oracle());
167 }
168 }
169 }
170
171
172 void AstTyper::VisitDoWhileStatement(DoWhileStatement* stmt) {
173 ASSERT(!HasStackOverflow());
174 CHECK_ALIVE(Visit(stmt->body()));
175 CHECK_ALIVE(Visit(stmt->cond()));
176
177 if (!stmt->cond()->ToBooleanIsTrue()) {
178 stmt->cond()->RecordToBooleanTypeFeedback(oracle());
179 }
180 }
181
182
183 void AstTyper::VisitWhileStatement(WhileStatement* stmt) {
184 ASSERT(!HasStackOverflow());
185 CHECK_ALIVE(Visit(stmt->cond()));
186 CHECK_ALIVE(Visit(stmt->body()));
187
188 if (!stmt->cond()->ToBooleanIsTrue()) {
189 stmt->cond()->RecordToBooleanTypeFeedback(oracle());
190 }
191 }
192
193
194 void AstTyper::VisitForStatement(ForStatement* stmt) {
195 ASSERT(!HasStackOverflow());
196 if (stmt->init() != NULL) {
197 CHECK_ALIVE(Visit(stmt->init()));
198 }
199 if (stmt->cond() != NULL) {
200 CHECK_ALIVE(Visit(stmt->cond()));
201
202 stmt->cond()->RecordToBooleanTypeFeedback(oracle());
203 }
204 CHECK_ALIVE(Visit(stmt->body()));
205 if (stmt->next() != NULL) {
206 CHECK_ALIVE(Visit(stmt->next()));
207 }
208 }
209
210
211 void AstTyper::VisitForInStatement(ForInStatement* stmt) {
212 ASSERT(!HasStackOverflow());
213 CHECK_ALIVE(Visit(stmt->enumerable()));
214 CHECK_ALIVE(Visit(stmt->body()));
215
216 stmt->RecordTypeFeedback(oracle());
217 }
218
219
220 void AstTyper::VisitTryCatchStatement(TryCatchStatement* stmt) {
221 ASSERT(!HasStackOverflow());
222 CHECK_ALIVE(Visit(stmt->try_block()));
223 CHECK_ALIVE(Visit(stmt->catch_block()));
224 }
225
226
227 void AstTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
228 ASSERT(!HasStackOverflow());
229 CHECK_ALIVE(Visit(stmt->try_block()));
230 CHECK_ALIVE(Visit(stmt->finally_block()));
231 }
232
233
234 void AstTyper::VisitDebuggerStatement(DebuggerStatement* stmt) {
235 ASSERT(!HasStackOverflow());
236 }
237
238
239 void AstTyper::VisitFunctionLiteral(FunctionLiteral* expr) {
240 ASSERT(!HasStackOverflow());
241 }
242
243
244 void AstTyper::VisitSharedFunctionInfoLiteral(SharedFunctionInfoLiteral* expr) {
245 ASSERT(!HasStackOverflow());
246 }
247
248
249 void AstTyper::VisitConditional(Conditional* expr) {
250 ASSERT(!HasStackOverflow());
251 CHECK_ALIVE(Visit(expr->condition()));
252 CHECK_ALIVE(Visit(expr->then_expression()));
253 CHECK_ALIVE(Visit(expr->else_expression()));
254
255 expr->condition()->RecordToBooleanTypeFeedback(oracle());
256 }
257
258
259 void AstTyper::VisitVariableProxy(VariableProxy* expr) {
260 ASSERT(!HasStackOverflow());
261 }
262
263
264 void AstTyper::VisitLiteral(Literal* expr) {
265 ASSERT(!HasStackOverflow());
266 }
267
268
269 void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) {
270 ASSERT(!HasStackOverflow());
271 }
272
273
274 void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) {
275 ASSERT(!HasStackOverflow());
276 ZoneList<ObjectLiteral::Property*>* properties = expr->properties();
277 for (int i = 0; i < properties->length(); ++i) {
278 ObjectLiteral::Property* prop = properties->at(i);
279 CHECK_ALIVE(Visit(prop->value()));
280
281 if ((prop->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL &&
282 !CompileTimeValue::IsCompileTimeValue(prop->value())) ||
283 prop->kind() == ObjectLiteral::Property::COMPUTED) {
284 if (prop->key()->handle()->IsInternalizedString() && prop->emit_store())
285 prop->RecordTypeFeedback(oracle());
286 }
287 }
288 }
289
290
291 void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) {
292 ASSERT(!HasStackOverflow());
293 ZoneList<Expression*>* values = expr->values();
294 for (int i = 0; i < values->length(); ++i) {
295 Expression* value = values->at(i);
296 CHECK_ALIVE(Visit(value));
297 }
298 }
299
300
301 void AstTyper::VisitAssignment(Assignment* expr) {
302 ASSERT(!HasStackOverflow());
303 CHECK_ALIVE(Visit(expr->target()));
304 CHECK_ALIVE(Visit(expr->value()));
305
306 // TODO(rossberg): Can we clean this up?
307 if (expr->is_compound()) {
308 CHECK_ALIVE(Visit(expr->binary_operation()));
309
310 Expression* target = expr->target();
311 Property* prop = target->AsProperty();
312 if (prop != NULL) {
313 prop->RecordTypeFeedback(oracle(), zone());
314 if (!prop->key()->IsPropertyName()) // i.e., keyed
315 expr->RecordTypeFeedback(oracle(), zone());
316 }
317 return;
318 }
319 if (expr->target()->AsProperty())
320 expr->RecordTypeFeedback(oracle(), zone());
321 }
322
323
324 void AstTyper::VisitYield(Yield* expr) {
325 ASSERT(!HasStackOverflow());
326 CHECK_ALIVE(Visit(expr->generator_object()));
327 CHECK_ALIVE(Visit(expr->expression()));
328 }
329
330
331 void AstTyper::VisitThrow(Throw* expr) {
332 ASSERT(!HasStackOverflow());
333 CHECK_ALIVE(Visit(expr->exception()));
334 }
335
336
337 void AstTyper::VisitProperty(Property* expr) {
338 ASSERT(!HasStackOverflow());
339 CHECK_ALIVE(Visit(expr->obj()));
340 CHECK_ALIVE(Visit(expr->key()));
341
342 expr->RecordTypeFeedback(oracle(), zone());
343 }
344
345
346 void AstTyper::VisitCall(Call* expr) {
347 ASSERT(!HasStackOverflow());
348 CHECK_ALIVE(Visit(expr->expression()));
349 ZoneList<Expression*>* args = expr->arguments();
350 for (int i = 0; i < args->length(); ++i) {
351 Expression* arg = args->at(i);
352 CHECK_ALIVE(Visit(arg));
353 }
354
355 Expression* callee = expr->expression();
356 Property* prop = callee->AsProperty();
357 if (prop != NULL) {
358 if (prop->key()->IsPropertyName())
359 expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD);
360 } else {
361 expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION);
362 }
363 }
364
365
366 void AstTyper::VisitCallNew(CallNew* expr) {
367 ASSERT(!HasStackOverflow());
368 CHECK_ALIVE(Visit(expr->expression()));
369 ZoneList<Expression*>* args = expr->arguments();
370 for (int i = 0; i < args->length(); ++i) {
371 Expression* arg = args->at(i);
372 CHECK_ALIVE(Visit(arg));
373 }
374
375 expr->RecordTypeFeedback(oracle());
376 }
377
378
379 void AstTyper::VisitCallRuntime(CallRuntime* expr) {
380 ASSERT(!HasStackOverflow());
381 ZoneList<Expression*>* args = expr->arguments();
382 for (int i = 0; i < args->length(); ++i) {
383 Expression* arg = args->at(i);
384 CHECK_ALIVE(Visit(arg));
385 }
386 }
387
388
389 void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
390 ASSERT(!HasStackOverflow());
391 CHECK_ALIVE(Visit(expr->expression()));
392
393 expr->RecordTypeFeedback(oracle());
394 if (expr->op() == Token::NOT) {
395 // TODO(rossberg): only do in test or value context.
396 expr->expression()->RecordToBooleanTypeFeedback(oracle());
397 }
398 }
399
400
401 void AstTyper::VisitCountOperation(CountOperation* expr) {
402 ASSERT(!HasStackOverflow());
403 CHECK_ALIVE(Visit(expr->expression()));
404
405 expr->RecordTypeFeedback(oracle(), zone());
406 Property* prop = expr->expression()->AsProperty();
407 if (prop != NULL) {
408 prop->RecordTypeFeedback(oracle(), zone());
409 }
410 }
411
412
413 void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
414 ASSERT(!HasStackOverflow());
415 CHECK_ALIVE(Visit(expr->left()));
416 CHECK_ALIVE(Visit(expr->right()));
417
418 expr->RecordTypeFeedback(oracle());
419 if (expr->op() == Token::OR || expr->op() == Token::AND) {
420 expr->left()->RecordToBooleanTypeFeedback(oracle());
421 }
422 }
423
424
425 void AstTyper::VisitCompareOperation(CompareOperation* expr) {
426 ASSERT(!HasStackOverflow());
427 CHECK_ALIVE(Visit(expr->left()));
428 CHECK_ALIVE(Visit(expr->right()));
429
430 expr->RecordTypeFeedback(oracle());
431 }
432
433
434 void AstTyper::VisitThisFunction(ThisFunction* expr) {
435 ASSERT(!HasStackOverflow());
436 }
437
438
439 void AstTyper::VisitDeclarations(ZoneList<Declaration*>* decls) {
440 ASSERT(!HasStackOverflow());
441 for (int i = 0; i < decls->length(); ++i) {
442 Declaration* decl = decls->at(i);
443 CHECK_ALIVE(Visit(decl));
444 }
445 }
446
447
448 void AstTyper::VisitVariableDeclaration(VariableDeclaration* declaration) {
449 ASSERT(!HasStackOverflow());
450 }
451
452
453 void AstTyper::VisitFunctionDeclaration(FunctionDeclaration* declaration) {
454 ASSERT(!HasStackOverflow());
455 CHECK_ALIVE(Visit(declaration->fun()));
456 }
457
458
459 void AstTyper::VisitModuleDeclaration(ModuleDeclaration* declaration) {
460 ASSERT(!HasStackOverflow());
461 CHECK_ALIVE(Visit(declaration->module()));
462 }
463
464
465 void AstTyper::VisitImportDeclaration(ImportDeclaration* declaration) {
466 ASSERT(!HasStackOverflow());
467 CHECK_ALIVE(Visit(declaration->module()));
468 }
469
470
471 void AstTyper::VisitExportDeclaration(ExportDeclaration* declaration) {
472 ASSERT(!HasStackOverflow());
473 }
474
475
476 void AstTyper::VisitModuleLiteral(ModuleLiteral* module) {
477 ASSERT(!HasStackOverflow());
478 CHECK_ALIVE(Visit(module->body()));
479 }
480
481
482 void AstTyper::VisitModuleVariable(ModuleVariable* module) {
483 ASSERT(!HasStackOverflow());
484 }
485
486
487 void AstTyper::VisitModulePath(ModulePath* module) {
488 ASSERT(!HasStackOverflow());
489 CHECK_ALIVE(Visit(module->module()));
490 }
491
492
493 void AstTyper::VisitModuleUrl(ModuleUrl* module) {
494 ASSERT(!HasStackOverflow());
495 }
496
497
498 void AstTyper::VisitModuleStatement(ModuleStatement* stmt) {
499 ASSERT(!HasStackOverflow());
500 CHECK_ALIVE(Visit(stmt->body()));
501 }
502
503
504 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/typing.h ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698