Index: src/typing.cc |
diff --git a/src/typing.cc b/src/typing.cc |
index 8487c05eb4af9fe472509c5afc34ae0eb1916053..8fa258176b6498f7d572cf1698ced7ba9691f398 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" |
@@ -41,8 +43,11 @@ AstTyper::AstTyper(CompilationInfo* info) |
Handle<Context>(info->closure()->context()->native_context()), |
info->isolate(), |
info->zone()), |
- store_(info->zone()) { |
+ store_(info->zone()), |
+ parameter_types_(NULL), |
+ stack_local_types_(NULL) { |
InitializeAstVisitor(info->isolate()); |
+ if (info_->is_osr()) ObserveTypesOnStack(); |
} |
@@ -68,6 +73,78 @@ void AstTyper::Run(CompilationInfo* info) { |
#undef RECURSE |
+ |
+Handle<Type> AstTyper::ObserveType(Object* value) { |
+ if (value->IsUndefined() || value->IsTheHole()) { |
+ return Handle<Type>(Type::None(), isolate()); |
+ } else { |
+ return Handle<Type>(Type::OfCurrently(Handle<Object>(value, isolate())), |
+ isolate()); |
+ } |
+} |
+ |
+ |
+void AstTyper::ObserveTypesOnStack() { |
+ 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->num_stack_slots(); |
+ |
+ parameter_types_ = new(zone()) ZoneList<Handle<Type> >(params + 1, zone()); |
+ stack_local_types_ = new(zone()) ZoneList<Handle<Type> >(locals, zone()); |
+ |
+ // The receiver ('this') is a parameter with index -1. We store it as |
+ // element 0 and shift other params up by 1. |
+ parameter_types_->Add(ObserveType(frame->receiver()), zone()); |
+ for (int i = 0; i < params; i++) { |
+ parameter_types_->Add(ObserveType(frame->GetParameter(i)), zone()); |
+ } |
+ |
+ // This includes the function var, if it is stored as a stack local. |
+ for (int i = 0; i < locals; i++) { |
+ stack_local_types_->Add(ObserveType(frame->GetExpression(i)), zone()); |
+ } |
+} |
+ |
+ |
+Handle<Type> AstTyper::GetObservedType(Variable* var) { |
+ ASSERT(info_->is_osr()); |
+ ZoneList<Handle<Type> >* list; |
+ int index = var->index(); |
+ |
+ if (var->IsParameter()) { |
+ index += 1; |
+ list = parameter_types_; |
+ } else { |
+ ASSERT(var->IsStackLocal()); |
+ list = stack_local_types_; |
+ } |
+ |
+ // We could also observe the type of context allocated values. We would go |
+ // up the function's scope chain until we find the variable's scope, go up |
+ // the context chain at the same time, and load the value from the context |
+ // slot stored as variable index. But this seems not to be worth the effort. |
+ |
+ ASSERT(0 <= index && index < list->length()); |
Jakob Kummerow
2013/12/12 13:46:46
Unnecessary -- List::at() contains the same check.
|
+ Handle<Type> result = list->at(index); |
+ |
+ if (FLAG_trace_osr && FLAG_print_scopes) { |
+ PrintF(" observed %s : ", var->IsParameter() ? "param" : "local"); |
+ var->name()->Print(); |
+ PrintF(" -> "); |
+ result->TypePrint(); |
+ } |
+ |
+ return result; |
+} |
+ |
+ |
#define RECURSE(call) \ |
do { \ |
ASSERT(!HasStackOverflow()); \ |
@@ -339,6 +416,7 @@ void AstTyper::VisitVariableProxy(VariableProxy* expr) { |
Variable* var = expr->var(); |
if (var->IsStackAllocated()) { |
NarrowType(expr, store_.LookupBounds(variable_index(var))); |
+ if (info_->is_osr()) NarrowLowerType(expr, GetObservedType(var)); |
} |
} |