| Index: src/full-codegen.cc
|
| diff --git a/src/full-codegen.cc b/src/full-codegen.cc
|
| index a993d4856b1e154a5924e71e80588e7993ef06e5..e32c59fc0746278c468de226c038445fc7aa2897 100644
|
| --- a/src/full-codegen.cc
|
| +++ b/src/full-codegen.cc
|
| @@ -1073,41 +1073,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);
|
| }
|
|
|
|
|
| @@ -1608,26 +1579,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(),
|
| + 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());
|
| }
|
| @@ -1795,6 +1778,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);
|
| + } 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 __
|
|
|
|
|
|
|