Skip to content

Commit aec46ca

Browse files
dslomovCommit bot
authored andcommitted
Stack allocate lexical locals + hoist stack slots
Review URL: https://codereview.chromium.org/981203003 Cr-Commit-Position: refs/heads/master@{#28008}
1 parent b3a8f61 commit aec46ca

16 files changed

Lines changed: 502 additions & 215 deletions

src/compiler/ast-graph-builder.cc

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,10 +1022,15 @@ void AstGraphBuilder::VisitBlock(Block* stmt) {
10221022
VisitStatements(stmt->statements());
10231023
} else {
10241024
// Visit declarations and statements in a block scope.
1025-
Node* context = BuildLocalBlockContext(stmt->scope());
1026-
ContextScope scope(this, stmt->scope(), context);
1027-
VisitDeclarations(stmt->scope()->declarations());
1028-
VisitStatements(stmt->statements());
1025+
if (stmt->scope()->ContextLocalCount() > 0) {
1026+
Node* context = BuildLocalBlockContext(stmt->scope());
1027+
ContextScope scope(this, stmt->scope(), context);
1028+
VisitDeclarations(stmt->scope()->declarations());
1029+
VisitStatements(stmt->statements());
1030+
} else {
1031+
VisitDeclarations(stmt->scope()->declarations());
1032+
VisitStatements(stmt->statements());
1033+
}
10291034
}
10301035
if (stmt->labels() != NULL) block.EndBlock();
10311036
}
@@ -1480,10 +1485,15 @@ void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
14801485
VisitClassLiteralContents(expr);
14811486
} else {
14821487
// Visit declarations and class literal in a block scope.
1483-
Node* context = BuildLocalBlockContext(expr->scope());
1484-
ContextScope scope(this, expr->scope(), context);
1485-
VisitDeclarations(expr->scope()->declarations());
1486-
VisitClassLiteralContents(expr);
1488+
if (expr->scope()->ContextLocalCount() > 0) {
1489+
Node* context = BuildLocalBlockContext(expr->scope());
1490+
ContextScope scope(this, expr->scope(), context);
1491+
VisitDeclarations(expr->scope()->declarations());
1492+
VisitClassLiteralContents(expr);
1493+
} else {
1494+
VisitDeclarations(expr->scope()->declarations());
1495+
VisitClassLiteralContents(expr);
1496+
}
14871497
}
14881498
}
14891499

src/full-codegen.cc

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1814,22 +1814,27 @@ bool BackEdgeTable::Verify(Isolate* isolate, Code* unoptimized) {
18141814
FullCodeGenerator::EnterBlockScopeIfNeeded::EnterBlockScopeIfNeeded(
18151815
FullCodeGenerator* codegen, Scope* scope, BailoutId entry_id,
18161816
BailoutId declarations_id, BailoutId exit_id)
1817-
: codegen_(codegen), scope_(scope), exit_id_(exit_id) {
1817+
: codegen_(codegen), exit_id_(exit_id) {
18181818
saved_scope_ = codegen_->scope();
18191819

18201820
if (scope == NULL) {
18211821
codegen_->PrepareForBailoutForId(entry_id, NO_REGISTERS);
1822+
needs_block_context_ = false;
18221823
} else {
1824+
needs_block_context_ = scope->ContextLocalCount() > 0;
18231825
codegen_->scope_ = scope;
18241826
{
1825-
Comment cmnt(masm(), "[ Extend block context");
1826-
__ Push(scope->GetScopeInfo(codegen->isolate()));
1827-
codegen_->PushFunctionArgumentForContextAllocation();
1828-
__ CallRuntime(Runtime::kPushBlockContext, 2);
1829-
1830-
// Replace the context stored in the frame.
1831-
codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset,
1832-
codegen_->context_register());
1827+
if (needs_block_context_) {
1828+
Comment cmnt(masm(), "[ Extend block context");
1829+
__ Push(scope->GetScopeInfo(codegen->isolate()));
1830+
codegen_->PushFunctionArgumentForContextAllocation();
1831+
__ CallRuntime(Runtime::kPushBlockContext, 2);
1832+
1833+
// Replace the context stored in the frame.
1834+
codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset,
1835+
codegen_->context_register());
1836+
}
1837+
CHECK_EQ(0, scope->num_stack_slots());
18331838
codegen_->PrepareForBailoutForId(entry_id, NO_REGISTERS);
18341839
}
18351840
{
@@ -1842,7 +1847,7 @@ FullCodeGenerator::EnterBlockScopeIfNeeded::EnterBlockScopeIfNeeded(
18421847

18431848

18441849
FullCodeGenerator::EnterBlockScopeIfNeeded::~EnterBlockScopeIfNeeded() {
1845-
if (scope_ != NULL) {
1850+
if (needs_block_context_) {
18461851
codegen_->LoadContextField(codegen_->context_register(),
18471852
Context::PREVIOUS_INDEX);
18481853
// Update local stack frame context field.

src/full-codegen.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "src/compiler.h"
1717
#include "src/globals.h"
1818
#include "src/objects.h"
19+
#include "src/scopes.h"
1920

2021
namespace v8 {
2122
namespace internal {
@@ -220,8 +221,9 @@ class FullCodeGenerator: public AstVisitor {
220221
virtual ~NestedBlock() {}
221222

222223
virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
223-
if (statement()->AsBlock()->scope() != NULL) {
224-
++(*context_length);
224+
auto block_scope = statement()->AsBlock()->scope();
225+
if (block_scope != nullptr) {
226+
if (block_scope->ContextLocalCount() > 0) ++(*context_length);
225227
}
226228
return previous_;
227229
}
@@ -968,9 +970,9 @@ class FullCodeGenerator: public AstVisitor {
968970
MacroAssembler* masm() const { return codegen_->masm(); }
969971

970972
FullCodeGenerator* codegen_;
971-
Scope* scope_;
972973
Scope* saved_scope_;
973974
BailoutId exit_id_;
975+
bool needs_block_context_;
974976
};
975977

976978
MacroAssembler* masm_;

src/hydrogen.cc

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4512,34 +4512,38 @@ void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
45124512

45134513
{ BreakAndContinueScope push(&break_info, this);
45144514
if (scope != NULL) {
4515-
// Load the function object.
4516-
Scope* declaration_scope = scope->DeclarationScope();
4517-
HInstruction* function;
4518-
HValue* outer_context = environment()->context();
4519-
if (declaration_scope->is_script_scope() ||
4520-
declaration_scope->is_eval_scope()) {
4521-
function = new(zone()) HLoadContextSlot(
4522-
outer_context, Context::CLOSURE_INDEX, HLoadContextSlot::kNoCheck);
4523-
} else {
4524-
function = New<HThisFunction>();
4525-
}
4526-
AddInstruction(function);
4527-
// Allocate a block context and store it to the stack frame.
4528-
HInstruction* inner_context = Add<HAllocateBlockContext>(
4529-
outer_context, function, scope->GetScopeInfo(isolate()));
4530-
HInstruction* instr = Add<HStoreFrameContext>(inner_context);
4531-
set_scope(scope);
4532-
environment()->BindContext(inner_context);
4533-
if (instr->HasObservableSideEffects()) {
4534-
AddSimulate(stmt->EntryId(), REMOVABLE_SIMULATE);
4515+
if (scope->ContextLocalCount() > 0) {
4516+
// Load the function object.
4517+
Scope* declaration_scope = scope->DeclarationScope();
4518+
HInstruction* function;
4519+
HValue* outer_context = environment()->context();
4520+
if (declaration_scope->is_script_scope() ||
4521+
declaration_scope->is_eval_scope()) {
4522+
function = new (zone())
4523+
HLoadContextSlot(outer_context, Context::CLOSURE_INDEX,
4524+
HLoadContextSlot::kNoCheck);
4525+
} else {
4526+
function = New<HThisFunction>();
4527+
}
4528+
AddInstruction(function);
4529+
// Allocate a block context and store it to the stack frame.
4530+
HInstruction* inner_context = Add<HAllocateBlockContext>(
4531+
outer_context, function, scope->GetScopeInfo(isolate()));
4532+
HInstruction* instr = Add<HStoreFrameContext>(inner_context);
4533+
set_scope(scope);
4534+
environment()->BindContext(inner_context);
4535+
if (instr->HasObservableSideEffects()) {
4536+
AddSimulate(stmt->EntryId(), REMOVABLE_SIMULATE);
4537+
}
45354538
}
45364539
VisitDeclarations(scope->declarations());
45374540
AddSimulate(stmt->DeclsId(), REMOVABLE_SIMULATE);
45384541
}
45394542
CHECK_BAILOUT(VisitStatements(stmt->statements()));
45404543
}
45414544
set_scope(outer_scope);
4542-
if (scope != NULL && current_block() != NULL) {
4545+
if (scope != NULL && current_block() != NULL &&
4546+
scope->ContextLocalCount() > 0) {
45434547
HValue* inner_context = environment()->context();
45444548
HValue* outer_context = Add<HLoadNamedField>(
45454549
inner_context, nullptr,

src/objects.h

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4288,6 +4288,9 @@ class ScopeInfo : public FixedArray {
42884288
// Return the name of the given stack local.
42894289
String* StackLocalName(int var);
42904290

4291+
// Return the name of the given stack local.
4292+
int StackLocalIndex(int var);
4293+
42914294
// Return the name of the given context local.
42924295
String* ContextLocalName(int var);
42934296

@@ -4396,33 +4399,38 @@ class ScopeInfo : public FixedArray {
43964399
// slot is used per parameter, so in total this part occupies
43974400
// ParameterCount() slots in the array. For other scopes than function
43984401
// scopes ParameterCount() is 0.
4399-
// 2. StackLocalEntries:
4402+
// 2. StackLocalFirstSlot:
4403+
// Index of a first stack slot for stack local. Stack locals belonging to
4404+
// this scope are located on a stack at slots starting from this index.
4405+
// 3. StackLocalEntries:
44004406
// Contains the names of local variables that are allocated on the stack,
4401-
// in increasing order of the stack slot index. One slot is used per stack
4402-
// local, so in total this part occupies StackLocalCount() slots in the
4403-
// array.
4404-
// 3. ContextLocalNameEntries:
4407+
// in increasing order of the stack slot index. First local variable has
4408+
// a stack slot index defined in StackLocalFirstSlot (point 2 above).
4409+
// One slot is used per stack local, so in total this part occupies
4410+
// StackLocalCount() slots in the array.
4411+
// 4. ContextLocalNameEntries:
44054412
// Contains the names of local variables and parameters that are allocated
44064413
// in the context. They are stored in increasing order of the context slot
44074414
// index starting with Context::MIN_CONTEXT_SLOTS. One slot is used per
44084415
// context local, so in total this part occupies ContextLocalCount() slots
44094416
// in the array.
4410-
// 4. ContextLocalInfoEntries:
4417+
// 5. ContextLocalInfoEntries:
44114418
// Contains the variable modes and initialization flags corresponding to
44124419
// the context locals in ContextLocalNameEntries. One slot is used per
44134420
// context local, so in total this part occupies ContextLocalCount()
44144421
// slots in the array.
4415-
// 5. StrongModeFreeVariableNameEntries:
4422+
// 6. StrongModeFreeVariableNameEntries:
44164423
// Stores the names of strong mode free variables.
4417-
// 6. StrongModeFreeVariablePositionEntries:
4424+
// 7. StrongModeFreeVariablePositionEntries:
44184425
// Stores the locations (start and end position) of strong mode free
44194426
// variables.
4420-
// 7. FunctionNameEntryIndex:
4427+
// 8. FunctionNameEntryIndex:
44214428
// If the scope belongs to a named function expression this part contains
44224429
// information about the function variable. It always occupies two array
44234430
// slots: a. The name of the function variable.
44244431
// b. The context or stack slot index for the variable.
44254432
int ParameterEntriesIndex();
4433+
int StackLocalFirstSlotIndex();
44264434
int StackLocalEntriesIndex();
44274435
int ContextLocalNameEntriesIndex();
44284436
int ContextLocalInfoEntriesIndex();

src/parser.cc

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ void ParserTraits::CheckPossibleEvalCall(Expression* expression,
519519
if (callee != NULL &&
520520
callee->raw_name() == parser_->ast_value_factory()->eval_string()) {
521521
scope->DeclarationScope()->RecordEvalCall();
522+
scope->RecordEvalCall();
522523
}
523524
}
524525

@@ -3339,8 +3340,8 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
33393340
clear_first =
33403341
factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
33413342
}
3342-
Statement* clear_first_or_next =
3343-
factory()->NewIfStatement(compare, clear_first, next, next->position());
3343+
Statement* clear_first_or_next = factory()->NewIfStatement(
3344+
compare, clear_first, next, RelocInfo::kNoPosition);
33443345
inner_block->AddStatement(clear_first_or_next, zone());
33453346
}
33463347

@@ -4048,6 +4049,10 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
40484049
parenthesized_function_ = false; // The bit was set for this function only.
40494050

40504051
if (is_lazily_parsed) {
4052+
for (Scope* s = scope_->outer_scope();
4053+
s != nullptr && (s != s->DeclarationScope()); s = s->outer_scope()) {
4054+
s->ForceContextAllocation();
4055+
}
40514056
SkipLazyFunctionBody(&materialized_literal_count,
40524057
&expected_property_count, CHECK_OK);
40534058
} else {

0 commit comments

Comments
 (0)