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 @@
#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'.
}
......
......@@ -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);
......
......@@ -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;
......
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