Line data Source code
1 : // Copyright 2013 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/crankshaft/typing.h"
6 :
7 : #include "src/ast/compile-time-value.h"
8 : #include "src/ast/scopes.h"
9 : #include "src/ast/variables.h"
10 : #include "src/frames-inl.h"
11 : #include "src/frames.h"
12 : #include "src/ostreams.h"
13 : #include "src/splay-tree-inl.h"
14 :
15 : namespace v8 {
16 : namespace internal {
17 :
18 370868 : AstTyper::AstTyper(Isolate* isolate, Zone* zone, Handle<JSFunction> closure,
19 : DeclarationScope* scope, BailoutId osr_ast_id,
20 : FunctionLiteral* root, AstTypeBounds* bounds)
21 : : isolate_(isolate),
22 : zone_(zone),
23 : closure_(closure),
24 : scope_(scope),
25 : osr_ast_id_(osr_ast_id),
26 : root_(root),
27 : oracle_(isolate, zone, handle(closure->shared()->code()),
28 : handle(closure->feedback_vector()),
29 : handle(closure->context()->native_context())),
30 : store_(zone),
31 1112606 : bounds_(bounds) {
32 : InitializeAstVisitor(isolate);
33 370869 : }
34 :
35 :
36 : #ifdef OBJECT_PRINT
37 : static void PrintObserved(Variable* var, Object* value, AstType* type) {
38 : OFStream os(stdout);
39 : os << " observed " << (var->IsParameter() ? "param" : "local") << " ";
40 : var->name()->Print(os);
41 : os << " : " << Brief(value) << " -> ";
42 : type->PrintTo(os);
43 : os << std::endl;
44 : }
45 : #endif // OBJECT_PRINT
46 :
47 :
48 10853 : Effect AstTyper::ObservedOnStack(Object* value) {
49 10853 : AstType* lower = AstType::NowOf(value, zone());
50 0 : return Effect(AstBounds(lower, AstType::Any()));
51 : }
52 :
53 :
54 46377 : void AstTyper::ObserveTypesAtOsrEntry(IterationStatement* stmt) {
55 90321 : if (stmt->OsrEntryId() != osr_ast_id_) return;
56 :
57 : DisallowHeapAllocation no_gc;
58 2433 : JavaScriptFrameIterator it(isolate_);
59 : JavaScriptFrame* frame = it.frame();
60 :
61 : // Assert that the frame on the stack belongs to the function we want to OSR.
62 : DCHECK_EQ(*closure_, frame->function());
63 :
64 2433 : int params = scope_->num_parameters();
65 2433 : int locals = scope_->StackLocalCount();
66 :
67 : // Use sequential composition to achieve desired narrowing.
68 : // The receiver is a parameter with index -1.
69 4866 : store_.Seq(parameter_index(-1), ObservedOnStack(frame->receiver()));
70 3781 : for (int i = 0; i < params; i++) {
71 2696 : store_.Seq(parameter_index(i), ObservedOnStack(frame->GetParameter(i)));
72 : }
73 :
74 7072 : for (int i = 0; i < locals; i++) {
75 14144 : store_.Seq(stack_local_index(i), ObservedOnStack(frame->GetExpression(i)));
76 : }
77 :
78 : #ifdef OBJECT_PRINT
79 : if (FLAG_trace_osr && FLAG_print_scopes) {
80 : PrintObserved(scope_->receiver(), frame->receiver(),
81 : store_.LookupBounds(parameter_index(-1)).lower);
82 :
83 : for (int i = 0; i < params; i++) {
84 : PrintObserved(scope_->parameter(i), frame->GetParameter(i),
85 : store_.LookupBounds(parameter_index(i)).lower);
86 : }
87 :
88 : int local_index = 0;
89 : for (Variable* var : *scope_->locals()) {
90 : if (var->IsStackLocal()) {
91 : PrintObserved(
92 : var, frame->GetExpression(local_index),
93 : store_.LookupBounds(stack_local_index(local_index)).lower);
94 : local_index++;
95 : }
96 : }
97 : }
98 : #endif // OBJECT_PRINT
99 : }
100 :
101 :
102 : #define RECURSE(call) \
103 : do { \
104 : DCHECK(!HasStackOverflow()); \
105 : call; \
106 : if (HasStackOverflow()) return; \
107 : } while (false)
108 :
109 :
110 741738 : void AstTyper::Run() {
111 741738 : RECURSE(VisitDeclarations(scope_->declarations()));
112 370869 : RECURSE(VisitStatements(root_->body()));
113 : }
114 :
115 :
116 3159728 : void AstTyper::VisitStatements(ZoneList<Statement*>* stmts) {
117 5534552 : for (int i = 0; i < stmts->length(); ++i) {
118 4837854 : Statement* stmt = stmts->at(i);
119 5230306 : RECURSE(Visit(stmt));
120 2070577 : if (stmt->IsJump()) break;
121 : }
122 : }
123 :
124 :
125 1377530 : void AstTyper::VisitBlock(Block* stmt) {
126 2066295 : RECURSE(VisitStatements(stmt->statements()));
127 688765 : if (stmt->labels() != NULL) {
128 85 : store_.Forget(); // Control may transfer here via 'break l'.
129 : }
130 : }
131 :
132 :
133 917717 : void AstTyper::VisitExpressionStatement(ExpressionStatement* stmt) {
134 917717 : RECURSE(Visit(stmt->expression()));
135 : }
136 :
137 :
138 0 : void AstTyper::VisitEmptyStatement(EmptyStatement* stmt) {
139 0 : }
140 :
141 :
142 407 : void AstTyper::VisitSloppyBlockFunctionStatement(
143 407 : SloppyBlockFunctionStatement* stmt) {
144 407 : Visit(stmt->statement());
145 407 : }
146 :
147 :
148 3735298 : void AstTyper::VisitIfStatement(IfStatement* stmt) {
149 : // Collect type feedback.
150 830143 : if (!stmt->condition()->ToBooleanIsTrue() &&
151 415055 : !stmt->condition()->ToBooleanIsFalse()) {
152 829254 : stmt->condition()->RecordToBooleanTypeFeedback(oracle());
153 : }
154 :
155 830176 : RECURSE(Visit(stmt->condition()));
156 415088 : Effects then_effects = EnterEffects();
157 830176 : RECURSE(Visit(stmt->then_statement()));
158 : ExitEffects();
159 415088 : Effects else_effects = EnterEffects();
160 830176 : RECURSE(Visit(stmt->else_statement()));
161 : ExitEffects();
162 415088 : then_effects.Alt(else_effects);
163 : store_.Seq(then_effects);
164 : }
165 :
166 :
167 0 : void AstTyper::VisitContinueStatement(ContinueStatement* stmt) {
168 : // TODO(rossberg): is it worth having a non-termination effect?
169 0 : }
170 :
171 :
172 0 : void AstTyper::VisitBreakStatement(BreakStatement* stmt) {
173 : // TODO(rossberg): is it worth having a non-termination effect?
174 0 : }
175 :
176 :
177 1650864 : void AstTyper::VisitReturnStatement(ReturnStatement* stmt) {
178 : // Collect type feedback.
179 : // TODO(rossberg): we only need this for inlining into test contexts...
180 1100576 : stmt->expression()->RecordToBooleanTypeFeedback(oracle());
181 :
182 550288 : RECURSE(Visit(stmt->expression()));
183 : // TODO(rossberg): is it worth having a non-termination effect?
184 : }
185 :
186 :
187 0 : void AstTyper::VisitWithStatement(WithStatement* stmt) {
188 : RECURSE(stmt->expression());
189 : RECURSE(stmt->statement());
190 : }
191 :
192 :
193 99487 : void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) {
194 9146 : RECURSE(Visit(stmt->tag()));
195 :
196 : ZoneList<CaseClause*>* clauses = stmt->cases();
197 : Effects local_effects(zone());
198 : bool complex_effects = false; // True for label effects or fall-through.
199 :
200 68178 : for (int i = 0; i < clauses->length(); ++i) {
201 122637 : CaseClause* clause = clauses->at(i);
202 :
203 : Effects clause_effects = EnterEffects();
204 :
205 29516 : if (!clause->is_default()) {
206 28126 : Expression* label = clause->label();
207 : // Collect type feedback.
208 : AstType* tag_type;
209 : AstType* label_type;
210 : AstType* combined_type;
211 : oracle()->CompareType(clause->CompareId(),
212 : clause->CompareOperationFeedbackSlot(), &tag_type,
213 28126 : &label_type, &combined_type);
214 56252 : NarrowLowerType(stmt->tag(), tag_type);
215 28126 : NarrowLowerType(label, label_type);
216 28126 : clause->set_compare_type(combined_type);
217 :
218 56252 : RECURSE(Visit(label));
219 28126 : if (!clause_effects.IsEmpty()) complex_effects = true;
220 : }
221 :
222 : ZoneList<Statement*>* stmts = clause->statements();
223 59032 : RECURSE(VisitStatements(stmts));
224 : ExitEffects();
225 52034 : if (stmts->is_empty() || stmts->last()->IsJump()) {
226 28651 : local_effects.Alt(clause_effects);
227 : } else {
228 : complex_effects = true;
229 : }
230 : }
231 :
232 4573 : if (complex_effects) {
233 609 : store_.Forget(); // Reached this in unknown state.
234 : } else {
235 : store_.Seq(local_effects);
236 : }
237 : }
238 :
239 :
240 0 : void AstTyper::VisitCaseClause(CaseClause* clause) {
241 0 : UNREACHABLE();
242 : }
243 :
244 :
245 3061 : void AstTyper::VisitDoWhileStatement(DoWhileStatement* stmt) {
246 : // Collect type feedback.
247 626 : if (!stmt->cond()->ToBooleanIsTrue()) {
248 1114 : stmt->cond()->RecordToBooleanTypeFeedback(oracle());
249 : }
250 :
251 : // TODO(rossberg): refine the unconditional Forget (here and elsewhere) by
252 : // computing the set of variables assigned in only some of the origins of the
253 : // control transfer (such as the loop body here).
254 626 : store_.Forget(); // Control may transfer here via looping or 'continue'.
255 626 : ObserveTypesAtOsrEntry(stmt);
256 1252 : RECURSE(Visit(stmt->body()));
257 1252 : RECURSE(Visit(stmt->cond()));
258 626 : store_.Forget(); // Control may transfer here via 'break'.
259 : }
260 :
261 :
262 19484 : void AstTyper::VisitWhileStatement(WhileStatement* stmt) {
263 : // Collect type feedback.
264 4225 : if (!stmt->cond()->ToBooleanIsTrue()) {
265 5168 : stmt->cond()->RecordToBooleanTypeFeedback(oracle());
266 : }
267 :
268 4225 : store_.Forget(); // Control may transfer here via looping or 'continue'.
269 8450 : RECURSE(Visit(stmt->cond()));
270 4225 : ObserveTypesAtOsrEntry(stmt);
271 8450 : RECURSE(Visit(stmt->body()));
272 4225 : store_.Forget(); // Control may transfer here via termination or 'break'.
273 : }
274 :
275 :
276 354783 : void AstTyper::VisitForStatement(ForStatement* stmt) {
277 40380 : if (stmt->init() != NULL) {
278 75318 : RECURSE(Visit(stmt->init()));
279 : }
280 40380 : store_.Forget(); // Control may transfer here via looping.
281 40380 : if (stmt->cond() != NULL) {
282 : // Collect type feedback.
283 39383 : stmt->cond()->RecordToBooleanTypeFeedback(oracle());
284 :
285 78766 : RECURSE(Visit(stmt->cond()));
286 : }
287 40380 : ObserveTypesAtOsrEntry(stmt);
288 80760 : RECURSE(Visit(stmt->body()));
289 40380 : if (stmt->next() != NULL) {
290 38419 : store_.Forget(); // Control may transfer here via 'continue'.
291 76838 : RECURSE(Visit(stmt->next()));
292 : }
293 40380 : store_.Forget(); // Control may transfer here via termination or 'break'.
294 : }
295 :
296 :
297 3438 : void AstTyper::VisitForInStatement(ForInStatement* stmt) {
298 : // Collect type feedback.
299 : stmt->set_for_in_type(static_cast<ForInStatement::ForInType>(
300 1146 : oracle()->ForInType(stmt->ForInFeedbackSlot())));
301 :
302 2292 : RECURSE(Visit(stmt->enumerable()));
303 1146 : store_.Forget(); // Control may transfer here via looping or 'continue'.
304 1146 : ObserveTypesAtOsrEntry(stmt);
305 2292 : RECURSE(Visit(stmt->body()));
306 1146 : store_.Forget(); // Control may transfer here via 'break'.
307 : }
308 :
309 0 : void AstTyper::VisitForOfStatement(ForOfStatement* stmt) {}
310 :
311 0 : void AstTyper::VisitTryCatchStatement(TryCatchStatement* stmt) {
312 0 : Effects try_effects = EnterEffects();
313 0 : RECURSE(Visit(stmt->try_block()));
314 : ExitEffects();
315 0 : Effects catch_effects = EnterEffects();
316 0 : store_.Forget(); // Control may transfer here via 'throw'.
317 0 : RECURSE(Visit(stmt->catch_block()));
318 : ExitEffects();
319 0 : try_effects.Alt(catch_effects);
320 : store_.Seq(try_effects);
321 : // At this point, only variables that were reassigned in the catch block are
322 : // still remembered.
323 : }
324 :
325 :
326 0 : void AstTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
327 0 : RECURSE(Visit(stmt->try_block()));
328 0 : store_.Forget(); // Control may transfer here via 'throw'.
329 0 : RECURSE(Visit(stmt->finally_block()));
330 : }
331 :
332 :
333 0 : void AstTyper::VisitDebuggerStatement(DebuggerStatement* stmt) {
334 0 : store_.Forget(); // May do whatever.
335 0 : }
336 :
337 :
338 0 : void AstTyper::VisitFunctionLiteral(FunctionLiteral* expr) {}
339 :
340 :
341 0 : void AstTyper::VisitClassLiteral(ClassLiteral* expr) {}
342 :
343 :
344 0 : void AstTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
345 0 : }
346 :
347 :
348 310 : void AstTyper::VisitDoExpression(DoExpression* expr) {
349 124 : RECURSE(VisitBlock(expr->block()));
350 124 : RECURSE(VisitVariableProxy(expr->result()));
351 62 : NarrowType(expr, bounds_->get(expr->result()));
352 : }
353 :
354 :
355 93850 : void AstTyper::VisitConditional(Conditional* expr) {
356 : // Collect type feedback.
357 18770 : expr->condition()->RecordToBooleanTypeFeedback(oracle());
358 :
359 18770 : RECURSE(Visit(expr->condition()));
360 9385 : Effects then_effects = EnterEffects();
361 18770 : RECURSE(Visit(expr->then_expression()));
362 : ExitEffects();
363 9385 : Effects else_effects = EnterEffects();
364 18770 : RECURSE(Visit(expr->else_expression()));
365 : ExitEffects();
366 9385 : then_effects.Alt(else_effects);
367 : store_.Seq(then_effects);
368 :
369 : NarrowType(expr,
370 : AstBounds::Either(bounds_->get(expr->then_expression()),
371 18770 : bounds_->get(expr->else_expression()), zone()));
372 : }
373 :
374 :
375 3406470 : void AstTyper::VisitVariableProxy(VariableProxy* expr) {
376 : Variable* var = expr->var();
377 3406470 : if (var->IsStackAllocated()) {
378 2591704 : NarrowType(expr, store_.LookupBounds(variable_index(var)));
379 : }
380 3406470 : }
381 :
382 :
383 2775482 : void AstTyper::VisitLiteral(Literal* expr) {
384 : AstType* type = AstType::Constant(expr->value(), zone());
385 2775482 : NarrowType(expr, AstBounds(type));
386 2775484 : }
387 :
388 :
389 0 : void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) {
390 : // TODO(rossberg): Reintroduce RegExp type.
391 8679 : NarrowType(expr, AstBounds(AstType::Object()));
392 0 : }
393 :
394 :
395 199148 : void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) {
396 : ZoneList<ObjectLiteral::Property*>* properties = expr->properties();
397 398296 : for (int i = 0; i < properties->length(); ++i) {
398 500005 : ObjectLiteral::Property* prop = properties->at(i);
399 :
400 : // Collect type feedback.
401 173550 : if ((prop->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL &&
402 502324 : !CompileTimeValue::IsCompileTimeValue(prop->value())) ||
403 : prop->kind() == ObjectLiteral::Property::COMPUTED) {
404 50638 : if (!prop->is_computed_name() &&
405 101227 : prop->key()->AsLiteral()->value()->IsInternalizedString() &&
406 25270 : prop->emit_store()) {
407 : // Record type feed back for the property.
408 25246 : FeedbackSlot slot = prop->GetSlot();
409 : SmallMapList maps;
410 25246 : oracle()->CollectReceiverTypes(slot, &maps);
411 : prop->set_receiver_type(maps.length() == 1 ? maps.at(0)
412 25246 : : Handle<Map>::null());
413 : }
414 : }
415 :
416 349979 : RECURSE(Visit(prop->value()));
417 : }
418 :
419 48319 : NarrowType(expr, AstBounds(AstType::Object()));
420 : }
421 :
422 :
423 986421 : void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) {
424 : ZoneList<Expression*>* values = expr->values();
425 1972842 : for (int i = 0; i < values->length(); ++i) {
426 1948496 : Expression* value = values->at(i);
427 1948496 : RECURSE(Visit(value));
428 : }
429 :
430 24346 : NarrowType(expr, AstBounds(AstType::Object()));
431 : }
432 :
433 :
434 2556767 : void AstTyper::VisitAssignment(Assignment* expr) {
435 : // Collect type feedback.
436 662770 : Property* prop = expr->target()->AsProperty();
437 632303 : if (prop != NULL) {
438 72284 : FeedbackSlot slot = expr->AssignmentSlot();
439 72284 : expr->set_is_uninitialized(oracle()->StoreIsUninitialized(slot));
440 72284 : if (!expr->IsUninitialized()) {
441 17723 : SmallMapList* receiver_types = expr->GetReceiverTypes();
442 17723 : if (prop->key()->IsPropertyName()) {
443 25488 : Literal* lit_key = prop->key()->AsLiteral();
444 : DCHECK(lit_key != NULL && lit_key->value()->IsString());
445 : Handle<String> name = Handle<String>::cast(lit_key->value());
446 12744 : oracle()->AssignmentReceiverTypes(slot, name, receiver_types);
447 : } else {
448 : KeyedAccessStoreMode store_mode;
449 : IcCheckType key_type;
450 : oracle()->KeyedAssignmentReceiverTypes(slot, receiver_types,
451 4979 : &store_mode, &key_type);
452 4979 : expr->set_store_mode(store_mode);
453 4979 : expr->set_key_type(key_type);
454 : }
455 : }
456 : }
457 :
458 : Expression* rhs =
459 632303 : expr->is_compound() ? expr->binary_operation() : expr->value();
460 1264606 : RECURSE(Visit(expr->target()));
461 1264606 : RECURSE(Visit(rhs));
462 632303 : NarrowType(expr, bounds_->get(rhs));
463 :
464 1693695 : VariableProxy* proxy = expr->target()->AsVariableProxy();
465 1192322 : if (proxy != NULL && proxy->var()->IsStackAllocated()) {
466 1002746 : store_.Seq(variable_index(proxy->var()), Effect(bounds_->get(expr)));
467 : }
468 : }
469 :
470 0 : void AstTyper::VisitSuspend(Suspend* expr) {
471 0 : RECURSE(Visit(expr->generator_object()));
472 0 : RECURSE(Visit(expr->expression()));
473 :
474 : // We don't know anything about the result type.
475 : }
476 :
477 :
478 14268 : void AstTyper::VisitThrow(Throw* expr) {
479 21402 : RECURSE(Visit(expr->exception()));
480 : // TODO(rossberg): is it worth having a non-termination effect?
481 :
482 7134 : NarrowType(expr, AstBounds(AstType::None()));
483 : }
484 :
485 :
486 3697040 : void AstTyper::VisitProperty(Property* expr) {
487 : // Collect type feedback.
488 600528 : FeedbackSlot slot = expr->PropertyFeedbackSlot();
489 600528 : expr->set_inline_cache_state(oracle()->LoadInlineCacheState(slot));
490 :
491 600528 : if (!expr->IsUninitialized()) {
492 367227 : if (expr->key()->IsPropertyName()) {
493 654350 : Literal* lit_key = expr->key()->AsLiteral();
494 : DCHECK(lit_key != NULL && lit_key->value()->IsString());
495 : Handle<String> name = Handle<String>::cast(lit_key->value());
496 654350 : oracle()->PropertyReceiverTypes(slot, name, expr->GetReceiverTypes());
497 : } else {
498 : bool is_string;
499 : IcCheckType key_type;
500 : oracle()->KeyedPropertyReceiverTypes(slot, expr->GetReceiverTypes(),
501 40052 : &is_string, &key_type);
502 40052 : expr->set_is_string_access(is_string);
503 40052 : expr->set_key_type(key_type);
504 : }
505 : }
506 :
507 1201055 : RECURSE(Visit(expr->obj()));
508 1201055 : RECURSE(Visit(expr->key()));
509 :
510 : // We don't know anything about the result type.
511 : }
512 :
513 :
514 4233216 : void AstTyper::VisitCall(Call* expr) {
515 : // Collect type feedback.
516 1309844 : RECURSE(Visit(expr->expression()));
517 654922 : FeedbackSlot slot = expr->CallFeedbackICSlot();
518 654922 : bool is_uninitialized = oracle()->CallIsUninitialized(slot);
519 654922 : if (!expr->expression()->IsProperty() && oracle()->CallIsMonomorphic(slot)) {
520 73280 : expr->set_target(oracle()->GetCallTarget(slot));
521 73280 : Handle<AllocationSite> site = oracle()->GetCallAllocationSite(slot);
522 : expr->set_allocation_site(site);
523 : }
524 :
525 : expr->set_is_uninitialized(is_uninitialized);
526 :
527 : ZoneList<Expression*>* args = expr->arguments();
528 3227056 : for (int i = 0; i < args->length(); ++i) {
529 2572134 : Expression* arg = args->at(i);
530 1917212 : RECURSE(Visit(arg));
531 : }
532 :
533 654922 : if (expr->is_possibly_eval()) {
534 0 : store_.Forget(); // Eval could do whatever to local variables.
535 : }
536 :
537 : // We don't know anything about the result type.
538 : }
539 :
540 :
541 167856 : void AstTyper::VisitCallNew(CallNew* expr) {
542 : // Collect type feedback.
543 32165 : FeedbackSlot allocation_site_feedback_slot = expr->CallNewFeedbackSlot();
544 : expr->set_allocation_site(
545 32165 : oracle()->GetCallNewAllocationSite(allocation_site_feedback_slot));
546 : bool monomorphic =
547 32165 : oracle()->CallNewIsMonomorphic(expr->CallNewFeedbackSlot());
548 : expr->set_is_monomorphic(monomorphic);
549 32165 : if (monomorphic) {
550 4923 : expr->set_target(oracle()->GetCallNewTarget(expr->CallNewFeedbackSlot()));
551 : }
552 :
553 64330 : RECURSE(Visit(expr->expression()));
554 : ZoneList<Expression*>* args = expr->arguments();
555 142722 : for (int i = 0; i < args->length(); ++i) {
556 110557 : Expression* arg = args->at(i);
557 78392 : RECURSE(Visit(arg));
558 : }
559 :
560 32165 : NarrowType(expr, AstBounds(AstType::None(), AstType::Receiver()));
561 : }
562 :
563 :
564 229281 : void AstTyper::VisitCallRuntime(CallRuntime* expr) {
565 : ZoneList<Expression*>* args = expr->arguments();
566 458562 : for (int i = 0; i < args->length(); ++i) {
567 377983 : Expression* arg = args->at(i);
568 377983 : RECURSE(Visit(arg));
569 : }
570 :
571 : // We don't know anything about the result type.
572 : }
573 :
574 :
575 1543790 : void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
576 : // Collect type feedback.
577 332521 : if (expr->op() == Token::NOT) {
578 : // TODO(rossberg): only do in test or value context.
579 427412 : expr->expression()->RecordToBooleanTypeFeedback(oracle());
580 : }
581 :
582 997563 : RECURSE(Visit(expr->expression()));
583 :
584 332521 : switch (expr->op()) {
585 : case Token::NOT:
586 : case Token::DELETE:
587 215028 : NarrowType(expr, AstBounds(AstType::Boolean()));
588 215028 : break;
589 : case Token::VOID:
590 11056 : NarrowType(expr, AstBounds(AstType::Undefined()));
591 11056 : break;
592 : case Token::TYPEOF:
593 106437 : NarrowType(expr, AstBounds(AstType::InternalizedString()));
594 106437 : break;
595 : default:
596 0 : UNREACHABLE();
597 : }
598 : }
599 :
600 :
601 183692 : void AstTyper::VisitCountOperation(CountOperation* expr) {
602 : // Collect type feedback.
603 45923 : FeedbackSlot slot = expr->CountSlot();
604 : KeyedAccessStoreMode store_mode;
605 : IcCheckType key_type;
606 45923 : oracle()->GetStoreModeAndKeyType(slot, &store_mode, &key_type);
607 45923 : oracle()->CountReceiverTypes(slot, expr->GetReceiverTypes());
608 45923 : expr->set_store_mode(store_mode);
609 45923 : expr->set_key_type(key_type);
610 : expr->set_type(oracle()->CountType(expr->CountBinOpFeedbackId(),
611 45923 : expr->CountBinaryOpFeedbackSlot()));
612 : // TODO(rossberg): merge the count type with the generic expression type.
613 :
614 91846 : RECURSE(Visit(expr->expression()));
615 :
616 45923 : NarrowType(expr, AstBounds(AstType::SignedSmall(), AstType::Number()));
617 :
618 128623 : VariableProxy* proxy = expr->expression()->AsVariableProxy();
619 90254 : if (proxy != NULL && proxy->var()->IsStackAllocated()) {
620 76738 : store_.Seq(variable_index(proxy->var()), Effect(bounds_->get(expr)));
621 : }
622 : }
623 :
624 6051459 : void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
625 : // Collect type feedback.
626 : AstType* type;
627 : AstType* left_type;
628 : AstType* right_type;
629 1031414 : Maybe<int> fixed_right_arg = Nothing<int>();
630 : Handle<AllocationSite> allocation_site;
631 : oracle()->BinaryType(expr->BinaryOperationFeedbackId(),
632 : expr->BinaryOperationFeedbackSlot(), &left_type,
633 : &right_type, &type, &fixed_right_arg, &allocation_site,
634 515707 : expr->op());
635 :
636 515707 : NarrowLowerType(expr, type);
637 1031414 : NarrowLowerType(expr->left(), left_type);
638 1031414 : NarrowLowerType(expr->right(), right_type);
639 : expr->set_allocation_site(allocation_site);
640 : expr->set_fixed_right_arg(fixed_right_arg);
641 515707 : if (expr->op() == Token::OR || expr->op() == Token::AND) {
642 122556 : expr->left()->RecordToBooleanTypeFeedback(oracle());
643 : }
644 :
645 515707 : switch (expr->op()) {
646 : case Token::COMMA:
647 13493 : RECURSE(Visit(expr->left()));
648 12992 : RECURSE(Visit(expr->right()));
649 6496 : NarrowType(expr, bounds_->get(expr->right()));
650 6496 : break;
651 : case Token::OR:
652 : case Token::AND: {
653 122556 : Effects left_effects = EnterEffects();
654 245112 : RECURSE(Visit(expr->left()));
655 : ExitEffects();
656 122556 : Effects right_effects = EnterEffects();
657 245112 : RECURSE(Visit(expr->right()));
658 : ExitEffects();
659 122556 : left_effects.Alt(right_effects);
660 : store_.Seq(left_effects);
661 :
662 : NarrowType(expr, AstBounds::Either(bounds_->get(expr->left()),
663 245112 : bounds_->get(expr->right()), zone()));
664 122556 : break;
665 : }
666 : case Token::BIT_OR:
667 : case Token::BIT_AND: {
668 81154 : RECURSE(Visit(expr->left()));
669 81154 : RECURSE(Visit(expr->right()));
670 : AstType* upper =
671 40577 : AstType::Union(bounds_->get(expr->left()).upper,
672 81154 : bounds_->get(expr->right()).upper, zone());
673 40577 : if (!upper->Is(AstType::Signed32())) upper = AstType::Signed32();
674 : AstType* lower =
675 40577 : AstType::Intersect(AstType::SignedSmall(), upper, zone());
676 40577 : NarrowType(expr, AstBounds(lower, upper));
677 40577 : break;
678 : }
679 : case Token::BIT_XOR:
680 : case Token::SHL:
681 : case Token::SAR:
682 52790 : RECURSE(Visit(expr->left()));
683 52790 : RECURSE(Visit(expr->right()));
684 26395 : NarrowType(expr, AstBounds(AstType::SignedSmall(), AstType::Signed32()));
685 26395 : break;
686 : case Token::SHR:
687 15944 : RECURSE(Visit(expr->left()));
688 15944 : RECURSE(Visit(expr->right()));
689 : // TODO(rossberg): The upper bound would be Unsigned32, but since there
690 : // is no 'positive Smi' type for the lower bound, we use the smallest
691 : // union of Smi and Unsigned32 as upper bound instead.
692 7972 : NarrowType(expr, AstBounds(AstType::SignedSmall(), AstType::Number()));
693 7972 : break;
694 : case Token::ADD: {
695 400498 : RECURSE(Visit(expr->left()));
696 399496 : RECURSE(Visit(expr->right()));
697 199748 : AstBounds l = bounds_->get(expr->left());
698 199748 : AstBounds r = bounds_->get(expr->right());
699 : AstType* lower =
700 376062 : !l.lower->IsInhabited() || !r.lower->IsInhabited()
701 : ? AstType::None()
702 144613 : : l.lower->Is(AstType::String()) || r.lower->Is(AstType::String())
703 : ? AstType::String()
704 143639 : : l.lower->Is(AstType::Number()) &&
705 : r.lower->Is(AstType::Number())
706 : ? AstType::SignedSmall()
707 655504 : : AstType::None();
708 : AstType* upper =
709 160534 : l.upper->Is(AstType::String()) || r.upper->Is(AstType::String())
710 : ? AstType::String()
711 34668 : : l.upper->Is(AstType::Number()) && r.upper->Is(AstType::Number())
712 : ? AstType::Number()
713 355824 : : AstType::NumberOrString();
714 199748 : NarrowType(expr, AstBounds(lower, upper));
715 : break;
716 : }
717 : case Token::SUB:
718 : case Token::MUL:
719 : case Token::DIV:
720 : case Token::MOD:
721 222924 : RECURSE(Visit(expr->left()));
722 222924 : RECURSE(Visit(expr->right()));
723 111462 : NarrowType(expr, AstBounds(AstType::SignedSmall(), AstType::Number()));
724 111462 : break;
725 : default:
726 0 : UNREACHABLE();
727 : }
728 : }
729 :
730 :
731 3536602 : void AstTyper::VisitCompareOperation(CompareOperation* expr) {
732 : // Collect type feedback.
733 : AstType* left_type;
734 : AstType* right_type;
735 : AstType* combined_type;
736 : oracle()->CompareType(expr->CompareOperationFeedbackId(),
737 : expr->CompareOperationFeedbackSlot(), &left_type,
738 505228 : &right_type, &combined_type);
739 1010458 : NarrowLowerType(expr->left(), left_type);
740 1010458 : NarrowLowerType(expr->right(), right_type);
741 505229 : expr->set_combined_type(combined_type);
742 :
743 1010458 : RECURSE(Visit(expr->left()));
744 1010458 : RECURSE(Visit(expr->right()));
745 :
746 505229 : NarrowType(expr, AstBounds(AstType::Boolean()));
747 : }
748 :
749 :
750 0 : void AstTyper::VisitSpread(Spread* expr) { UNREACHABLE(); }
751 :
752 :
753 0 : void AstTyper::VisitEmptyParentheses(EmptyParentheses* expr) {
754 0 : UNREACHABLE();
755 : }
756 :
757 0 : void AstTyper::VisitGetIterator(GetIterator* expr) { UNREACHABLE(); }
758 :
759 0 : void AstTyper::VisitImportCallExpression(ImportCallExpression* expr) {
760 0 : UNREACHABLE();
761 : }
762 :
763 0 : void AstTyper::VisitThisFunction(ThisFunction* expr) {}
764 :
765 :
766 0 : void AstTyper::VisitSuperPropertyReference(SuperPropertyReference* expr) {}
767 :
768 :
769 0 : void AstTyper::VisitSuperCallReference(SuperCallReference* expr) {}
770 :
771 :
772 8 : void AstTyper::VisitRewritableExpression(RewritableExpression* expr) {
773 8 : Visit(expr->expression());
774 8 : }
775 :
776 3131445 : int AstTyper::variable_index(Variable* var) {
777 : // Stack locals have the range [0 .. l]
778 : // Parameters have the range [-1 .. p]
779 : // We map this to [-p-2 .. -1, 0 .. l]
780 : return var->IsStackLocal()
781 : ? stack_local_index(var->index())
782 4417095 : : var->IsParameter() ? parameter_index(var->index()) : kNoVar;
783 : }
784 :
785 830612 : void AstTyper::VisitDeclarations(Declaration::List* decls) {
786 1201481 : for (Declaration* decl : *decls) {
787 1290355 : RECURSE(Visit(decl));
788 : }
789 : }
790 :
791 :
792 0 : void AstTyper::VisitVariableDeclaration(VariableDeclaration* declaration) {
793 0 : }
794 :
795 :
796 33831 : void AstTyper::VisitFunctionDeclaration(FunctionDeclaration* declaration) {
797 33831 : RECURSE(Visit(declaration->fun()));
798 : }
799 :
800 :
801 : } // namespace internal
802 : } // namespace v8
|