Skip to content

Commit 6bd1d3c

Browse files
LeszekSwirskiCommit Bot
authored andcommitted
[objects] Merge SFI outer_scope_info and feedback_metadata
Merge the outer_scope_info and feedback_metadata fields on SharedFunctionInfo. outer_scope_info is only used during parsing, and feedback_metadata is only available after compilation, so the two never exist at the same time. Thus, they can share a field slot. The exception is un-compiling and re-compiling a function, where we need the outer_scope_info again. Fortunately, the outer_scope_info can be re-calculated from the SFI's scope_info. Bug: v8:7606 Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng Change-Id: I6b97fefe859e89df75ad870da4a0bfa4b869772a Reviewed-on: https://chromium-review.googlesource.com/992432 Reviewed-by: Igor Sheludko <ishell@chromium.org> Reviewed-by: Yang Guo <yangguo@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#52454}
1 parent 48d1525 commit 6bd1d3c

25 files changed

Lines changed: 260 additions & 182 deletions

src/api.cc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -734,10 +734,14 @@ StartupData SnapshotCreator::CreateBlob(
734734

735735
i::HeapIterator heap_iterator(isolate->heap());
736736
while (i::HeapObject* current_obj = heap_iterator.next()) {
737-
// Complete in-object slack tracking for all functions.
738737
if (current_obj->IsJSFunction()) {
739738
i::JSFunction* fun = i::JSFunction::cast(current_obj);
739+
740+
// Complete in-object slack tracking for all functions.
740741
fun->CompleteInobjectSlackTrackingIfActive();
742+
743+
// Also, clear out feedback vectors.
744+
fun->feedback_cell()->set_value(isolate->heap()->undefined_value());
741745
}
742746

743747
// Clear out re-compilable data from all shared function infos. Any
@@ -746,12 +750,8 @@ StartupData SnapshotCreator::CreateBlob(
746750
if (current_obj->IsSharedFunctionInfo() &&
747751
function_code_handling == FunctionCodeHandling::kClear) {
748752
i::SharedFunctionInfo* shared = i::SharedFunctionInfo::cast(current_obj);
749-
if (shared->HasBytecodeArray()) {
750-
shared->ClearBytecodeArray();
751-
} else if (shared->HasAsmWasmData()) {
752-
shared->ClearAsmWasmData();
753-
} else if (shared->HasPreParsedScopeData()) {
754-
shared->ClearPreParsedScopeData();
753+
if (shared->CanFlushCompiled()) {
754+
shared->FlushCompiled();
755755
}
756756
DCHECK(shared->HasCodeObject() || shared->HasBuiltinId() ||
757757
shared->IsApiFunction());

src/compiler-dispatcher/unoptimized-compile-job.cc

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ UnoptimizedCompileJob::UnoptimizedCompileJob(Isolate* isolate,
7777
trace_compiler_dispatcher_jobs_(FLAG_trace_compiler_dispatcher_jobs) {
7878
DCHECK(!shared_->is_toplevel());
7979
// TODO(rmcilroy): Handle functions with non-empty outer scope info.
80-
DCHECK(shared_->outer_scope_info()->IsTheHole(isolate) ||
81-
ScopeInfo::cast(shared_->outer_scope_info())->length() == 0);
80+
DCHECK(!shared_->HasOuterScopeInfo());
8281
HandleScope scope(isolate);
8382
Handle<Script> script(Script::cast(shared_->script()), isolate);
8483
Handle<String> source(String::cast(script->source()), isolate);
@@ -206,9 +205,8 @@ void UnoptimizedCompileJob::PrepareOnMainThread(Isolate* isolate) {
206205

207206
parser_.reset(new Parser(parse_info_.get()));
208207
MaybeHandle<ScopeInfo> outer_scope_info;
209-
if (!shared_->outer_scope_info()->IsTheHole(isolate) &&
210-
ScopeInfo::cast(shared_->outer_scope_info())->length() > 0) {
211-
outer_scope_info = handle(ScopeInfo::cast(shared_->outer_scope_info()));
208+
if (shared_->HasOuterScopeInfo()) {
209+
outer_scope_info = handle(shared_->GetOuterScopeInfo());
212210
}
213211
parser_->DeserializeScopeChain(parse_info_.get(), outer_scope_info);
214212

src/compiler.cc

Lines changed: 16 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -283,37 +283,17 @@ void OptimizedCompilationJob::RecordFunctionCompilation(
283283
time_taken_to_execute_.InMillisecondsF() +
284284
time_taken_to_finalize_.InMillisecondsF();
285285

286-
LogFunctionCompilation(tag, compilation_info()->shared_info(),
287-
parse_info()->script(), abstract_code, true,
288-
time_taken_ms, isolate);
286+
Handle<Script> script(
287+
Script::cast(compilation_info()->shared_info()->script()));
288+
LogFunctionCompilation(tag, compilation_info()->shared_info(), script,
289+
abstract_code, true, time_taken_ms, isolate);
289290
}
290291

291292
// ----------------------------------------------------------------------------
292293
// Local helper methods that make up the compilation pipeline.
293294

294295
namespace {
295296

296-
void EnsureFeedbackMetadata(UnoptimizedCompilationInfo* compilation_info,
297-
Handle<SharedFunctionInfo> shared_info,
298-
Isolate* isolate) {
299-
// If no type feedback metadata exists, create it. At this point the
300-
// AstNumbering pass has already run. Note the snapshot can contain outdated
301-
// vectors for a different configuration, hence we also recreate a new vector
302-
// when the function is not compiled (i.e. no code was serialized).
303-
304-
if (shared_info->feedback_metadata()->is_empty() ||
305-
!shared_info->is_compiled()) {
306-
Handle<FeedbackMetadata> feedback_metadata = FeedbackMetadata::New(
307-
isolate, compilation_info->feedback_vector_spec());
308-
shared_info->set_feedback_metadata(*feedback_metadata);
309-
}
310-
311-
// It's very important that recompiles do not alter the structure of the type
312-
// feedback vector. Verify that the structure fits the function literal.
313-
CHECK(!shared_info->feedback_metadata()->SpecDiffersFrom(
314-
compilation_info->feedback_vector_spec()));
315-
}
316-
317297
bool UseAsmWasm(FunctionLiteral* literal, bool asm_wasm_broken) {
318298
// Check whether asm.js validation is enabled.
319299
if (!FLAG_validate_asm) return false;
@@ -335,23 +315,25 @@ void InstallUnoptimizedCode(UnoptimizedCompilationInfo* compilation_info,
335315
DCHECK_EQ(shared_info->language_mode(),
336316
compilation_info->literal()->language_mode());
337317

338-
// Ensure feedback metadata is installed.
339-
EnsureFeedbackMetadata(compilation_info, shared_info, isolate);
340-
341318
// Update the shared function info with the scope info.
342319
Handle<ScopeInfo> scope_info = compilation_info->scope()->scope_info();
343320
shared_info->set_scope_info(*scope_info);
344-
Scope* outer_scope = compilation_info->scope()->GetOuterScopeWithContext();
345-
if (outer_scope)
346-
shared_info->set_outer_scope_info(*outer_scope->scope_info());
347321

348322
if (compilation_info->has_bytecode_array()) {
349323
DCHECK(!shared_info->HasBytecodeArray()); // Only compiled once.
350324
DCHECK(!compilation_info->has_asm_wasm_data());
325+
DCHECK(!shared_info->HasFeedbackMetadata());
326+
327+
Handle<FeedbackMetadata> feedback_metadata = FeedbackMetadata::New(
328+
isolate, compilation_info->feedback_vector_spec());
329+
351330
shared_info->set_bytecode_array(*compilation_info->bytecode_array());
331+
shared_info->set_feedback_metadata(*feedback_metadata);
352332
} else {
353333
DCHECK(compilation_info->has_asm_wasm_data());
354334
shared_info->set_asm_wasm_data(*compilation_info->asm_wasm_data());
335+
shared_info->set_feedback_metadata(
336+
isolate->heap()->empty_feedback_metadata());
355337
}
356338

357339
// Install coverage info on the shared function info.
@@ -690,7 +672,6 @@ MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
690672
std::unique_ptr<OptimizedCompilationJob> job(
691673
compiler::Pipeline::NewCompilationJob(function, has_script));
692674
OptimizedCompilationInfo* compilation_info = job->compilation_info();
693-
ParseInfo* parse_info = job->parse_info();
694675

695676
compilation_info->SetOptimizingForOsr(osr_offset, osr_frame);
696677

@@ -734,7 +715,6 @@ MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
734715

735716
// Reopen handles in the new CompilationHandleScope.
736717
compilation_info->ReopenHandlesInNewHandleScope();
737-
parse_info->ReopenHandlesInNewHandleScope();
738718

739719
if (mode == ConcurrencyMode::kConcurrent) {
740720
if (GetOptimizedCodeLater(job.get(), isolate)) {
@@ -843,9 +823,8 @@ MaybeHandle<SharedFunctionInfo> FinalizeTopLevel(
843823
DCHECK_EQ(kNoSourcePosition,
844824
parse_info->literal()->function_token_position());
845825
Handle<SharedFunctionInfo> shared_info =
846-
isolate->factory()->NewSharedFunctionInfoForLiteral(parse_info->literal(),
847-
parse_info->script());
848-
shared_info->set_is_toplevel(true);
826+
isolate->factory()->NewSharedFunctionInfoForLiteral(
827+
parse_info->literal(), parse_info->script(), true);
849828

850829
// Finalize compilation of the unoptimized bytecode or asm-js data.
851830
if (!FinalizeUnoptimizedCode(parse_info, isolate, shared_info,
@@ -1900,12 +1879,8 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
19001879

19011880
// Allocate a shared function info object which will be compiled lazily.
19021881
Handle<SharedFunctionInfo> result =
1903-
isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script);
1904-
result->set_is_toplevel(false);
1905-
Scope* outer_scope = literal->scope()->GetOuterScopeWithContext();
1906-
if (outer_scope) {
1907-
result->set_outer_scope_info(*outer_scope->scope_info());
1908-
}
1882+
isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script,
1883+
false);
19091884
return result;
19101885
}
19111886

src/compiler.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -268,12 +268,11 @@ class UnoptimizedCompilationJob : public CompilationJob {
268268
// Each of the three phases can either fail or succeed.
269269
class OptimizedCompilationJob : public CompilationJob {
270270
public:
271-
OptimizedCompilationJob(uintptr_t stack_limit, ParseInfo* parse_info,
271+
OptimizedCompilationJob(uintptr_t stack_limit,
272272
OptimizedCompilationInfo* compilation_info,
273273
const char* compiler_name,
274274
State initial_state = State::kReadyToPrepare)
275275
: CompilationJob(stack_limit, initial_state),
276-
parse_info_(parse_info),
277276
compilation_info_(compilation_info),
278277
compiler_name_(compiler_name) {}
279278

@@ -299,7 +298,6 @@ class OptimizedCompilationJob : public CompilationJob {
299298
void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
300299
Isolate* isolate) const;
301300

302-
ParseInfo* parse_info() const { return parse_info_; }
303301
OptimizedCompilationInfo* compilation_info() const {
304302
return compilation_info_;
305303
}
@@ -312,8 +310,6 @@ class OptimizedCompilationJob : public CompilationJob {
312310
virtual Status FinalizeJobImpl(Isolate* isolate) = 0;
313311

314312
private:
315-
// TODO(rmcilroy): Remove parse_info.
316-
ParseInfo* parse_info_;
317313
OptimizedCompilationInfo* compilation_info_;
318314
base::TimeDelta time_taken_to_prepare_;
319315
base::TimeDelta time_taken_to_execute_;

src/compiler/pipeline.cc

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -744,21 +744,21 @@ PipelineStatistics* CreatePipelineStatistics(Handle<Script> script,
744744

745745
class PipelineCompilationJob final : public OptimizedCompilationJob {
746746
public:
747-
PipelineCompilationJob(ParseInfo* parse_info,
748-
Handle<SharedFunctionInfo> shared_info,
747+
PipelineCompilationJob(Handle<SharedFunctionInfo> shared_info,
749748
Handle<JSFunction> function)
750749
// Note that the OptimizedCompilationInfo is not initialized at the time
751750
// we pass it to the CompilationJob constructor, but it is not
752751
// dereferenced there.
753-
: OptimizedCompilationJob(parse_info->stack_limit(), parse_info,
754-
&compilation_info_, "TurboFan"),
755-
parse_info_(parse_info),
752+
: OptimizedCompilationJob(
753+
function->GetIsolate()->stack_guard()->real_climit(),
754+
&compilation_info_, "TurboFan"),
755+
zone_(function->GetIsolate()->allocator(), ZONE_NAME),
756756
zone_stats_(function->GetIsolate()->allocator()),
757-
compilation_info_(parse_info_.get()->zone(), function->GetIsolate(),
758-
shared_info, function),
759-
pipeline_statistics_(
760-
CreatePipelineStatistics(parse_info_->script(), compilation_info(),
761-
function->GetIsolate(), &zone_stats_)),
757+
compilation_info_(&zone_, function->GetIsolate(), shared_info,
758+
function),
759+
pipeline_statistics_(CreatePipelineStatistics(
760+
handle(Script::cast(shared_info->script())), compilation_info(),
761+
function->GetIsolate(), &zone_stats_)),
762762
data_(&zone_stats_, function->GetIsolate(), compilation_info(),
763763
pipeline_statistics_.get()),
764764
pipeline_(&data_),
@@ -773,7 +773,7 @@ class PipelineCompilationJob final : public OptimizedCompilationJob {
773773
void RegisterWeakObjectsInOptimizedCode(Handle<Code> code, Isolate* isolate);
774774

775775
private:
776-
std::unique_ptr<ParseInfo> parse_info_;
776+
Zone zone_;
777777
ZoneStats zone_stats_;
778778
OptimizedCompilationInfo compilation_info_;
779779
std::unique_ptr<PipelineStatistics> pipeline_statistics_;
@@ -889,8 +889,8 @@ class PipelineWasmCompilationJob final : public OptimizedCompilationJob {
889889
OptimizedCompilationInfo* info, Isolate* isolate, JSGraph* jsgraph,
890890
CallDescriptor* call_descriptor, SourcePositionTable* source_positions,
891891
WasmCompilationData* wasm_compilation_data, bool asmjs_origin)
892-
: OptimizedCompilationJob(isolate->stack_guard()->real_climit(), nullptr,
893-
info, "TurboFan", State::kReadyToExecute),
892+
: OptimizedCompilationJob(isolate->stack_guard()->real_climit(), info,
893+
"TurboFan", State::kReadyToExecute),
894894
zone_stats_(isolate->allocator()),
895895
pipeline_statistics_(CreatePipelineStatistics(
896896
Handle<Script>::null(), info, isolate, &zone_stats_)),
@@ -2075,13 +2075,7 @@ Handle<Code> Pipeline::GenerateCodeForTesting(
20752075
OptimizedCompilationJob* Pipeline::NewCompilationJob(
20762076
Handle<JSFunction> function, bool has_script) {
20772077
Handle<SharedFunctionInfo> shared = handle(function->shared());
2078-
ParseInfo* parse_info;
2079-
if (!has_script) {
2080-
parse_info = ParseInfo::AllocateWithoutScript(shared);
2081-
} else {
2082-
parse_info = new ParseInfo(shared);
2083-
}
2084-
return new PipelineCompilationJob(parse_info, shared, function);
2078+
return new PipelineCompilationJob(shared, function);
20852079
}
20862080

20872081
// static

src/debug/liveedit.cc

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -826,7 +826,7 @@ void LiveEdit::ReplaceFunctionCode(
826826
if (shared_info->is_compiled()) {
827827
// Clear old bytecode. This will trigger self-healing if we do not install
828828
// new bytecode.
829-
shared_info->ClearBytecodeArray();
829+
shared_info->FlushCompiled();
830830
shared_info->set_bytecode_array(new_shared_info->bytecode_array());
831831

832832
if (shared_info->HasBreakInfo()) {
@@ -835,16 +835,12 @@ void LiveEdit::ReplaceFunctionCode(
835835
handle(shared_info->GetDebugInfo()));
836836
}
837837
shared_info->set_scope_info(new_shared_info->scope_info());
838-
shared_info->set_outer_scope_info(new_shared_info->outer_scope_info());
838+
shared_info->set_feedback_metadata(new_shared_info->feedback_metadata());
839839
shared_info->DisableOptimization(BailoutReason::kLiveEdit);
840-
// Update the type feedback vector, if needed.
841-
Handle<FeedbackMetadata> new_feedback_metadata(
842-
new_shared_info->feedback_metadata());
843-
shared_info->set_feedback_metadata(*new_feedback_metadata);
844840
} else {
845-
// Use an empty FeedbackMetadata.
846-
Handle<FeedbackMetadata> feedback_metadata = FeedbackMetadata::New(isolate);
847-
shared_info->set_feedback_metadata(*feedback_metadata);
841+
// There should not be any feedback metadata. Keep the outer scope info the
842+
// same.
843+
DCHECK(!shared_info->HasFeedbackMetadata());
848844
}
849845

850846
int start_position = compile_info_wrapper.GetStartPosition();

src/factory.cc

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2545,11 +2545,11 @@ void Factory::ReinitializeJSGlobalProxy(Handle<JSGlobalProxy> object,
25452545
}
25462546

25472547
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfoForLiteral(
2548-
FunctionLiteral* literal, Handle<Script> script) {
2548+
FunctionLiteral* literal, Handle<Script> script, bool is_toplevel) {
25492549
FunctionKind kind = literal->kind();
25502550
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfoForBuiltin(
25512551
literal->name(), Builtins::kCompileLazy, kind);
2552-
SharedFunctionInfo::InitFromFunctionLiteral(shared, literal);
2552+
SharedFunctionInfo::InitFromFunctionLiteral(shared, literal, is_toplevel);
25532553
SharedFunctionInfo::SetScript(shared, script, false);
25542554
return shared;
25552555
}
@@ -2577,14 +2577,16 @@ Handle<JSMessageObject> Factory::NewJSMessageObject(
25772577
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfoForApiFunction(
25782578
MaybeHandle<String> maybe_name,
25792579
Handle<FunctionTemplateInfo> function_template_info, FunctionKind kind) {
2580-
return NewSharedFunctionInfo(maybe_name, function_template_info,
2581-
Builtins::kNoBuiltinId, kind);
2580+
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(
2581+
maybe_name, function_template_info, Builtins::kNoBuiltinId, kind);
2582+
return shared;
25822583
}
25832584

25842585
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfoForBuiltin(
25852586
MaybeHandle<String> maybe_name, int builtin_index, FunctionKind kind) {
2586-
return NewSharedFunctionInfo(maybe_name, MaybeHandle<Code>(), builtin_index,
2587-
kind);
2587+
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(
2588+
maybe_name, MaybeHandle<Code>(), builtin_index, kind);
2589+
return shared;
25882590
}
25892591

25902592
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
@@ -2621,12 +2623,19 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
26212623
} else {
26222624
share->set_builtin_id(Builtins::kIllegal);
26232625
}
2624-
share->set_outer_scope_info(*the_hole_value());
2626+
// Generally functions won't have feedback, unless they have been created
2627+
// from a FunctionLiteral. Those can just reset this field to keep the
2628+
// SharedFunctionInfo in a consistent state.
2629+
if (maybe_builtin_index == Builtins::kCompileLazy) {
2630+
share->set_raw_outer_scope_info_or_feedback_metadata(*the_hole_value(),
2631+
SKIP_WRITE_BARRIER);
2632+
} else {
2633+
share->set_raw_outer_scope_info_or_feedback_metadata(
2634+
*empty_feedback_metadata(), SKIP_WRITE_BARRIER);
2635+
}
26252636
share->set_script(*undefined_value(), SKIP_WRITE_BARRIER);
26262637
share->set_debug_info(Smi::kZero, SKIP_WRITE_BARRIER);
26272638
share->set_function_identifier(*undefined_value(), SKIP_WRITE_BARRIER);
2628-
share->set_feedback_metadata(isolate()->heap()->empty_feedback_metadata(),
2629-
SKIP_WRITE_BARRIER);
26302639
share->set_function_literal_id(FunctionLiteral::kIdTypeInvalid);
26312640
#if V8_SFI_HAS_UNIQUE_ID
26322641
share->set_unique_id(isolate()->GetNextUniqueSharedFunctionInfoId());

src/factory.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,7 @@ class V8_EXPORT_PRIVATE Factory final {
805805
FunctionKind kind = kNormalFunction);
806806

807807
Handle<SharedFunctionInfo> NewSharedFunctionInfoForLiteral(
808-
FunctionLiteral* literal, Handle<Script> script);
808+
FunctionLiteral* literal, Handle<Script> script, bool is_toplevel);
809809

810810
static bool IsFunctionModeWithPrototype(FunctionMode function_mode) {
811811
return (function_mode & kWithPrototypeBits) != 0;

src/ic/accessor-assembler.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1910,8 +1910,8 @@ void AccessorAssembler::BranchIfStrictMode(Node* vector, Node* slot,
19101910
Label* if_strict) {
19111911
Node* sfi =
19121912
LoadObjectField(vector, FeedbackVector::kSharedFunctionInfoOffset);
1913-
Node* metadata =
1914-
LoadObjectField(sfi, SharedFunctionInfo::kFeedbackMetadataOffset);
1913+
TNode<FeedbackMetadata> metadata = CAST(LoadObjectField(
1914+
sfi, SharedFunctionInfo::kOuterScopeInfoOrFeedbackMetadataOffset));
19151915
Node* slot_int = SmiToInt32(slot);
19161916

19171917
// See VectorICComputer::index().

0 commit comments

Comments
 (0)