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 371311 : 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 1113933 : bounds_(bounds) {
32 : InitializeAstVisitor(isolate);
33 371311 : }
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 10897 : Effect AstTyper::ObservedOnStack(Object* value) {
49 10897 : AstType* lower = AstType::NowOf(value, zone());
50 0 : return Effect(AstBounds(lower, AstType::Any()));
51 : }
52 :
53 :
54 46508 : void AstTyper::ObserveTypesAtOsrEntry(IterationStatement* stmt) {
55 90577 : if (stmt->OsrEntryId() != osr_ast_id_) return;
56 :
57 : DisallowHeapAllocation no_gc;
58 2439 : 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 2439 : int params = scope_->num_parameters();
65 2439 : int locals = scope_->StackLocalCount();
66 :
67 : // Use sequential composition to achieve desired narrowing.
68 : // The receiver is a parameter with index -1.
69 4878 : store_.Seq(parameter_index(-1), ObservedOnStack(frame->receiver()));
70 3790 : for (int i = 0; i < params; i++) {
71 2702 : store_.Seq(parameter_index(i), ObservedOnStack(frame->GetParameter(i)));
72 : }
73 :
74 7107 : for (int i = 0; i < locals; i++) {
75 14214 : 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 742622 : void AstTyper::Run() {
111 742622 : RECURSE(VisitDeclarations(scope_->declarations()));
112 371311 : RECURSE(VisitStatements(root_->body()));
113 : }
114 :
115 :
116 3162876 : void AstTyper::VisitStatements(ZoneList<Statement*>* stmts) {
117 5538966 : for (int i = 0; i < stmts->length(); ++i) {
118 4841262 : Statement* stmt = stmts->at(i);
119 5234655 : RECURSE(Visit(stmt));
120 2071778 : if (stmt->IsJump()) break;
121 : }
122 : }
123 :
124 :
125 1380206 : void AstTyper::VisitBlock(Block* stmt) {
126 2070309 : RECURSE(VisitStatements(stmt->statements()));
127 690103 : if (stmt->labels() != NULL) {
128 85 : store_.Forget(); // Control may transfer here via 'break l'.
129 : }
130 : }
131 :
132 :
133 916500 : void AstTyper::VisitExpressionStatement(ExpressionStatement* stmt) {
134 916500 : 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 3748250 : void AstTyper::VisitIfStatement(IfStatement* stmt) {
149 : // Collect type feedback.
150 833021 : if (!stmt->condition()->ToBooleanIsTrue() &&
151 416494 : !stmt->condition()->ToBooleanIsFalse()) {
152 832134 : stmt->condition()->RecordToBooleanTypeFeedback(oracle());
153 : }
154 :
155 833054 : RECURSE(Visit(stmt->condition()));
156 416527 : Effects then_effects = EnterEffects();
157 833054 : RECURSE(Visit(stmt->then_statement()));
158 : ExitEffects();
159 416527 : Effects else_effects = EnterEffects();
160 833054 : RECURSE(Visit(stmt->else_statement()));
161 : ExitEffects();
162 416527 : 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 1654458 : void AstTyper::VisitReturnStatement(ReturnStatement* stmt) {
178 : // Collect type feedback.
179 : // TODO(rossberg): we only need this for inlining into test contexts...
180 1102972 : stmt->expression()->RecordToBooleanTypeFeedback(oracle());
181 :
182 551486 : 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 100121 : void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) {
194 9232 : 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 68598 : for (int i = 0; i < clauses->length(); ++i) {
201 123348 : CaseClause* clause = clauses->at(i);
202 :
203 : Effects clause_effects = EnterEffects();
204 :
205 29683 : if (!clause->is_default()) {
206 28295 : 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 28295 : &label_type, &combined_type);
214 56590 : NarrowLowerType(stmt->tag(), tag_type);
215 28295 : NarrowLowerType(label, label_type);
216 28295 : clause->set_compare_type(combined_type);
217 :
218 56590 : RECURSE(Visit(label));
219 28295 : if (!clause_effects.IsEmpty()) complex_effects = true;
220 : }
221 :
222 : ZoneList<Statement*>* stmts = clause->statements();
223 59366 : RECURSE(VisitStatements(stmts));
224 : ExitEffects();
225 52368 : if (stmts->is_empty() || stmts->last()->IsJump()) {
226 28820 : local_effects.Alt(clause_effects);
227 : } else {
228 : complex_effects = true;
229 : }
230 : }
231 :
232 4616 : if (complex_effects) {
233 607 : 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 3050 : void AstTyper::VisitDoWhileStatement(DoWhileStatement* stmt) {
246 : // Collect type feedback.
247 624 : if (!stmt->cond()->ToBooleanIsTrue()) {
248 1108 : 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 624 : store_.Forget(); // Control may transfer here via looping or 'continue'.
255 624 : ObserveTypesAtOsrEntry(stmt);
256 1248 : RECURSE(Visit(stmt->body()));
257 1248 : RECURSE(Visit(stmt->cond()));
258 624 : store_.Forget(); // Control may transfer here via 'break'.
259 : }
260 :
261 :
262 19738 : void AstTyper::VisitWhileStatement(WhileStatement* stmt) {
263 : // Collect type feedback.
264 4279 : if (!stmt->cond()->ToBooleanIsTrue()) {
265 5244 : stmt->cond()->RecordToBooleanTypeFeedback(oracle());
266 : }
267 :
268 4279 : store_.Forget(); // Control may transfer here via looping or 'continue'.
269 8558 : RECURSE(Visit(stmt->cond()));
270 4279 : ObserveTypesAtOsrEntry(stmt);
271 8558 : RECURSE(Visit(stmt->body()));
272 4279 : store_.Forget(); // Control may transfer here via termination or 'break'.
273 : }
274 :
275 :
276 355543 : void AstTyper::VisitForStatement(ForStatement* stmt) {
277 40465 : if (stmt->init() != NULL) {
278 75482 : RECURSE(Visit(stmt->init()));
279 : }
280 40465 : store_.Forget(); // Control may transfer here via looping.
281 40465 : if (stmt->cond() != NULL) {
282 : // Collect type feedback.
283 39468 : stmt->cond()->RecordToBooleanTypeFeedback(oracle());
284 :
285 78936 : RECURSE(Visit(stmt->cond()));
286 : }
287 40465 : ObserveTypesAtOsrEntry(stmt);
288 80930 : RECURSE(Visit(stmt->body()));
289 40465 : if (stmt->next() != NULL) {
290 38503 : store_.Forget(); // Control may transfer here via 'continue'.
291 77006 : RECURSE(Visit(stmt->next()));
292 : }
293 40465 : store_.Forget(); // Control may transfer here via termination or 'break'.
294 : }
295 :
296 :
297 3420 : void AstTyper::VisitForInStatement(ForInStatement* stmt) {
298 : // Collect type feedback.
299 : stmt->set_for_in_type(static_cast<ForInStatement::ForInType>(
300 1140 : oracle()->ForInType(stmt->ForInFeedbackSlot())));
301 :
302 2280 : RECURSE(Visit(stmt->enumerable()));
303 1140 : store_.Forget(); // Control may transfer here via looping or 'continue'.
304 1140 : ObserveTypesAtOsrEntry(stmt);
305 2280 : RECURSE(Visit(stmt->body()));
306 1140 : 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 94270 : void AstTyper::VisitConditional(Conditional* expr) {
356 : // Collect type feedback.
357 18854 : expr->condition()->RecordToBooleanTypeFeedback(oracle());
358 :
359 18854 : RECURSE(Visit(expr->condition()));
360 9427 : Effects then_effects = EnterEffects();
361 18854 : RECURSE(Visit(expr->then_expression()));
362 : ExitEffects();
363 9427 : Effects else_effects = EnterEffects();
364 18854 : RECURSE(Visit(expr->else_expression()));
365 : ExitEffects();
366 9427 : then_effects.Alt(else_effects);
367 : store_.Seq(then_effects);
368 :
369 : NarrowType(expr,
370 : AstBounds::Either(bounds_->get(expr->then_expression()),
371 18854 : bounds_->get(expr->else_expression()), zone()));
372 : }
373 :
374 :
375 3404978 : void AstTyper::VisitVariableProxy(VariableProxy* expr) {
376 : Variable* var = expr->var();
377 3404978 : if (var->IsStackAllocated()) {
378 2589013 : NarrowType(expr, store_.LookupBounds(variable_index(var)));
379 : }
380 3404978 : }
381 :
382 :
383 2779361 : void AstTyper::VisitLiteral(Literal* expr) {
384 : AstType* type = AstType::Constant(expr->value(), zone());
385 2779361 : NarrowType(expr, AstBounds(type));
386 2779361 : }
387 :
388 :
389 0 : void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) {
390 : // TODO(rossberg): Reintroduce RegExp type.
391 8660 : NarrowType(expr, AstBounds(AstType::Object()));
392 0 : }
393 :
394 :
395 200200 : void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) {
396 : ZoneList<ObjectLiteral::Property*>* properties = expr->properties();
397 400400 : for (int i = 0; i < properties->length(); ++i) {
398 502658 : ObjectLiteral::Property* prop = properties->at(i);
399 :
400 : // Collect type feedback.
401 174533 : if ((prop->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL &&
402 504810 : !CompileTimeValue::IsCompileTimeValue(prop->value())) ||
403 : prop->kind() == ObjectLiteral::Property::COMPUTED) {
404 50722 : if (!prop->is_computed_name() &&
405 101397 : prop->key()->AsLiteral()->value()->IsInternalizedString() &&
406 25314 : prop->emit_store()) {
407 : // Record type feed back for the property.
408 25290 : FeedbackSlot slot = prop->GetSlot();
409 : SmallMapList maps;
410 25290 : oracle()->CollectReceiverTypes(slot, &maps);
411 : prop->set_receiver_type(maps.length() == 1 ? maps.at(0)
412 25290 : : Handle<Map>::null());
413 : }
414 : }
415 :
416 351830 : RECURSE(Visit(prop->value()));
417 : }
418 :
419 48570 : NarrowType(expr, AstBounds(AstType::Object()));
420 : }
421 :
422 :
423 985755 : void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) {
424 : ZoneList<Expression*>* values = expr->values();
425 1971510 : for (int i = 0; i < values->length(); ++i) {
426 1947124 : Expression* value = values->at(i);
427 1947124 : RECURSE(Visit(value));
428 : }
429 :
430 24386 : NarrowType(expr, AstBounds(AstType::Object()));
431 : }
432 :
433 :
434 2550212 : void AstTyper::VisitAssignment(Assignment* expr) {
435 : // Collect type feedback.
436 662168 : Property* prop = expr->target()->AsProperty();
437 630656 : if (prop != NULL) {
438 73045 : FeedbackSlot slot = expr->AssignmentSlot();
439 73045 : expr->set_is_uninitialized(oracle()->StoreIsUninitialized(slot));
440 73045 : if (!expr->IsUninitialized()) {
441 18243 : SmallMapList* receiver_types = expr->GetReceiverTypes();
442 18243 : if (prop->key()->IsPropertyName()) {
443 26538 : 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 13269 : oracle()->AssignmentReceiverTypes(slot, name, receiver_types);
447 : } else {
448 : KeyedAccessStoreMode store_mode;
449 : IcCheckType key_type;
450 : oracle()->KeyedAssignmentReceiverTypes(slot, receiver_types,
451 4974 : &store_mode, &key_type);
452 4974 : expr->set_store_mode(store_mode);
453 4974 : expr->set_key_type(key_type);
454 : }
455 : }
456 : }
457 :
458 : Expression* rhs =
459 630656 : expr->is_compound() ? expr->binary_operation() : expr->value();
460 1261312 : RECURSE(Visit(expr->target()));
461 1261312 : RECURSE(Visit(rhs));
462 630656 : NarrowType(expr, bounds_->get(rhs));
463 :
464 1687202 : VariableProxy* proxy = expr->target()->AsVariableProxy();
465 1188267 : if (proxy != NULL && proxy->var()->IsStackAllocated()) {
466 997870 : 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 14338 : void AstTyper::VisitThrow(Throw* expr) {
479 21507 : RECURSE(Visit(expr->exception()));
480 : // TODO(rossberg): is it worth having a non-termination effect?
481 :
482 7169 : NarrowType(expr, AstBounds(AstType::None()));
483 : }
484 :
485 :
486 3720134 : void AstTyper::VisitProperty(Property* expr) {
487 : // Collect type feedback.
488 604009 : FeedbackSlot slot = expr->PropertyFeedbackSlot();
489 604009 : expr->set_inline_cache_state(oracle()->LoadInlineCacheState(slot));
490 :
491 604009 : if (!expr->IsUninitialized()) {
492 370123 : if (expr->key()->IsPropertyName()) {
493 659932 : 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 659932 : oracle()->PropertyReceiverTypes(slot, name, expr->GetReceiverTypes());
497 : } else {
498 : bool is_string;
499 : IcCheckType key_type;
500 : oracle()->KeyedPropertyReceiverTypes(slot, expr->GetReceiverTypes(),
501 40157 : &is_string, &key_type);
502 40157 : expr->set_is_string_access(is_string);
503 40157 : expr->set_key_type(key_type);
504 : }
505 : }
506 :
507 1208018 : RECURSE(Visit(expr->obj()));
508 1208018 : RECURSE(Visit(expr->key()));
509 :
510 : // We don't know anything about the result type.
511 : }
512 :
513 :
514 4240427 : void AstTyper::VisitCall(Call* expr) {
515 : // Collect type feedback.
516 1312224 : RECURSE(Visit(expr->expression()));
517 656112 : FeedbackSlot slot = expr->CallFeedbackICSlot();
518 656112 : bool is_uninitialized = oracle()->CallIsUninitialized(slot);
519 656112 : if (!expr->expression()->IsProperty() && oracle()->CallIsMonomorphic(slot)) {
520 73025 : expr->set_target(oracle()->GetCallTarget(slot));
521 73025 : 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 3231958 : for (int i = 0; i < args->length(); ++i) {
529 2575846 : Expression* arg = args->at(i);
530 1919734 : RECURSE(Visit(arg));
531 : }
532 :
533 656112 : 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 168585 : void AstTyper::VisitCallNew(CallNew* expr) {
542 : // Collect type feedback.
543 32299 : FeedbackSlot allocation_site_feedback_slot = expr->CallNewFeedbackSlot();
544 : expr->set_allocation_site(
545 32299 : oracle()->GetCallNewAllocationSite(allocation_site_feedback_slot));
546 : bool monomorphic =
547 32299 : oracle()->CallNewIsMonomorphic(expr->CallNewFeedbackSlot());
548 : expr->set_is_monomorphic(monomorphic);
549 32299 : if (monomorphic) {
550 5012 : expr->set_target(oracle()->GetCallNewTarget(expr->CallNewFeedbackSlot()));
551 : }
552 :
553 64598 : RECURSE(Visit(expr->expression()));
554 : ZoneList<Expression*>* args = expr->arguments();
555 143376 : for (int i = 0; i < args->length(); ++i) {
556 111077 : Expression* arg = args->at(i);
557 78778 : RECURSE(Visit(arg));
558 : }
559 :
560 32299 : NarrowType(expr, AstBounds(AstType::None(), AstType::Receiver()));
561 : }
562 :
563 :
564 229244 : void AstTyper::VisitCallRuntime(CallRuntime* expr) {
565 : ZoneList<Expression*>* args = expr->arguments();
566 458488 : for (int i = 0; i < args->length(); ++i) {
567 377902 : Expression* arg = args->at(i);
568 377902 : RECURSE(Visit(arg));
569 : }
570 :
571 : // We don't know anything about the result type.
572 : }
573 :
574 :
575 1549359 : void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
576 : // Collect type feedback.
577 333707 : if (expr->op() == Token::NOT) {
578 : // TODO(rossberg): only do in test or value context.
579 429062 : expr->expression()->RecordToBooleanTypeFeedback(oracle());
580 : }
581 :
582 1001121 : RECURSE(Visit(expr->expression()));
583 :
584 333707 : switch (expr->op()) {
585 : case Token::NOT:
586 : case Token::DELETE:
587 215880 : NarrowType(expr, AstBounds(AstType::Boolean()));
588 215880 : break;
589 : case Token::VOID:
590 11080 : NarrowType(expr, AstBounds(AstType::Undefined()));
591 11080 : break;
592 : case Token::TYPEOF:
593 106747 : NarrowType(expr, AstBounds(AstType::InternalizedString()));
594 106747 : break;
595 : default:
596 0 : UNREACHABLE();
597 : }
598 : }
599 :
600 :
601 183924 : void AstTyper::VisitCountOperation(CountOperation* expr) {
602 : // Collect type feedback.
603 45981 : FeedbackSlot slot = expr->CountSlot();
604 : KeyedAccessStoreMode store_mode;
605 : IcCheckType key_type;
606 45981 : oracle()->GetStoreModeAndKeyType(slot, &store_mode, &key_type);
607 45981 : oracle()->CountReceiverTypes(slot, expr->GetReceiverTypes());
608 45981 : expr->set_store_mode(store_mode);
609 45981 : expr->set_key_type(key_type);
610 : expr->set_type(oracle()->CountType(expr->CountBinOpFeedbackId(),
611 45981 : expr->CountBinaryOpFeedbackSlot()));
612 : // TODO(rossberg): merge the count type with the generic expression type.
613 :
614 91962 : RECURSE(Visit(expr->expression()));
615 :
616 45981 : NarrowType(expr, AstBounds(AstType::SignedSmall(), AstType::Number()));
617 :
618 128822 : VariableProxy* proxy = expr->expression()->AsVariableProxy();
619 90363 : if (proxy != NULL && proxy->var()->IsStackAllocated()) {
620 76918 : store_.Seq(variable_index(proxy->var()), Effect(bounds_->get(expr)));
621 : }
622 : }
623 :
624 6006972 : void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
625 : // Collect type feedback.
626 : AstType* type;
627 : AstType* left_type;
628 : AstType* right_type;
629 1023802 : 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 511901 : expr->op());
635 :
636 511901 : NarrowLowerType(expr, type);
637 1023802 : NarrowLowerType(expr->left(), left_type);
638 1023802 : NarrowLowerType(expr->right(), right_type);
639 : expr->set_allocation_site(allocation_site);
640 : expr->set_fixed_right_arg(fixed_right_arg);
641 511901 : if (expr->op() == Token::OR || expr->op() == Token::AND) {
642 122994 : expr->left()->RecordToBooleanTypeFeedback(oracle());
643 : }
644 :
645 511901 : switch (expr->op()) {
646 : case Token::COMMA:
647 13503 : RECURSE(Visit(expr->left()));
648 13002 : RECURSE(Visit(expr->right()));
649 6501 : NarrowType(expr, bounds_->get(expr->right()));
650 6501 : break;
651 : case Token::OR:
652 : case Token::AND: {
653 122994 : Effects left_effects = EnterEffects();
654 245988 : RECURSE(Visit(expr->left()));
655 : ExitEffects();
656 122994 : Effects right_effects = EnterEffects();
657 245988 : RECURSE(Visit(expr->right()));
658 : ExitEffects();
659 122994 : left_effects.Alt(right_effects);
660 : store_.Seq(left_effects);
661 :
662 : NarrowType(expr, AstBounds::Either(bounds_->get(expr->left()),
663 245988 : bounds_->get(expr->right()), zone()));
664 122994 : break;
665 : }
666 : case Token::BIT_OR:
667 : case Token::BIT_AND: {
668 79862 : RECURSE(Visit(expr->left()));
669 79862 : RECURSE(Visit(expr->right()));
670 : AstType* upper =
671 39931 : AstType::Union(bounds_->get(expr->left()).upper,
672 79862 : bounds_->get(expr->right()).upper, zone());
673 39931 : if (!upper->Is(AstType::Signed32())) upper = AstType::Signed32();
674 : AstType* lower =
675 39931 : AstType::Intersect(AstType::SignedSmall(), upper, zone());
676 39931 : NarrowType(expr, AstBounds(lower, upper));
677 39931 : break;
678 : }
679 : case Token::BIT_XOR:
680 : case Token::SHL:
681 : case Token::SAR:
682 50952 : RECURSE(Visit(expr->left()));
683 50952 : RECURSE(Visit(expr->right()));
684 25476 : NarrowType(expr, AstBounds(AstType::SignedSmall(), AstType::Signed32()));
685 25476 : break;
686 : case Token::SHR:
687 15824 : RECURSE(Visit(expr->left()));
688 15824 : 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 7912 : NarrowType(expr, AstBounds(AstType::SignedSmall(), AstType::Number()));
693 7912 : break;
694 : case Token::ADD: {
695 394690 : RECURSE(Visit(expr->left()));
696 393688 : RECURSE(Visit(expr->right()));
697 196844 : AstBounds l = bounds_->get(expr->left());
698 196844 : AstBounds r = bounds_->get(expr->right());
699 : AstType* lower =
700 370222 : !l.lower->IsInhabited() || !r.lower->IsInhabited()
701 : ? AstType::None()
702 141629 : : l.lower->Is(AstType::String()) || r.lower->Is(AstType::String())
703 : ? AstType::String()
704 140655 : : l.lower->Is(AstType::Number()) &&
705 : r.lower->Is(AstType::Number())
706 : ? AstType::SignedSmall()
707 643657 : : AstType::None();
708 : AstType* upper =
709 157594 : l.upper->Is(AstType::String()) || r.upper->Is(AstType::String())
710 : ? AstType::String()
711 31789 : : l.upper->Is(AstType::Number()) && r.upper->Is(AstType::Number())
712 : ? AstType::Number()
713 349979 : : AstType::NumberOrString();
714 196844 : 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 223484 : RECURSE(Visit(expr->left()));
722 223484 : RECURSE(Visit(expr->right()));
723 111742 : NarrowType(expr, AstBounds(AstType::SignedSmall(), AstType::Number()));
724 111742 : break;
725 : default:
726 0 : UNREACHABLE();
727 : }
728 : }
729 :
730 :
731 3547019 : 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 506717 : &right_type, &combined_type);
739 1013434 : NarrowLowerType(expr->left(), left_type);
740 1013434 : NarrowLowerType(expr->right(), right_type);
741 506717 : expr->set_combined_type(combined_type);
742 :
743 1013434 : RECURSE(Visit(expr->left()));
744 1013434 : RECURSE(Visit(expr->right()));
745 :
746 506717 : 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 3126407 : 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 4414604 : : var->IsParameter() ? parameter_index(var->index()) : kNoVar;
783 : }
784 :
785 828339 : void AstTyper::VisitDeclarations(Declaration::List* decls) {
786 1199650 : for (Declaration* decl : *decls) {
787 1285367 : RECURSE(Visit(decl));
788 : }
789 : }
790 :
791 :
792 0 : void AstTyper::VisitVariableDeclaration(VariableDeclaration* declaration) {
793 0 : }
794 :
795 :
796 33827 : void AstTyper::VisitFunctionDeclaration(FunctionDeclaration* declaration) {
797 33827 : RECURSE(Visit(declaration->fun()));
798 : }
799 :
800 :
801 : } // namespace internal
802 : } // namespace v8
|