Support declarations of context allocated locals in Crankshaft.
The changes to scopes and parser introduce a VariableProxy wrapping the function-name variable for function literals. It seems the easiest way to get an AST id for the HSimulate after context-slot stores in declarations. Review URL: http://codereview.chromium.org/7826009 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9112 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
1be99a9627
commit
913f444cb7
@ -688,10 +688,11 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitDeclaration(Variable* variable,
|
void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
|
||||||
Variable::Mode mode,
|
Variable::Mode mode,
|
||||||
FunctionLiteral* function) {
|
FunctionLiteral* function) {
|
||||||
Comment cmnt(masm_, "[ Declaration");
|
Comment cmnt(masm_, "[ Declaration");
|
||||||
|
Variable* variable = proxy->var();
|
||||||
ASSERT(variable != NULL); // Must have been resolved.
|
ASSERT(variable != NULL); // Must have been resolved.
|
||||||
Slot* slot = variable->AsSlot();
|
Slot* slot = variable->AsSlot();
|
||||||
ASSERT(slot != NULL);
|
ASSERT(slot != NULL);
|
||||||
@ -729,10 +730,12 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
|
|||||||
// We know that we have written a function, which is not a smi.
|
// We know that we have written a function, which is not a smi.
|
||||||
__ mov(r1, Operand(cp));
|
__ mov(r1, Operand(cp));
|
||||||
__ RecordWrite(r1, Operand(offset), r2, result_register());
|
__ RecordWrite(r1, Operand(offset), r2, result_register());
|
||||||
|
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
|
||||||
} else if (mode == Variable::CONST || mode == Variable::LET) {
|
} else if (mode == Variable::CONST || mode == Variable::LET) {
|
||||||
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
|
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
|
||||||
__ str(ip, ContextOperand(cp, slot->index()));
|
__ str(ip, ContextOperand(cp, slot->index()));
|
||||||
// No write barrier since the_hole_value is in old space.
|
// No write barrier since the_hole_value is in old space.
|
||||||
|
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -767,7 +770,7 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
|
|||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
||||||
EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
|
EmitDeclaration(decl->proxy(), decl->mode(), decl->fun());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -403,7 +403,7 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
|
|
||||||
// Platform-specific code for a variable, constant, or function
|
// Platform-specific code for a variable, constant, or function
|
||||||
// declaration. Functions have an initial value.
|
// declaration. Functions have an initial value.
|
||||||
void EmitDeclaration(Variable* variable,
|
void EmitDeclaration(VariableProxy* proxy,
|
||||||
Variable::Mode mode,
|
Variable::Mode mode,
|
||||||
FunctionLiteral* function);
|
FunctionLiteral* function);
|
||||||
|
|
||||||
|
@ -2298,11 +2298,7 @@ HGraph* HGraphBuilder::CreateGraph() {
|
|||||||
// Handle implicit declaration of the function name in named function
|
// Handle implicit declaration of the function name in named function
|
||||||
// expressions before other declarations.
|
// expressions before other declarations.
|
||||||
if (scope->is_function_scope() && scope->function() != NULL) {
|
if (scope->is_function_scope() && scope->function() != NULL) {
|
||||||
if (!scope->function()->IsStackAllocated()) {
|
HandleDeclaration(scope->function(), Variable::CONST, NULL);
|
||||||
Bailout("unsupported declaration");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
environment()->Bind(scope->function(), graph()->GetConstantHole());
|
|
||||||
}
|
}
|
||||||
VisitDeclarations(scope->declarations());
|
VisitDeclarations(scope->declarations());
|
||||||
AddSimulate(AstNode::kDeclarationsId);
|
AddSimulate(AstNode::kDeclarationsId);
|
||||||
@ -5822,20 +5818,51 @@ void HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
|
|||||||
|
|
||||||
|
|
||||||
void HGraphBuilder::VisitDeclaration(Declaration* decl) {
|
void HGraphBuilder::VisitDeclaration(Declaration* decl) {
|
||||||
// We support only declarations that do not require code generation.
|
HandleDeclaration(decl->proxy(), decl->mode(), decl->fun());
|
||||||
Variable* var = decl->proxy()->var();
|
|
||||||
if (!var->IsStackAllocated() ||
|
|
||||||
decl->mode() == Variable::LET) {
|
|
||||||
return Bailout("unsupported declaration");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decl->mode() == Variable::CONST) {
|
|
||||||
ASSERT(var->IsStackAllocated());
|
void HGraphBuilder::HandleDeclaration(VariableProxy* proxy,
|
||||||
|
Variable::Mode mode,
|
||||||
|
FunctionLiteral* function) {
|
||||||
|
if (mode == Variable::LET) return Bailout("unsupported let declaration");
|
||||||
|
Variable* var = proxy->var();
|
||||||
|
Slot* slot = var->AsSlot();
|
||||||
|
ASSERT(slot != NULL);
|
||||||
|
switch (slot->type()) {
|
||||||
|
case Slot::PARAMETER:
|
||||||
|
case Slot::LOCAL:
|
||||||
|
if (mode == Variable::CONST) {
|
||||||
environment()->Bind(var, graph()->GetConstantHole());
|
environment()->Bind(var, graph()->GetConstantHole());
|
||||||
} else if (decl->fun() != NULL) {
|
} else if (function != NULL) {
|
||||||
VisitForValue(decl->fun());
|
VisitForValue(function);
|
||||||
HValue* function = Pop();
|
HValue* function_value = Pop();
|
||||||
environment()->Bind(var, function);
|
environment()->Bind(var, function_value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Slot::CONTEXT: {
|
||||||
|
HValue* context = environment()->LookupContext();
|
||||||
|
if (mode == Variable::CONST) {
|
||||||
|
HStoreContextSlot* store =
|
||||||
|
new HStoreContextSlot(context,
|
||||||
|
slot->index(),
|
||||||
|
graph()->GetConstantHole());
|
||||||
|
AddInstruction(store);
|
||||||
|
if (store->HasSideEffects()) AddSimulate(proxy->id());
|
||||||
|
} else if (function != NULL) {
|
||||||
|
VisitForValue(function);
|
||||||
|
HValue* function_value = Pop();
|
||||||
|
HStoreContextSlot* store =
|
||||||
|
new HStoreContextSlot(context,
|
||||||
|
slot->index(),
|
||||||
|
function_value);
|
||||||
|
AddInstruction(store);
|
||||||
|
if (store->HasSideEffects()) AddSimulate(proxy->id());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Slot::LOOKUP:
|
||||||
|
return Bailout("unsupported lookup slot in declaration");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -779,6 +779,10 @@ class HGraphBuilder: public AstVisitor {
|
|||||||
INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
|
INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
|
||||||
#undef INLINE_FUNCTION_GENERATOR_DECLARATION
|
#undef INLINE_FUNCTION_GENERATOR_DECLARATION
|
||||||
|
|
||||||
|
void HandleDeclaration(VariableProxy* proxy,
|
||||||
|
Variable::Mode mode,
|
||||||
|
FunctionLiteral* function);
|
||||||
|
|
||||||
void VisitDelete(UnaryOperation* expr);
|
void VisitDelete(UnaryOperation* expr);
|
||||||
void VisitVoid(UnaryOperation* expr);
|
void VisitVoid(UnaryOperation* expr);
|
||||||
void VisitTypeof(UnaryOperation* expr);
|
void VisitTypeof(UnaryOperation* expr);
|
||||||
|
@ -684,10 +684,11 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitDeclaration(Variable* variable,
|
void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
|
||||||
Variable::Mode mode,
|
Variable::Mode mode,
|
||||||
FunctionLiteral* function) {
|
FunctionLiteral* function) {
|
||||||
Comment cmnt(masm_, "[ Declaration");
|
Comment cmnt(masm_, "[ Declaration");
|
||||||
|
Variable* variable = proxy->var();
|
||||||
ASSERT(variable != NULL); // Must have been resolved.
|
ASSERT(variable != NULL); // Must have been resolved.
|
||||||
Slot* slot = variable->AsSlot();
|
Slot* slot = variable->AsSlot();
|
||||||
ASSERT(slot != NULL);
|
ASSERT(slot != NULL);
|
||||||
@ -724,10 +725,12 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
|
|||||||
int offset = Context::SlotOffset(slot->index());
|
int offset = Context::SlotOffset(slot->index());
|
||||||
__ mov(ebx, esi);
|
__ mov(ebx, esi);
|
||||||
__ RecordWrite(ebx, offset, result_register(), ecx);
|
__ RecordWrite(ebx, offset, result_register(), ecx);
|
||||||
|
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
|
||||||
} else if (mode == Variable::CONST || mode == Variable::LET) {
|
} else if (mode == Variable::CONST || mode == Variable::LET) {
|
||||||
__ mov(ContextOperand(esi, slot->index()),
|
__ mov(ContextOperand(esi, slot->index()),
|
||||||
Immediate(isolate()->factory()->the_hole_value()));
|
Immediate(isolate()->factory()->the_hole_value()));
|
||||||
// No write barrier since the hole value is in old space.
|
// No write barrier since the hole value is in old space.
|
||||||
|
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -763,7 +766,7 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
|
|||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
||||||
EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
|
EmitDeclaration(decl->proxy(), decl->mode(), decl->fun());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -131,18 +131,18 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope)
|
|||||||
// For now, this must happen at the very end because of the
|
// For now, this must happen at the very end because of the
|
||||||
// ordering of the scope info slots and the respective slot indices.
|
// ordering of the scope info slots and the respective slot indices.
|
||||||
if (scope->is_function_scope()) {
|
if (scope->is_function_scope()) {
|
||||||
Variable* var = scope->function();
|
VariableProxy* proxy = scope->function();
|
||||||
if (var != NULL &&
|
if (proxy != NULL &&
|
||||||
var->is_used() &&
|
proxy->var()->is_used() &&
|
||||||
var->AsSlot()->type() == Slot::CONTEXT) {
|
proxy->var()->IsContextSlot()) {
|
||||||
function_name_ = var->name();
|
function_name_ = proxy->name();
|
||||||
// Note that we must not find the function name in the context slot
|
// Note that we must not find the function name in the context slot
|
||||||
// list - instead it must be handled separately in the
|
// list - instead it must be handled separately in the
|
||||||
// Contexts::Lookup() function. Thus record an empty symbol here so we
|
// Contexts::Lookup() function. Thus record an empty symbol here so we
|
||||||
// get the correct number of context slots.
|
// get the correct number of context slots.
|
||||||
ASSERT(var->AsSlot()->index() - Context::MIN_CONTEXT_SLOTS ==
|
ASSERT(proxy->var()->AsSlot()->index() - Context::MIN_CONTEXT_SLOTS ==
|
||||||
context_slots_.length());
|
context_slots_.length());
|
||||||
ASSERT(var->AsSlot()->index() - Context::MIN_CONTEXT_SLOTS ==
|
ASSERT(proxy->var()->AsSlot()->index() - Context::MIN_CONTEXT_SLOTS ==
|
||||||
context_modes_.length());
|
context_modes_.length());
|
||||||
context_slots_.Add(FACTORY->empty_symbol());
|
context_slots_.Add(FACTORY->empty_symbol());
|
||||||
context_modes_.Add(Variable::INTERNAL);
|
context_modes_.Add(Variable::INTERNAL);
|
||||||
|
@ -378,8 +378,10 @@ Variable* Scope::Lookup(Handle<String> name) {
|
|||||||
|
|
||||||
Variable* Scope::DeclareFunctionVar(Handle<String> name) {
|
Variable* Scope::DeclareFunctionVar(Handle<String> name) {
|
||||||
ASSERT(is_function_scope() && function_ == NULL);
|
ASSERT(is_function_scope() && function_ == NULL);
|
||||||
function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL);
|
Variable* function_var =
|
||||||
return function_;
|
new Variable(this, name, Variable::CONST, true, Variable::NORMAL);
|
||||||
|
function_ = new(isolate_->zone()) VariableProxy(isolate_, function_var);
|
||||||
|
return function_->var();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -715,7 +717,7 @@ void Scope::Print(int n) {
|
|||||||
PrettyPrinter printer;
|
PrettyPrinter printer;
|
||||||
Indent(n1, "// function var\n");
|
Indent(n1, "// function var\n");
|
||||||
if (function_ != NULL) {
|
if (function_ != NULL) {
|
||||||
PrintVar(&printer, n1, function_);
|
PrintVar(&printer, n1, function_->var());
|
||||||
}
|
}
|
||||||
|
|
||||||
Indent(n1, "// temporary vars\n");
|
Indent(n1, "// temporary vars\n");
|
||||||
@ -796,7 +798,7 @@ Variable* Scope::LookupRecursive(Handle<String> name,
|
|||||||
// the name of named function literal is kept in an intermediate scope
|
// the name of named function literal is kept in an intermediate scope
|
||||||
// in between this scope and the next outer scope.)
|
// in between this scope and the next outer scope.)
|
||||||
if (function_ != NULL && function_->name().is_identical_to(name)) {
|
if (function_ != NULL && function_->name().is_identical_to(name)) {
|
||||||
var = function_;
|
var = function_->var();
|
||||||
|
|
||||||
} else if (outer_scope_ != NULL) {
|
} else if (outer_scope_ != NULL) {
|
||||||
var = outer_scope_->LookupRecursive(
|
var = outer_scope_->LookupRecursive(
|
||||||
@ -1114,7 +1116,7 @@ void Scope::AllocateNonParameterLocals() {
|
|||||||
// because of the current ScopeInfo implementation (see
|
// because of the current ScopeInfo implementation (see
|
||||||
// ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
|
// ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
|
||||||
if (function_ != NULL) {
|
if (function_ != NULL) {
|
||||||
AllocateNonParameterLocal(function_);
|
AllocateNonParameterLocal(function_->var());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,7 +239,7 @@ class Scope: public ZoneObject {
|
|||||||
// The variable holding the function literal for named function
|
// The variable holding the function literal for named function
|
||||||
// literals, or NULL.
|
// literals, or NULL.
|
||||||
// Only valid for function scopes.
|
// Only valid for function scopes.
|
||||||
Variable* function() const {
|
VariableProxy* function() const {
|
||||||
ASSERT(is_function_scope());
|
ASSERT(is_function_scope());
|
||||||
return function_;
|
return function_;
|
||||||
}
|
}
|
||||||
@ -358,7 +358,7 @@ class Scope: public ZoneObject {
|
|||||||
// Convenience variable.
|
// Convenience variable.
|
||||||
Variable* receiver_;
|
Variable* receiver_;
|
||||||
// Function variable, if any; function scopes only.
|
// Function variable, if any; function scopes only.
|
||||||
Variable* function_;
|
VariableProxy* function_;
|
||||||
// Convenience variable; function scopes only.
|
// Convenience variable; function scopes only.
|
||||||
Variable* arguments_;
|
Variable* arguments_;
|
||||||
|
|
||||||
|
@ -659,10 +659,11 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitDeclaration(Variable* variable,
|
void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
|
||||||
Variable::Mode mode,
|
Variable::Mode mode,
|
||||||
FunctionLiteral* function) {
|
FunctionLiteral* function) {
|
||||||
Comment cmnt(masm_, "[ Declaration");
|
Comment cmnt(masm_, "[ Declaration");
|
||||||
|
Variable* variable = proxy->var();
|
||||||
ASSERT(variable != NULL); // Must have been resolved.
|
ASSERT(variable != NULL); // Must have been resolved.
|
||||||
Slot* slot = variable->AsSlot();
|
Slot* slot = variable->AsSlot();
|
||||||
ASSERT(slot != NULL);
|
ASSERT(slot != NULL);
|
||||||
@ -699,10 +700,12 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
|
|||||||
int offset = Context::SlotOffset(slot->index());
|
int offset = Context::SlotOffset(slot->index());
|
||||||
__ movq(rbx, rsi);
|
__ movq(rbx, rsi);
|
||||||
__ RecordWrite(rbx, offset, result_register(), rcx);
|
__ RecordWrite(rbx, offset, result_register(), rcx);
|
||||||
|
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
|
||||||
} else if (mode == Variable::CONST || mode == Variable::LET) {
|
} else if (mode == Variable::CONST || mode == Variable::LET) {
|
||||||
__ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
|
__ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
|
||||||
__ movq(ContextOperand(rsi, slot->index()), kScratchRegister);
|
__ movq(ContextOperand(rsi, slot->index()), kScratchRegister);
|
||||||
// No write barrier since the hole value is in old space.
|
// No write barrier since the hole value is in old space.
|
||||||
|
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -734,7 +737,7 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
|
|||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
|
||||||
EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
|
EmitDeclaration(decl->proxy(), decl->mode(), decl->fun());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user