Chromium Code Reviews| Index: src/typing.cc |
| diff --git a/src/typing.cc b/src/typing.cc |
| index 9458d6dc2fe401142f7b4e3392cea419fe94500c..6c14295911e08d30c8ba6f1b14ec2516e0bf0a4f 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(); |
|
rossberg
2013/12/16 09:57:26
This should go into the Run method. It is not cons
|
| } |
| @@ -68,6 +73,77 @@ void AstTyper::Run(CompilationInfo* info) { |
| #undef RECURSE |
| + |
| +Handle<Type> AstTyper::ObserveType(Object* value) { |
| + if (value->IsUndefined() || value->IsTheHole()) { |
|
rossberg
2013/12/16 09:57:26
Why is the type None for undefined?
|
| + 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. |
| + |
| + Handle<Type> result = list->at(index); |
| +#ifdef OBJECT_PRINT |
| + if (FLAG_trace_osr && FLAG_print_scopes) { |
| + PrintF(" observed %s : ", var->IsParameter() ? "param" : "local"); |
| + var->name()->Print(); |
| + PrintF(" -> "); |
| + result->TypePrint(); |
| + } |
| +#endif |
| + return result; |
| +} |
| + |
| + |
| #define RECURSE(call) \ |
| do { \ |
| ASSERT(!HasStackOverflow()); \ |
| @@ -339,6 +415,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)); |
| } |
| } |