Collect type information based on stack allocated values for OSR.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 18 Dec 2013 10:38:58 +0000 (10:38 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 18 Dec 2013 10:38:58 +0000 (10:38 +0000)
R=jkummerow@chromium.org, rossberg@chromium.org

Review URL: https://codereview.chromium.org/100093004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18343 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/typing.cc
src/typing.h
src/utils.h

index 9458d6d..cec5f86 100644 (file)
@@ -27,6 +27,8 @@
 
 #include "typing.h"
 
+#include "frames.h"
+#include "frames-inl.h"
 #include "parser.h"  // for CompileTimeValue; TODO(rossberg): should move
 #include "scopes.h"
 
@@ -68,6 +70,75 @@ void AstTyper::Run(CompilationInfo* info) {
 
 #undef RECURSE
 
+
+Effect AstTyper::ObservedOnStack(Object* value) {
+  Type* lower = Type::OfCurrently(Handle<Object>(value, isolate()));
+  return Effect(Bounds(lower, Type::Any(), isolate()));
+}
+
+
+#ifdef OBJECT_PRINT
+  static void PrintObserved(Variable* var, Object* value, Handle<Type> type) {
+    PrintF("  observed %s ", var->IsParameter() ? "param" : "local");
+    var->name()->Print();
+    PrintF(" : ");
+    value->ShortPrint();
+    PrintF(" -> ");
+    type->TypePrint();
+  }
+#endif  // OBJECT_PRINT
+
+
+void AstTyper::ObserveTypesAtOsrEntry(IterationStatement* stmt) {
+  if (stmt->OsrEntryId() != info_->osr_ast_id()) return;
+
+  DisallowHeapAllocation no_gc;
+  JavaScriptFrameIterator it(isolate());
+  JavaScriptFrame* frame = it.frame();
+  Scope* scope = info_->scope();
+
+  // Assert that the frame on the stack belongs to the function we want to OSR.
+  ASSERT_EQ(*info_->closure(), frame->function());
+
+  int params = scope->num_parameters();
+  int locals = scope->StackLocalCount();
+
+  // Use sequential composition to achieve desired narrowing.
+  // The receiver is a parameter with index -1.
+  store_.Seq(parameter_index(-1), ObservedOnStack(frame->receiver()));
+  for (int i = 0; i < params; i++) {
+    store_.Seq(parameter_index(i), ObservedOnStack(frame->GetParameter(i)));
+  }
+
+  for (int i = 0; i < locals; i++) {
+    store_.Seq(stack_local_index(i), ObservedOnStack(frame->GetExpression(i)));
+  }
+
+#ifdef OBJECT_PRINT
+  if (FLAG_trace_osr && FLAG_print_scopes) {
+    PrintObserved(scope->receiver(),
+                  frame->receiver(),
+                  store_.LookupBounds(parameter_index(-1)).lower);
+
+    for (int i = 0; i < params; i++) {
+      PrintObserved(scope->parameter(i),
+                    frame->GetParameter(i),
+                    store_.LookupBounds(parameter_index(i)).lower);
+    }
+
+    ZoneList<Variable*> local_vars(locals, zone());
+    ZoneList<Variable*> context_vars(scope->ContextLocalCount(), zone());
+    scope->CollectStackAndContextLocals(&local_vars, &context_vars);
+    for (int i = 0; i < locals; i++) {
+      PrintObserved(local_vars.at(i),
+                    frame->GetExpression(i),
+                    store_.LookupBounds(stack_local_index(i)).lower);
+    }
+  }
+#endif  // OBJECT_PRINT
+}
+
+
 #define RECURSE(call)                \
   do {                               \
     ASSERT(!HasStackOverflow());     \
@@ -221,6 +292,7 @@ void AstTyper::VisitDoWhileStatement(DoWhileStatement* stmt) {
   // computing the set of variables assigned in only some of the origins of the
   // control transfer (such as the loop body here).
   store_.Forget();  // Control may transfer here via looping or 'continue'.
+  ObserveTypesAtOsrEntry(stmt);
   RECURSE(Visit(stmt->body()));
   RECURSE(Visit(stmt->cond()));
   store_.Forget();  // Control may transfer here via 'break'.
@@ -235,6 +307,7 @@ void AstTyper::VisitWhileStatement(WhileStatement* stmt) {
 
   store_.Forget();  // Control may transfer here via looping or 'continue'.
   RECURSE(Visit(stmt->cond()));
+  ObserveTypesAtOsrEntry(stmt);
   RECURSE(Visit(stmt->body()));
   store_.Forget();  // Control may transfer here via termination or 'break'.
 }
@@ -251,6 +324,7 @@ void AstTyper::VisitForStatement(ForStatement* stmt) {
 
     RECURSE(Visit(stmt->cond()));
   }
+  ObserveTypesAtOsrEntry(stmt);
   RECURSE(Visit(stmt->body()));
   if (stmt->next() != NULL) {
     store_.Forget();  // Control may transfer here via 'continue'.
@@ -267,6 +341,7 @@ void AstTyper::VisitForInStatement(ForInStatement* stmt) {
 
   RECURSE(Visit(stmt->enumerable()));
   store_.Forget();  // Control may transfer here via looping or 'continue'.
+  ObserveTypesAtOsrEntry(stmt);
   RECURSE(Visit(stmt->body()));
   store_.Forget();  // Control may transfer here via 'break'.
 }
index a111ae5..ec9132f 100644 (file)
@@ -58,6 +58,9 @@ class AstTyper: public AstVisitor {
  private:
   explicit AstTyper(CompilationInfo* info);
 
+  Effect ObservedOnStack(Object* value);
+  void ObserveTypesAtOsrEntry(IterationStatement* stmt);
+
   static const int kNoVar = INT_MIN;
   typedef v8::internal::Effects<int, kNoVar> Effects;
   typedef v8::internal::NestedEffects<int, kNoVar> Store;
@@ -82,12 +85,15 @@ class AstTyper: public AstVisitor {
   }
   void ExitEffects() { store_ = store_.Pop(); }
 
+  int parameter_index(int index) { return -index - 2; }
+  int stack_local_index(int index) { return index; }
+
   int variable_index(Variable* var) {
     // Stack locals have the range [0 .. l]
     // Parameters have the range [-1 .. p]
     // We map this to [-p-2 .. -1, 0 .. l]
-    return var->IsStackLocal() ? var->index() :
-           var->IsParameter() ? -var->index() - 2 : kNoVar;
+    return var->IsStackLocal() ? stack_local_index(var->index()) :
+           var->IsParameter() ? parameter_index(var->index()) : kNoVar;
   }
 
   void VisitDeclarations(ZoneList<Declaration*>* declarations);
index 3a0936e..14a4c56 100644 (file)
@@ -1118,6 +1118,7 @@ class BailoutId {
 
   bool IsNone() const { return id_ == kNoneId; }
   bool operator==(const BailoutId& other) const { return id_ == other.id_; }
+  bool operator!=(const BailoutId& other) const { return id_ != other.id_; }
 
  private:
   static const int kNoneId = -1;