Skip to content

Commit cc09cc9

Browse files
verwaestV8 LUCI CQ
authored andcommitted
[parsing] Reuse scope infos held alive through eval
... by inserting the scope_info of the context in which we eval in what used to be the "shared_function_infos" table. This CL renames that table to the "infos" table. It would have been nice to add a separate table, but mixing it into the same table has the advantage that nested infos are easy to find. As a drive-by change this change also drops `eval_scope_position` as a way to distinguish eval. While it's technically fine for multiple evals in the scope to share scripts, it actually breaks source position info because the stack includes where eval was called by attaching that position to the script. It's relatively unlikely that we'll have multiple evals in the same scope with the same script anyway... Change-Id: I40fe2ed0c3fc9353e98846728561828f9803869d Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5701108 Reviewed-by: Leszek Swirski <[email protected]> Commit-Queue: Leszek Swirski <[email protected]> Auto-Submit: Toon Verwaest <[email protected]> Cr-Commit-Position: refs/heads/main@{#95043}
1 parent 42659e0 commit cc09cc9

48 files changed

Lines changed: 281 additions & 276 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/ast/ast-function-literal-id-reindexer.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ void AstFunctionLiteralIdReindexer::VisitFunctionLiteral(FunctionLiteral* lit) {
3131
lit->set_function_literal_id(lit->function_literal_id() + delta_);
3232
}
3333

34+
void AstFunctionLiteralIdReindexer::VisitCall(Call* expr) {
35+
AstTraversalVisitor::VisitCall(expr);
36+
if (expr->is_possibly_eval()) {
37+
expr->adjust_eval_scope_info_index(delta_);
38+
}
39+
}
40+
3441
void AstFunctionLiteralIdReindexer::VisitClassLiteral(ClassLiteral* expr) {
3542
// Manually visit the class literal so that we can change the property walk.
3643
// This should be kept in-sync with AstTraversalVisitor::VisitClassLiteral.

src/ast/ast-function-literal-id-reindexer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class AstFunctionLiteralIdReindexer final
3030
// AstTraversalVisitor implementation.
3131
void VisitFunctionLiteral(FunctionLiteral* lit);
3232
void VisitClassLiteral(ClassLiteral* lit);
33+
void VisitCall(Call* lit);
3334

3435
private:
3536
int delta_;

src/ast/ast.h

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1731,7 +1731,7 @@ class CallBase : public Expression {
17311731
class Call final : public CallBase {
17321732
public:
17331733
bool is_possibly_eval() const {
1734-
return IsPossiblyEvalField::decode(bit_field_);
1734+
return EvalScopeInfoIndexField::decode(bit_field_) > 0;
17351735
}
17361736

17371737
bool is_tagged_template() const {
@@ -1742,6 +1742,15 @@ class Call final : public CallBase {
17421742
return IsOptionalChainLinkField::decode(bit_field_);
17431743
}
17441744

1745+
uint32_t eval_scope_info_index() const {
1746+
return EvalScopeInfoIndexField::decode(bit_field_);
1747+
}
1748+
1749+
void adjust_eval_scope_info_index(int delta) {
1750+
bit_field_ = EvalScopeInfoIndexField::update(
1751+
bit_field_, eval_scope_info_index() + delta);
1752+
}
1753+
17451754
enum CallType {
17461755
GLOBAL_CALL,
17471756
WITH_CALL,
@@ -1757,11 +1766,6 @@ class Call final : public CallBase {
17571766
OTHER_CALL,
17581767
};
17591768

1760-
enum PossiblyEval {
1761-
IS_POSSIBLY_EVAL,
1762-
NOT_EVAL,
1763-
};
1764-
17651769
// Helpers to determine how to handle the call.
17661770
CallType GetCallType() const;
17671771

@@ -1773,26 +1777,26 @@ class Call final : public CallBase {
17731777

17741778
Call(Zone* zone, Expression* expression,
17751779
const ScopedPtrList<Expression>& arguments, int pos, bool has_spread,
1776-
PossiblyEval possibly_eval, bool optional_chain)
1780+
int eval_scope_info_index, bool optional_chain)
17771781
: CallBase(zone, kCall, expression, arguments, pos, has_spread) {
1778-
bit_field_ |=
1779-
IsPossiblyEvalField::encode(possibly_eval == IS_POSSIBLY_EVAL) |
1780-
IsTaggedTemplateField::encode(false) |
1781-
IsOptionalChainLinkField::encode(optional_chain);
1782+
bit_field_ |= IsTaggedTemplateField::encode(false) |
1783+
IsOptionalChainLinkField::encode(optional_chain) |
1784+
EvalScopeInfoIndexField::encode(eval_scope_info_index);
1785+
DCHECK_EQ(eval_scope_info_index > 0, is_possibly_eval());
17821786
}
17831787

17841788
Call(Zone* zone, Expression* expression,
17851789
const ScopedPtrList<Expression>& arguments, int pos,
17861790
TaggedTemplateTag tag)
17871791
: CallBase(zone, kCall, expression, arguments, pos, false) {
1788-
bit_field_ |= IsPossiblyEvalField::encode(false) |
1789-
IsTaggedTemplateField::encode(true) |
1790-
IsOptionalChainLinkField::encode(false);
1792+
bit_field_ |= IsTaggedTemplateField::encode(true) |
1793+
IsOptionalChainLinkField::encode(false) |
1794+
EvalScopeInfoIndexField::encode(0);
17911795
}
17921796

1793-
using IsPossiblyEvalField = CallBase::NextBitField<bool, 1>;
1794-
using IsTaggedTemplateField = IsPossiblyEvalField::Next<bool, 1>;
1797+
using IsTaggedTemplateField = CallBase::NextBitField<bool, 1>;
17951798
using IsOptionalChainLinkField = IsTaggedTemplateField::Next<bool, 1>;
1799+
using EvalScopeInfoIndexField = IsOptionalChainLinkField::Next<uint32_t, 20>;
17961800
};
17971801

17981802
class CallNew final : public CallBase {
@@ -3184,12 +3188,11 @@ class AstNodeFactory final {
31843188

31853189
Call* NewCall(Expression* expression,
31863190
const ScopedPtrList<Expression>& arguments, int pos,
3187-
bool has_spread,
3188-
Call::PossiblyEval possibly_eval = Call::NOT_EVAL,
3191+
bool has_spread, int eval_scope_info_index = 0,
31893192
bool optional_chain = false) {
3190-
DCHECK_IMPLIES(possibly_eval == Call::IS_POSSIBLY_EVAL, !optional_chain);
3193+
DCHECK_IMPLIES(eval_scope_info_index > 0, !optional_chain);
31913194
return zone_->New<Call>(zone_, expression, arguments, pos, has_spread,
3192-
possibly_eval, optional_chain);
3195+
eval_scope_info_index, optional_chain);
31933196
}
31943197

31953198
SuperCallForwardArgs* NewSuperCallForwardArgs(SuperCallReference* expression,

src/ast/scopes.cc

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2798,7 +2798,7 @@ void DeclarationScope::AllocateScopeInfos(ParseInfo* info,
27982798
scope->RecalcPrivateNameContextChain();
27992799
}
28002800

2801-
Tagged<WeakFixedArray> infos = script->shared_function_infos();
2801+
Tagged<WeakFixedArray> infos = script->infos();
28022802
std::unordered_map<int, Handle<ScopeInfo>> scope_infos_to_reuse;
28032803
if (v8_flags.reuse_scope_infos && infos->length() != 0) {
28042804
Tagged<SharedFunctionInfo> sfi = *info->literal()->shared_function_info();
@@ -2808,15 +2808,20 @@ void DeclarationScope::AllocateScopeInfos(ParseInfo* info,
28082808
// Look at all the existing inner functions (they are numbered id+1 until
28092809
// max_id+1) to reattach their outer scope infos to corresponding scopes.
28102810
for (int i = info->literal()->function_literal_id() + 1;
2811-
i < info->max_function_literal_id() + 1; ++i) {
2812-
Tagged<MaybeObject> maybe_sfi = infos->get(i);
2813-
if (maybe_sfi.IsWeak()) {
2814-
Tagged<SharedFunctionInfo> sfi =
2815-
Cast<SharedFunctionInfo>(maybe_sfi.GetHeapObjectAssumeWeak());
2816-
// Reuse outer scope infos. Don't look at sfi->scope_info() because that
2817-
// might be empty if the sfi isn't compiled yet.
2818-
if (!sfi->HasOuterScopeInfo()) continue;
2819-
Tagged<ScopeInfo> scope_info = sfi->GetOuterScopeInfo();
2811+
i < info->max_info_id() + 1; ++i) {
2812+
Tagged<MaybeObject> maybe_info = infos->get(i);
2813+
if (maybe_info.IsWeak()) {
2814+
Tagged<Object> info = maybe_info.GetHeapObjectAssumeWeak();
2815+
Tagged<ScopeInfo> scope_info;
2816+
if (Is<SharedFunctionInfo>(info)) {
2817+
Tagged<SharedFunctionInfo> sfi = Cast<SharedFunctionInfo>(info);
2818+
// Reuse outer scope infos. Don't look at sfi->scope_info() because
2819+
// that might be empty if the sfi isn't compiled yet.
2820+
if (!sfi->HasOuterScopeInfo()) continue;
2821+
scope_info = sfi->GetOuterScopeInfo();
2822+
} else {
2823+
scope_info = Cast<ScopeInfo>(info);
2824+
}
28202825
while (true) {
28212826
if (scope_info == outer) break;
28222827
int id = scope_info->UniqueIdInScript();

src/builtins/builtins-function.cc

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,10 @@ MaybeHandle<Object> CreateDynamicFunction(Isolate* isolate,
8484
// come from here.
8585
Handle<JSFunction> function;
8686
{
87-
ASSIGN_RETURN_ON_EXCEPTION(
88-
isolate, function,
89-
Compiler::GetFunctionFromString(
90-
handle(target->native_context(), isolate), source,
91-
ONLY_SINGLE_FUNCTION_LITERAL, parameters_end_pos, is_code_like));
87+
ASSIGN_RETURN_ON_EXCEPTION(isolate, function,
88+
Compiler::GetFunctionFromString(
89+
handle(target->native_context(), isolate),
90+
source, parameters_end_pos, is_code_like));
9291
Handle<Object> result;
9392
ASSIGN_RETURN_ON_EXCEPTION(
9493
isolate, result,

src/codegen/background-merge-task.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class V8_EXPORT_PRIVATE BackgroundMergeTask {
7373
// SharedFunctionInfo in the cached script. The main thread must:
7474
// 1. Check whether the cached script gained corresponding SharedFunctionInfos
7575
// for any of these, and if so, redo the merge.
76-
// 2. Update the cached script's shared_function_infos list to refer to these.
76+
// 2. Update the cached script's infos list to refer to these.
7777
std::vector<Handle<SharedFunctionInfo>> used_new_sfis_;
7878

7979
// SharedFunctionInfos from the cached script which were not compiled, with

0 commit comments

Comments
 (0)