V8 Project
typing.cc
Go to the documentation of this file.
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 
13 namespace v8 {
14 namespace internal {
15 
16 
18  : info_(info),
19  oracle_(
20  handle(info->closure()->shared()->code()),
21  handle(info->closure()->shared()->feedback_vector()),
22  handle(info->closure()->context()->native_context()),
23  info->zone()),
24  store_(info->zone()) {
25  InitializeAstVisitor(info->zone());
26 }
27 
28 
29 #define RECURSE(call) \
30  do { \
31  DCHECK(!visitor->HasStackOverflow()); \
32  call; \
33  if (visitor->HasStackOverflow()) return; \
34  } while (false)
35 
37  AstTyper* visitor = new(info->zone()) AstTyper(info);
38  Scope* scope = info->scope();
39 
40  // Handle implicit declaration of the function name in named function
41  // expressions before other declarations.
42  if (scope->is_function_scope() && scope->function() != NULL) {
43  RECURSE(visitor->VisitVariableDeclaration(scope->function()));
44  }
45  RECURSE(visitor->VisitDeclarations(scope->declarations()));
46  RECURSE(visitor->VisitStatements(info->function()->body()));
47 }
48 
49 #undef RECURSE
50 
51 
52 #ifdef OBJECT_PRINT
53  static void PrintObserved(Variable* var, Object* value, Type* type) {
54  OFStream os(stdout);
55  os << " observed " << (var->IsParameter() ? "param" : "local") << " ";
56  var->name()->Print(os);
57  os << " : " << Brief(value) << " -> ";
58  type->PrintTo(os);
59  os << endl;
60  }
61 #endif // OBJECT_PRINT
62 
63 
65  Type* lower = Type::NowOf(value, zone());
66  return Effect(Bounds(lower, Type::Any(zone())));
67 }
68 
69 
71  if (stmt->OsrEntryId() != info_->osr_ast_id()) return;
72 
74  JavaScriptFrameIterator it(isolate());
75  JavaScriptFrame* frame = it.frame();
76  Scope* scope = info_->scope();
77 
78  // Assert that the frame on the stack belongs to the function we want to OSR.
79  DCHECK_EQ(*info_->closure(), frame->function());
80 
81  int params = scope->num_parameters();
82  int locals = scope->StackLocalCount();
83 
84  // Use sequential composition to achieve desired narrowing.
85  // The receiver is a parameter with index -1.
87  for (int i = 0; i < params; i++) {
89  }
90 
91  for (int i = 0; i < locals; i++) {
93  }
94 
95 #ifdef OBJECT_PRINT
96  if (FLAG_trace_osr && FLAG_print_scopes) {
97  PrintObserved(scope->receiver(),
98  frame->receiver(),
100 
101  for (int i = 0; i < params; i++) {
102  PrintObserved(scope->parameter(i),
103  frame->GetParameter(i),
105  }
106 
107  ZoneList<Variable*> local_vars(locals, zone());
108  ZoneList<Variable*> context_vars(scope->ContextLocalCount(), zone());
109  scope->CollectStackAndContextLocals(&local_vars, &context_vars);
110  for (int i = 0; i < locals; i++) {
111  PrintObserved(local_vars.at(i),
112  frame->GetExpression(i),
114  }
115  }
116 #endif // OBJECT_PRINT
117 }
118 
119 
120 #define RECURSE(call) \
121  do { \
122  DCHECK(!HasStackOverflow()); \
123  call; \
124  if (HasStackOverflow()) return; \
125  } while (false)
126 
127 
129  for (int i = 0; i < stmts->length(); ++i) {
130  Statement* stmt = stmts->at(i);
131  RECURSE(Visit(stmt));
132  if (stmt->IsJump()) break;
133  }
134 }
135 
136 
137 void AstTyper::VisitBlock(Block* stmt) {
138  RECURSE(VisitStatements(stmt->statements()));
139  if (stmt->labels() != NULL) {
140  store_.Forget(); // Control may transfer here via 'break l'.
141  }
142 }
143 
144 
145 void AstTyper::VisitExpressionStatement(ExpressionStatement* stmt) {
146  RECURSE(Visit(stmt->expression()));
147 }
148 
149 
150 void AstTyper::VisitEmptyStatement(EmptyStatement* stmt) {
151 }
152 
153 
154 void AstTyper::VisitIfStatement(IfStatement* stmt) {
155  // Collect type feedback.
156  if (!stmt->condition()->ToBooleanIsTrue() &&
157  !stmt->condition()->ToBooleanIsFalse()) {
158  stmt->condition()->RecordToBooleanTypeFeedback(oracle());
159  }
160 
161  RECURSE(Visit(stmt->condition()));
162  Effects then_effects = EnterEffects();
163  RECURSE(Visit(stmt->then_statement()));
164  ExitEffects();
165  Effects else_effects = EnterEffects();
166  RECURSE(Visit(stmt->else_statement()));
167  ExitEffects();
168  then_effects.Alt(else_effects);
169  store_.Seq(then_effects);
170 }
171 
172 
173 void AstTyper::VisitContinueStatement(ContinueStatement* stmt) {
174  // TODO(rossberg): is it worth having a non-termination effect?
175 }
176 
177 
178 void AstTyper::VisitBreakStatement(BreakStatement* stmt) {
179  // TODO(rossberg): is it worth having a non-termination effect?
180 }
181 
182 
183 void AstTyper::VisitReturnStatement(ReturnStatement* stmt) {
184  // Collect type feedback.
185  // TODO(rossberg): we only need this for inlining into test contexts...
186  stmt->expression()->RecordToBooleanTypeFeedback(oracle());
187 
188  RECURSE(Visit(stmt->expression()));
189  // TODO(rossberg): is it worth having a non-termination effect?
190 }
191 
192 
193 void AstTyper::VisitWithStatement(WithStatement* stmt) {
194  RECURSE(stmt->expression());
195  RECURSE(stmt->statement());
196 }
197 
198 
199 void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) {
200  RECURSE(Visit(stmt->tag()));
201 
202  ZoneList<CaseClause*>* clauses = stmt->cases();
203  Effects local_effects(zone());
204  bool complex_effects = false; // True for label effects or fall-through.
205 
206  for (int i = 0; i < clauses->length(); ++i) {
207  CaseClause* clause = clauses->at(i);
208 
209  Effects clause_effects = EnterEffects();
210 
211  if (!clause->is_default()) {
212  Expression* label = clause->label();
213  // Collect type feedback.
214  Type* tag_type;
215  Type* label_type;
216  Type* combined_type;
217  oracle()->CompareType(clause->CompareId(),
218  &tag_type, &label_type, &combined_type);
219  NarrowLowerType(stmt->tag(), tag_type);
220  NarrowLowerType(label, label_type);
221  clause->set_compare_type(combined_type);
222 
223  RECURSE(Visit(label));
224  if (!clause_effects.IsEmpty()) complex_effects = true;
225  }
226 
227  ZoneList<Statement*>* stmts = clause->statements();
228  RECURSE(VisitStatements(stmts));
229  ExitEffects();
230  if (stmts->is_empty() || stmts->last()->IsJump()) {
231  local_effects.Alt(clause_effects);
232  } else {
233  complex_effects = true;
234  }
235  }
236 
237  if (complex_effects) {
238  store_.Forget(); // Reached this in unknown state.
239  } else {
240  store_.Seq(local_effects);
241  }
242 }
243 
244 
245 void AstTyper::VisitCaseClause(CaseClause* clause) {
246  UNREACHABLE();
247 }
248 
249 
250 void AstTyper::VisitDoWhileStatement(DoWhileStatement* stmt) {
251  // Collect type feedback.
252  if (!stmt->cond()->ToBooleanIsTrue()) {
253  stmt->cond()->RecordToBooleanTypeFeedback(oracle());
254  }
255 
256  // TODO(rossberg): refine the unconditional Forget (here and elsewhere) by
257  // computing the set of variables assigned in only some of the origins of the
258  // control transfer (such as the loop body here).
259  store_.Forget(); // Control may transfer here via looping or 'continue'.
261  RECURSE(Visit(stmt->body()));
262  RECURSE(Visit(stmt->cond()));
263  store_.Forget(); // Control may transfer here via 'break'.
264 }
265 
266 
267 void AstTyper::VisitWhileStatement(WhileStatement* stmt) {
268  // Collect type feedback.
269  if (!stmt->cond()->ToBooleanIsTrue()) {
270  stmt->cond()->RecordToBooleanTypeFeedback(oracle());
271  }
272 
273  store_.Forget(); // Control may transfer here via looping or 'continue'.
274  RECURSE(Visit(stmt->cond()));
276  RECURSE(Visit(stmt->body()));
277  store_.Forget(); // Control may transfer here via termination or 'break'.
278 }
279 
280 
281 void AstTyper::VisitForStatement(ForStatement* stmt) {
282  if (stmt->init() != NULL) {
283  RECURSE(Visit(stmt->init()));
284  }
285  store_.Forget(); // Control may transfer here via looping.
286  if (stmt->cond() != NULL) {
287  // Collect type feedback.
288  stmt->cond()->RecordToBooleanTypeFeedback(oracle());
289 
290  RECURSE(Visit(stmt->cond()));
291  }
293  RECURSE(Visit(stmt->body()));
294  if (stmt->next() != NULL) {
295  store_.Forget(); // Control may transfer here via 'continue'.
296  RECURSE(Visit(stmt->next()));
297  }
298  store_.Forget(); // Control may transfer here via termination or 'break'.
299 }
300 
301 
302 void AstTyper::VisitForInStatement(ForInStatement* stmt) {
303  // Collect type feedback.
304  stmt->set_for_in_type(static_cast<ForInStatement::ForInType>(
305  oracle()->ForInType(stmt->ForInFeedbackSlot())));
306 
307  RECURSE(Visit(stmt->enumerable()));
308  store_.Forget(); // Control may transfer here via looping or 'continue'.
310  RECURSE(Visit(stmt->body()));
311  store_.Forget(); // Control may transfer here via 'break'.
312 }
313 
314 
315 void AstTyper::VisitForOfStatement(ForOfStatement* stmt) {
316  RECURSE(Visit(stmt->iterable()));
317  store_.Forget(); // Control may transfer here via looping or 'continue'.
318  RECURSE(Visit(stmt->body()));
319  store_.Forget(); // Control may transfer here via 'break'.
320 }
321 
322 
323 void AstTyper::VisitTryCatchStatement(TryCatchStatement* stmt) {
324  Effects try_effects = EnterEffects();
325  RECURSE(Visit(stmt->try_block()));
326  ExitEffects();
327  Effects catch_effects = EnterEffects();
328  store_.Forget(); // Control may transfer here via 'throw'.
329  RECURSE(Visit(stmt->catch_block()));
330  ExitEffects();
331  try_effects.Alt(catch_effects);
332  store_.Seq(try_effects);
333  // At this point, only variables that were reassigned in the catch block are
334  // still remembered.
335 }
336 
337 
338 void AstTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
339  RECURSE(Visit(stmt->try_block()));
340  store_.Forget(); // Control may transfer here via 'throw'.
341  RECURSE(Visit(stmt->finally_block()));
342 }
343 
344 
345 void AstTyper::VisitDebuggerStatement(DebuggerStatement* stmt) {
346  store_.Forget(); // May do whatever.
347 }
348 
349 
350 void AstTyper::VisitFunctionLiteral(FunctionLiteral* expr) {
351  expr->InitializeSharedInfo(Handle<Code>(info_->closure()->shared()->code()));
352 }
353 
354 
355 void AstTyper::VisitClassLiteral(ClassLiteral* expr) {}
356 
357 
358 void AstTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
359 }
360 
361 
362 void AstTyper::VisitConditional(Conditional* expr) {
363  // Collect type feedback.
364  expr->condition()->RecordToBooleanTypeFeedback(oracle());
365 
366  RECURSE(Visit(expr->condition()));
367  Effects then_effects = EnterEffects();
368  RECURSE(Visit(expr->then_expression()));
369  ExitEffects();
370  Effects else_effects = EnterEffects();
371  RECURSE(Visit(expr->else_expression()));
372  ExitEffects();
373  then_effects.Alt(else_effects);
374  store_.Seq(then_effects);
375 
377  expr->then_expression()->bounds(),
378  expr->else_expression()->bounds(), zone()));
379 }
380 
381 
382 void AstTyper::VisitVariableProxy(VariableProxy* expr) {
383  Variable* var = expr->var();
384  if (var->IsStackAllocated()) {
386  }
387 }
388 
389 
390 void AstTyper::VisitLiteral(Literal* expr) {
391  Type* type = Type::Constant(expr->value(), zone());
392  NarrowType(expr, Bounds(type));
393 }
394 
395 
396 void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) {
397  NarrowType(expr, Bounds(Type::RegExp(zone())));
398 }
399 
400 
401 void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) {
402  ZoneList<ObjectLiteral::Property*>* properties = expr->properties();
403  for (int i = 0; i < properties->length(); ++i) {
404  ObjectLiteral::Property* prop = properties->at(i);
405 
406  // Collect type feedback.
407  if ((prop->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL &&
408  !CompileTimeValue::IsCompileTimeValue(prop->value())) ||
409  prop->kind() == ObjectLiteral::Property::COMPUTED) {
410  if (prop->key()->value()->IsInternalizedString() && prop->emit_store()) {
411  prop->RecordTypeFeedback(oracle());
412  }
413  }
414 
415  RECURSE(Visit(prop->value()));
416  }
417 
418  NarrowType(expr, Bounds(Type::Object(zone())));
419 }
420 
421 
422 void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) {
423  ZoneList<Expression*>* values = expr->values();
424  for (int i = 0; i < values->length(); ++i) {
425  Expression* value = values->at(i);
426  RECURSE(Visit(value));
427  }
428 
429  NarrowType(expr, Bounds(Type::Array(zone())));
430 }
431 
432 
433 void AstTyper::VisitAssignment(Assignment* expr) {
434  // Collect type feedback.
435  Property* prop = expr->target()->AsProperty();
436  if (prop != NULL) {
437  TypeFeedbackId id = expr->AssignmentFeedbackId();
438  expr->set_is_uninitialized(oracle()->StoreIsUninitialized(id));
439  if (!expr->IsUninitialized()) {
440  if (prop->key()->IsPropertyName()) {
441  Literal* lit_key = prop->key()->AsLiteral();
442  DCHECK(lit_key != NULL && lit_key->value()->IsString());
443  Handle<String> name = Handle<String>::cast(lit_key->value());
444  oracle()->AssignmentReceiverTypes(id, name, expr->GetReceiverTypes());
445  } else {
446  KeyedAccessStoreMode store_mode;
448  id, expr->GetReceiverTypes(), &store_mode);
449  expr->set_store_mode(store_mode);
450  }
451  }
452  }
453 
454  Expression* rhs =
455  expr->is_compound() ? expr->binary_operation() : expr->value();
456  RECURSE(Visit(expr->target()));
457  RECURSE(Visit(rhs));
458  NarrowType(expr, rhs->bounds());
459 
460  VariableProxy* proxy = expr->target()->AsVariableProxy();
461  if (proxy != NULL && proxy->var()->IsStackAllocated()) {
462  store_.Seq(variable_index(proxy->var()), Effect(expr->bounds()));
463  }
464 }
465 
466 
467 void AstTyper::VisitYield(Yield* expr) {
468  RECURSE(Visit(expr->generator_object()));
469  RECURSE(Visit(expr->expression()));
470 
471  // We don't know anything about the result type.
472 }
473 
474 
475 void AstTyper::VisitThrow(Throw* expr) {
476  RECURSE(Visit(expr->exception()));
477  // TODO(rossberg): is it worth having a non-termination effect?
478 
479  NarrowType(expr, Bounds(Type::None(zone())));
480 }
481 
482 
483 void AstTyper::VisitProperty(Property* expr) {
484  // Collect type feedback.
485  TypeFeedbackId id = expr->PropertyFeedbackId();
486  expr->set_is_uninitialized(oracle()->LoadIsUninitialized(id));
487  if (!expr->IsUninitialized()) {
488  if (expr->key()->IsPropertyName()) {
489  Literal* lit_key = expr->key()->AsLiteral();
490  DCHECK(lit_key != NULL && lit_key->value()->IsString());
491  Handle<String> name = Handle<String>::cast(lit_key->value());
492  oracle()->PropertyReceiverTypes(id, name, expr->GetReceiverTypes());
493  } else {
494  bool is_string;
496  id, expr->GetReceiverTypes(), &is_string);
497  expr->set_is_string_access(is_string);
498  }
499  }
500 
501  RECURSE(Visit(expr->obj()));
502  RECURSE(Visit(expr->key()));
503 
504  // We don't know anything about the result type.
505 }
506 
507 
508 void AstTyper::VisitCall(Call* expr) {
509  // Collect type feedback.
510  RECURSE(Visit(expr->expression()));
511  if (!expr->expression()->IsProperty() &&
512  expr->IsUsingCallFeedbackSlot(isolate()) &&
513  oracle()->CallIsMonomorphic(expr->CallFeedbackSlot())) {
514  expr->set_target(oracle()->GetCallTarget(expr->CallFeedbackSlot()));
515  Handle<AllocationSite> site =
516  oracle()->GetCallAllocationSite(expr->CallFeedbackSlot());
517  expr->set_allocation_site(site);
518  }
519 
520  ZoneList<Expression*>* args = expr->arguments();
521  for (int i = 0; i < args->length(); ++i) {
522  Expression* arg = args->at(i);
523  RECURSE(Visit(arg));
524  }
525 
526  VariableProxy* proxy = expr->expression()->AsVariableProxy();
527  if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
528  store_.Forget(); // Eval could do whatever to local variables.
529  }
530 
531  // We don't know anything about the result type.
532 }
533 
534 
535 void AstTyper::VisitCallNew(CallNew* expr) {
536  // Collect type feedback.
537  expr->RecordTypeFeedback(oracle());
538 
539  RECURSE(Visit(expr->expression()));
540  ZoneList<Expression*>* args = expr->arguments();
541  for (int i = 0; i < args->length(); ++i) {
542  Expression* arg = args->at(i);
543  RECURSE(Visit(arg));
544  }
545 
546  NarrowType(expr, Bounds(Type::None(zone()), Type::Receiver(zone())));
547 }
548 
549 
550 void AstTyper::VisitCallRuntime(CallRuntime* expr) {
551  ZoneList<Expression*>* args = expr->arguments();
552  for (int i = 0; i < args->length(); ++i) {
553  Expression* arg = args->at(i);
554  RECURSE(Visit(arg));
555  }
556 
557  // We don't know anything about the result type.
558 }
559 
560 
561 void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
562  // Collect type feedback.
563  if (expr->op() == Token::NOT) {
564  // TODO(rossberg): only do in test or value context.
565  expr->expression()->RecordToBooleanTypeFeedback(oracle());
566  }
567 
568  RECURSE(Visit(expr->expression()));
569 
570  switch (expr->op()) {
571  case Token::NOT:
572  case Token::DELETE:
573  NarrowType(expr, Bounds(Type::Boolean(zone())));
574  break;
575  case Token::VOID:
576  NarrowType(expr, Bounds(Type::Undefined(zone())));
577  break;
578  case Token::TYPEOF:
579  NarrowType(expr, Bounds(Type::InternalizedString(zone())));
580  break;
581  default:
582  UNREACHABLE();
583  }
584 }
585 
586 
587 void AstTyper::VisitCountOperation(CountOperation* expr) {
588  // Collect type feedback.
589  TypeFeedbackId store_id = expr->CountStoreFeedbackId();
590  expr->set_store_mode(oracle()->GetStoreMode(store_id));
591  oracle()->CountReceiverTypes(store_id, expr->GetReceiverTypes());
592  expr->set_type(oracle()->CountType(expr->CountBinOpFeedbackId()));
593  // TODO(rossberg): merge the count type with the generic expression type.
594 
595  RECURSE(Visit(expr->expression()));
596 
597  NarrowType(expr, Bounds(Type::SignedSmall(zone()), Type::Number(zone())));
598 
599  VariableProxy* proxy = expr->expression()->AsVariableProxy();
600  if (proxy != NULL && proxy->var()->IsStackAllocated()) {
601  store_.Seq(variable_index(proxy->var()), Effect(expr->bounds()));
602  }
603 }
604 
605 
606 void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
607  // Collect type feedback.
608  Type* type;
609  Type* left_type;
610  Type* right_type;
611  Maybe<int> fixed_right_arg;
612  Handle<AllocationSite> allocation_site;
613  oracle()->BinaryType(expr->BinaryOperationFeedbackId(),
614  &left_type, &right_type, &type, &fixed_right_arg,
615  &allocation_site, expr->op());
616  NarrowLowerType(expr, type);
617  NarrowLowerType(expr->left(), left_type);
618  NarrowLowerType(expr->right(), right_type);
619  expr->set_allocation_site(allocation_site);
620  expr->set_fixed_right_arg(fixed_right_arg);
621  if (expr->op() == Token::OR || expr->op() == Token::AND) {
622  expr->left()->RecordToBooleanTypeFeedback(oracle());
623  }
624 
625  switch (expr->op()) {
626  case Token::COMMA:
627  RECURSE(Visit(expr->left()));
628  RECURSE(Visit(expr->right()));
629  NarrowType(expr, expr->right()->bounds());
630  break;
631  case Token::OR:
632  case Token::AND: {
633  Effects left_effects = EnterEffects();
634  RECURSE(Visit(expr->left()));
635  ExitEffects();
636  Effects right_effects = EnterEffects();
637  RECURSE(Visit(expr->right()));
638  ExitEffects();
639  left_effects.Alt(right_effects);
640  store_.Seq(left_effects);
641 
643  expr->left()->bounds(), expr->right()->bounds(), zone()));
644  break;
645  }
646  case Token::BIT_OR:
647  case Token::BIT_AND: {
648  RECURSE(Visit(expr->left()));
649  RECURSE(Visit(expr->right()));
650  Type* upper = Type::Union(
651  expr->left()->bounds().upper, expr->right()->bounds().upper, zone());
652  if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone());
653  Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone());
654  NarrowType(expr, Bounds(lower, upper));
655  break;
656  }
657  case Token::BIT_XOR:
658  case Token::SHL:
659  case Token::SAR:
660  RECURSE(Visit(expr->left()));
661  RECURSE(Visit(expr->right()));
662  NarrowType(expr,
663  Bounds(Type::SignedSmall(zone()), Type::Signed32(zone())));
664  break;
665  case Token::SHR:
666  RECURSE(Visit(expr->left()));
667  RECURSE(Visit(expr->right()));
668  // TODO(rossberg): The upper bound would be Unsigned32, but since there
669  // is no 'positive Smi' type for the lower bound, we use the smallest
670  // union of Smi and Unsigned32 as upper bound instead.
671  NarrowType(expr, Bounds(Type::SignedSmall(zone()), Type::Number(zone())));
672  break;
673  case Token::ADD: {
674  RECURSE(Visit(expr->left()));
675  RECURSE(Visit(expr->right()));
676  Bounds l = expr->left()->bounds();
677  Bounds r = expr->right()->bounds();
678  Type* lower =
679  !l.lower->IsInhabited() || !r.lower->IsInhabited() ?
680  Type::None(zone()) :
681  l.lower->Is(Type::String()) || r.lower->Is(Type::String()) ?
682  Type::String(zone()) :
683  l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) ?
684  Type::SignedSmall(zone()) : Type::None(zone());
685  Type* upper =
686  l.upper->Is(Type::String()) || r.upper->Is(Type::String()) ?
687  Type::String(zone()) :
688  l.upper->Is(Type::Number()) && r.upper->Is(Type::Number()) ?
689  Type::Number(zone()) : Type::NumberOrString(zone());
690  NarrowType(expr, Bounds(lower, upper));
691  break;
692  }
693  case Token::SUB:
694  case Token::MUL:
695  case Token::DIV:
696  case Token::MOD:
697  RECURSE(Visit(expr->left()));
698  RECURSE(Visit(expr->right()));
699  NarrowType(expr, Bounds(Type::SignedSmall(zone()), Type::Number(zone())));
700  break;
701  default:
702  UNREACHABLE();
703  }
704 }
705 
706 
707 void AstTyper::VisitCompareOperation(CompareOperation* expr) {
708  // Collect type feedback.
709  Type* left_type;
710  Type* right_type;
711  Type* combined_type;
712  oracle()->CompareType(expr->CompareOperationFeedbackId(),
713  &left_type, &right_type, &combined_type);
714  NarrowLowerType(expr->left(), left_type);
715  NarrowLowerType(expr->right(), right_type);
716  expr->set_combined_type(combined_type);
717 
718  RECURSE(Visit(expr->left()));
719  RECURSE(Visit(expr->right()));
720 
721  NarrowType(expr, Bounds(Type::Boolean(zone())));
722 }
723 
724 
725 void AstTyper::VisitThisFunction(ThisFunction* expr) {
726 }
727 
728 
729 void AstTyper::VisitSuperReference(SuperReference* expr) {}
730 
731 
733  for (int i = 0; i < decls->length(); ++i) {
734  Declaration* decl = decls->at(i);
735  RECURSE(Visit(decl));
736  }
737 }
738 
739 
740 void AstTyper::VisitVariableDeclaration(VariableDeclaration* declaration) {
741 }
742 
743 
744 void AstTyper::VisitFunctionDeclaration(FunctionDeclaration* declaration) {
745  RECURSE(Visit(declaration->fun()));
746 }
747 
748 
749 void AstTyper::VisitModuleDeclaration(ModuleDeclaration* declaration) {
750  RECURSE(Visit(declaration->module()));
751 }
752 
753 
754 void AstTyper::VisitImportDeclaration(ImportDeclaration* declaration) {
755  RECURSE(Visit(declaration->module()));
756 }
757 
758 
759 void AstTyper::VisitExportDeclaration(ExportDeclaration* declaration) {
760 }
761 
762 
763 void AstTyper::VisitModuleLiteral(ModuleLiteral* module) {
764  RECURSE(Visit(module->body()));
765 }
766 
767 
768 void AstTyper::VisitModuleVariable(ModuleVariable* module) {
769 }
770 
771 
772 void AstTyper::VisitModulePath(ModulePath* module) {
773  RECURSE(Visit(module->module()));
774 }
775 
776 
777 void AstTyper::VisitModuleUrl(ModuleUrl* module) {
778 }
779 
780 
781 void AstTyper::VisitModuleStatement(ModuleStatement* stmt) {
782  RECURSE(Visit(stmt->body()));
783 }
784 
785 
786 } } // namespace v8::internal
void NarrowType(Expression *e, Bounds b)
Definition: typing.h:51
int parameter_index(int index)
Definition: typing.h:64
int variable_index(Variable *var)
Definition: typing.h:67
CompilationInfo * info_
Definition: typing.h:45
void ObserveTypesAtOsrEntry(IterationStatement *stmt)
Definition: typing.cc:70
v8::internal::Effects< int, kNoVar > Effects
Definition: typing.h:42
void NarrowLowerType(Expression *e, Type *t)
Definition: typing.h:54
AstTyper(CompilationInfo *info)
Definition: typing.cc:17
Effect ObservedOnStack(Object *value)
Definition: typing.cc:64
TypeFeedbackOracle * oracle()
Definition: typing.h:49
static void Run(CompilationInfo *info)
Definition: typing.cc:36
void VisitStatements(ZoneList< Statement * > *statements)
Definition: typing.cc:128
int stack_local_index(int index)
Definition: typing.h:65
Effects EnterEffects()
Definition: typing.h:58
void VisitDeclarations(ZoneList< Declaration * > *declarations)
Definition: typing.cc:732
BailoutId osr_ast_id() const
Definition: compiler.h:128
FunctionLiteral * function() const
Definition: compiler.h:107
Handle< JSFunction > closure() const
Definition: compiler.h:111
static bool IsCompileTimeValue(Expression *expression)
Definition: parser.cc:3331
void Seq(Var var, Effect effect)
Definition: effects.h:96
Bounds LookupBounds(Var var)
Definition: effects.h:89
static Handle< T > cast(Handle< S > that)
Definition: handles.h:116
BailoutId OsrEntryId() const
Definition: ast.h:734
Object * receiver() const
Definition: frames-inl.h:250
Object * GetParameter(int index) const
Definition: frames-inl.h:217
JSFunction * function() const
Definition: frames-inl.h:265
T & at(int i) const
Definition: list.h:69
int ContextLocalCount() const
Definition: scopes.cc:1405
int num_parameters() const
Definition: scopes.h:321
VariableDeclaration * function() const
Definition: scopes.h:309
Variable * receiver()
Definition: scopes.h:305
void CollectStackAndContextLocals(ZoneList< Variable * > *stack_locals, ZoneList< Variable * > *context_locals)
Definition: scopes.cc:584
bool is_function_scope() const
Definition: scopes.h:265
ZoneList< Declaration * > * declarations()
Definition: scopes.h:327
Variable * parameter(int index) const
Definition: scopes.h:316
int StackLocalCount() const
Definition: scopes.cc:1399
Object * GetExpression(int index) const
Definition: frames-inl.h:154
virtual bool IsJump() const
Definition: ast.h:260
void KeyedPropertyReceiverTypes(TypeFeedbackId id, SmallMapList *receiver_types, bool *is_string)
Definition: type-info.cc:266
void CompareType(TypeFeedbackId id, Type **left, Type **right, Type **combined)
Definition: type-info.cc:176
void BinaryType(TypeFeedbackId id, Type **left, Type **right, Type **result, Maybe< int > *fixed_right_arg, Handle< AllocationSite > *allocation_site, Token::Value operation)
Definition: type-info.cc:210
void CountReceiverTypes(TypeFeedbackId id, SmallMapList *receiver_types)
Definition: type-info.cc:295
Handle< AllocationSite > GetCallAllocationSite(int slot)
Definition: type-info.cc:152
void PropertyReceiverTypes(TypeFeedbackId id, Handle< String > name, SmallMapList *receiver_types)
Definition: type-info.cc:257
void KeyedAssignmentReceiverTypes(TypeFeedbackId id, SmallMapList *receiver_types, KeyedAccessStoreMode *store_mode)
Definition: type-info.cc:286
void AssignmentReceiverTypes(TypeFeedbackId id, Handle< String > name, SmallMapList *receiver_types)
Definition: type-info.cc:278
static TypeHandle NowOf(i::Object *value, Region *region)
Definition: types-inl.h:30
static TypeHandle Array(TypeHandle element, Region *region)
Definition: types.h:340
bool Is(TypeImpl *that)
Definition: types.h:390
static TypeHandle Constant(i::Handle< i::Object > value, Region *region)
Definition: types.h:330
void PrintTo(OStream &os, PrintDimension dim=BOTH_DIMS)
Definition: types.cc:1034
static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region *reg)
Definition: types.cc:607
static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region *reg)
Definition: types.cc:737
Handle< String > name() const
Definition: variables.h:71
bool IsParameter() const
Definition: variables.h:94
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
#define COMMA
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define UNREACHABLE()
Definition: logging.h:30
#define DCHECK(condition)
Definition: logging.h:205
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
bool Is(Object *obj)
TypeImpl< ZoneTypeConfig > Type
KeyedAccessStoreMode
Definition: objects.h:153
OStream & endl(OStream &os)
Definition: ostreams.cc:112
kSerializedDataOffset Object
Definition: objects-inl.h:5322
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:146
BoundsImpl< ZoneTypeConfig > Bounds
Definition: types.h:1047
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
@ None
Definition: v8.h:2211
static Handle< Value > Throw(Isolate *isolate, const char *message)
Definition: d8.cc:72
Handle< Primitive > Undefined(Isolate *isolate)
Definition: v8.h:6836
#define VOID
static BoundsImpl Either(BoundsImpl b1, BoundsImpl b2, Region *region)
Definition: types.h:1024
#define RECURSE(call)
Definition: typing.cc:120