Chromium Code Reviews| Index: src/full-codegen.cc |
| diff --git a/src/full-codegen.cc b/src/full-codegen.cc |
| index e399a3496c342f536e92fc0d4aee84a5d83270a2..79771dbcc4d937c3f60998702f9124e1664369b0 100644 |
| --- a/src/full-codegen.cc |
| +++ b/src/full-codegen.cc |
| @@ -1070,41 +1070,12 @@ void FullCodeGenerator::VisitBlock(Block* stmt) { |
| NestedBlock nested_block(this, stmt); |
| SetStatementPosition(stmt); |
| - Scope* saved_scope = scope(); |
| - // Push a block context when entering a block with block scoped variables. |
| - if (stmt->scope() == NULL) { |
| - PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); |
| - } else { |
| - scope_ = stmt->scope(); |
| - DCHECK(!scope_->is_module_scope()); |
| - { Comment cmnt(masm_, "[ Extend block context"); |
| - __ Push(scope_->GetScopeInfo()); |
| - PushFunctionArgumentForContextAllocation(); |
| - __ CallRuntime(Runtime::kPushBlockContext, 2); |
| - |
| - // Replace the context stored in the frame. |
| - StoreToFrameField(StandardFrameConstants::kContextOffset, |
| - context_register()); |
| - PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); |
| - } |
| - { Comment cmnt(masm_, "[ Declarations"); |
| - VisitDeclarations(scope_->declarations()); |
| - PrepareForBailoutForId(stmt->DeclsId(), NO_REGISTERS); |
| - } |
| - } |
| - |
| - VisitStatements(stmt->statements()); |
| - scope_ = saved_scope; |
| - __ bind(nested_block.break_label()); |
| - |
| - // Pop block context if necessary. |
| - if (stmt->scope() != NULL) { |
| - LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
| - // Update local stack frame context field. |
| - StoreToFrameField(StandardFrameConstants::kContextOffset, |
| - context_register()); |
| + { |
| + EnterBlockScopeIfNeeded block_scope_state( |
| + this, stmt->scope(), stmt->EntryId(), stmt->DeclsId(), stmt->ExitId()); |
| + VisitStatements(stmt->statements()); |
| + __ bind(nested_block.break_label()); |
| } |
| - PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
| } |
| @@ -1605,26 +1576,38 @@ void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
| void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) { |
| Comment cmnt(masm_, "[ ClassLiteral"); |
| - if (lit->raw_name() != NULL) { |
| - __ Push(lit->name()); |
| - } else { |
| - __ Push(isolate()->factory()->undefined_value()); |
| - } |
| + { |
| + EnterBlockScopeIfNeeded block_scope_state( |
| + this, lit->scope(), BailoutId::None(), BailoutId::None(), |
|
Dmitry Lomov (no reviews)
2014/11/13 21:10:37
Nice!
|
| + BailoutId::None()); |
| - if (lit->extends() != NULL) { |
| - VisitForStackValue(lit->extends()); |
| - } else { |
| - __ Push(isolate()->factory()->the_hole_value()); |
| - } |
| + if (lit->raw_name() != NULL) { |
| + __ Push(lit->name()); |
| + } else { |
| + __ Push(isolate()->factory()->undefined_value()); |
| + } |
| - VisitForStackValue(lit->constructor()); |
| + if (lit->extends() != NULL) { |
| + VisitForStackValue(lit->extends()); |
| + } else { |
| + __ Push(isolate()->factory()->the_hole_value()); |
| + } |
| + |
| + VisitForStackValue(lit->constructor()); |
| - __ Push(script()); |
| - __ Push(Smi::FromInt(lit->start_position())); |
| - __ Push(Smi::FromInt(lit->end_position())); |
| + __ Push(script()); |
| + __ Push(Smi::FromInt(lit->start_position())); |
| + __ Push(Smi::FromInt(lit->end_position())); |
| - __ CallRuntime(Runtime::kDefineClass, 6); |
| - EmitClassDefineProperties(lit); |
| + __ CallRuntime(Runtime::kDefineClass, 6); |
| + EmitClassDefineProperties(lit); |
| + |
| + if (lit->scope() != NULL) { |
| + DCHECK_NOT_NULL(lit->class_variable_proxy()); |
| + EmitVariableAssignment(lit->class_variable_proxy()->var(), |
| + Token::INIT_CONST); |
| + } |
| + } |
| context()->Plug(result_register()); |
| } |
| @@ -1792,6 +1775,49 @@ bool BackEdgeTable::Verify(Isolate* isolate, Code* unoptimized) { |
| #endif // DEBUG |
| +FullCodeGenerator::EnterBlockScopeIfNeeded::EnterBlockScopeIfNeeded( |
| + FullCodeGenerator* codegen, Scope* scope, BailoutId entry_id, |
| + BailoutId declarations_id, BailoutId exit_id) |
| + : codegen_(codegen), scope_(scope), exit_id_(exit_id) { |
| + saved_scope_ = codegen_->scope(); |
| + |
| + if (scope == NULL) { |
| + codegen_->PrepareForBailoutForId(entry_id, NO_REGISTERS); |
|
Dmitry Lomov (no reviews)
2014/11/13 21:10:37
This should crash under --always-opt when entry_id
arv (Not doing code reviews)
2014/11/13 21:56:29
Since ClassLiteral is not optimized this is fine.
|
| + } else { |
| + codegen_->scope_ = scope; |
| + { |
| + Comment cmnt(masm(), "[ Extend block context"); |
| + __ Push(scope->GetScopeInfo()); |
| + codegen_->PushFunctionArgumentForContextAllocation(); |
| + __ CallRuntime(Runtime::kPushBlockContext, 2); |
| + |
| + // Replace the context stored in the frame. |
| + codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset, |
| + codegen_->context_register()); |
| + codegen_->PrepareForBailoutForId(entry_id, NO_REGISTERS); |
| + } |
| + { |
| + Comment cmnt(masm(), "[ Declarations"); |
| + codegen_->VisitDeclarations(scope->declarations()); |
| + codegen_->PrepareForBailoutForId(declarations_id, NO_REGISTERS); |
| + } |
| + } |
| +} |
| + |
| + |
| +FullCodeGenerator::EnterBlockScopeIfNeeded::~EnterBlockScopeIfNeeded() { |
| + if (scope_ != NULL) { |
| + codegen_->LoadContextField(codegen_->context_register(), |
| + Context::PREVIOUS_INDEX); |
| + // Update local stack frame context field. |
| + codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset, |
| + codegen_->context_register()); |
| + } |
| + codegen_->PrepareForBailoutForId(exit_id_, NO_REGISTERS); |
| + codegen_->scope_ = saved_scope_; |
| +} |
| + |
| + |
| #undef __ |