Commit 37d5abc9 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Collect type information based on stack allocated values for OSR.

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
parent 389ee8d5
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include "typing.h" #include "typing.h"
#include "frames.h"
#include "frames-inl.h"
#include "parser.h" // for CompileTimeValue; TODO(rossberg): should move #include "parser.h" // for CompileTimeValue; TODO(rossberg): should move
#include "scopes.h" #include "scopes.h"
...@@ -68,6 +70,75 @@ void AstTyper::Run(CompilationInfo* info) { ...@@ -68,6 +70,75 @@ void AstTyper::Run(CompilationInfo* info) {
#undef RECURSE #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) \ #define RECURSE(call) \
do { \ do { \
ASSERT(!HasStackOverflow()); \ ASSERT(!HasStackOverflow()); \
...@@ -221,6 +292,7 @@ void AstTyper::VisitDoWhileStatement(DoWhileStatement* stmt) { ...@@ -221,6 +292,7 @@ void AstTyper::VisitDoWhileStatement(DoWhileStatement* stmt) {
// computing the set of variables assigned in only some of the origins of the // computing the set of variables assigned in only some of the origins of the
// control transfer (such as the loop body here). // control transfer (such as the loop body here).
store_.Forget(); // Control may transfer here via looping or 'continue'. store_.Forget(); // Control may transfer here via looping or 'continue'.
ObserveTypesAtOsrEntry(stmt);
RECURSE(Visit(stmt->body())); RECURSE(Visit(stmt->body()));
RECURSE(Visit(stmt->cond())); RECURSE(Visit(stmt->cond()));
store_.Forget(); // Control may transfer here via 'break'. store_.Forget(); // Control may transfer here via 'break'.
...@@ -235,6 +307,7 @@ void AstTyper::VisitWhileStatement(WhileStatement* stmt) { ...@@ -235,6 +307,7 @@ void AstTyper::VisitWhileStatement(WhileStatement* stmt) {
store_.Forget(); // Control may transfer here via looping or 'continue'. store_.Forget(); // Control may transfer here via looping or 'continue'.
RECURSE(Visit(stmt->cond())); RECURSE(Visit(stmt->cond()));
ObserveTypesAtOsrEntry(stmt);
RECURSE(Visit(stmt->body())); RECURSE(Visit(stmt->body()));
store_.Forget(); // Control may transfer here via termination or 'break'. store_.Forget(); // Control may transfer here via termination or 'break'.
} }
...@@ -251,6 +324,7 @@ void AstTyper::VisitForStatement(ForStatement* stmt) { ...@@ -251,6 +324,7 @@ void AstTyper::VisitForStatement(ForStatement* stmt) {
RECURSE(Visit(stmt->cond())); RECURSE(Visit(stmt->cond()));
} }
ObserveTypesAtOsrEntry(stmt);
RECURSE(Visit(stmt->body())); RECURSE(Visit(stmt->body()));
if (stmt->next() != NULL) { if (stmt->next() != NULL) {
store_.Forget(); // Control may transfer here via 'continue'. store_.Forget(); // Control may transfer here via 'continue'.
...@@ -267,6 +341,7 @@ void AstTyper::VisitForInStatement(ForInStatement* stmt) { ...@@ -267,6 +341,7 @@ void AstTyper::VisitForInStatement(ForInStatement* stmt) {
RECURSE(Visit(stmt->enumerable())); RECURSE(Visit(stmt->enumerable()));
store_.Forget(); // Control may transfer here via looping or 'continue'. store_.Forget(); // Control may transfer here via looping or 'continue'.
ObserveTypesAtOsrEntry(stmt);
RECURSE(Visit(stmt->body())); RECURSE(Visit(stmt->body()));
store_.Forget(); // Control may transfer here via 'break'. store_.Forget(); // Control may transfer here via 'break'.
} }
......
...@@ -58,6 +58,9 @@ class AstTyper: public AstVisitor { ...@@ -58,6 +58,9 @@ class AstTyper: public AstVisitor {
private: private:
explicit AstTyper(CompilationInfo* info); explicit AstTyper(CompilationInfo* info);
Effect ObservedOnStack(Object* value);
void ObserveTypesAtOsrEntry(IterationStatement* stmt);
static const int kNoVar = INT_MIN; static const int kNoVar = INT_MIN;
typedef v8::internal::Effects<int, kNoVar> Effects; typedef v8::internal::Effects<int, kNoVar> Effects;
typedef v8::internal::NestedEffects<int, kNoVar> Store; typedef v8::internal::NestedEffects<int, kNoVar> Store;
...@@ -82,12 +85,15 @@ class AstTyper: public AstVisitor { ...@@ -82,12 +85,15 @@ class AstTyper: public AstVisitor {
} }
void ExitEffects() { store_ = store_.Pop(); } 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) { int variable_index(Variable* var) {
// Stack locals have the range [0 .. l] // Stack locals have the range [0 .. l]
// Parameters have the range [-1 .. p] // Parameters have the range [-1 .. p]
// We map this to [-p-2 .. -1, 0 .. l] // We map this to [-p-2 .. -1, 0 .. l]
return var->IsStackLocal() ? var->index() : return var->IsStackLocal() ? stack_local_index(var->index()) :
var->IsParameter() ? -var->index() - 2 : kNoVar; var->IsParameter() ? parameter_index(var->index()) : kNoVar;
} }
void VisitDeclarations(ZoneList<Declaration*>* declarations); void VisitDeclarations(ZoneList<Declaration*>* declarations);
......
...@@ -1118,6 +1118,7 @@ class BailoutId { ...@@ -1118,6 +1118,7 @@ class BailoutId {
bool IsNone() const { return id_ == kNoneId; } 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_; }
bool operator!=(const BailoutId& other) const { return id_ != other.id_; }
private: private:
static const int kNoneId = -1; static const int kNoneId = -1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment