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

Side by Side Diff: src/typing.cc

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

Powered by Google App Engine
This is Rietveld 408576698