Index: src/typing.cc |
diff --git a/src/typing.cc b/src/typing.cc |
index 9458d6dc2fe401142f7b4e3392cea419fe94500c..cec5f863de11be36cc5c523a728db3ff47fced4c 100644 |
--- a/src/typing.cc |
+++ b/src/typing.cc |
@@ -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'. |
} |