Commit a6e7d781 authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[nojit] Store a dedicated InterpreterEntryTrampoline copy on roots

V8 supports a mechanism to generate better profiling information for
ticks in bytecode execution. Usually, these would find the IET but would
not know which JS function is currently being executed. With
--interpreted_frames_native_stack, we create a dedicated copy of the
IET for each JS function, which the profiler can use the infer the
current function.

This mechanism doesn't work when IET is embedded. But JIT-less V8 will
require all builtins to be embedded.

This CL implements a workaround that should keep all configuration
happy: We keep a full copy of IET on the root list for sole purpose of
using it as a template to create copies for profiling later on. The
'real' IET builtin itself can be embedded in a follow-up CL.

Change-Id: Iaf1629708f0e41c3683979245019fbd3e3153c97
Reviewed-on: https://chromium-review.googlesource.com/c/1335700
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57548}
parent 8f4c5abf
...@@ -224,18 +224,11 @@ bool Builtins::IsIsolateIndependentBuiltin(const Code code) { ...@@ -224,18 +224,11 @@ bool Builtins::IsIsolateIndependentBuiltin(const Code code) {
bool Builtins::IsIsolateIndependent(int index) { bool Builtins::IsIsolateIndependent(int index) {
DCHECK(IsBuiltinId(index)); DCHECK(IsBuiltinId(index));
switch (index) { switch (index) {
// TODO(jgruber): There's currently two blockers for moving // TODO(jgruber): InterpreterEnterBytecode calculates a pointer into the
// InterpreterEntryTrampoline into the binary: // middle of InterpreterEntryTrampoline (see
// 1. InterpreterEnterBytecode calculates a pointer into the middle of // interpreter_entry_return_pc_offset). When the builtin is embedded, the
// InterpreterEntryTrampoline (see interpreter_entry_return_pc_offset). // pointer would need to be calculated at an offset from the embedded
// When the builtin is embedded, the pointer would need to be calculated // instruction stream (instead of the trampoline code object).
// at an offset from the embedded instruction stream (instead of the
// trampoline code object).
// 2. We create distinct copies of the trampoline to make it possible to
// attribute ticks in the interpreter to individual JS functions.
// See https://crrev.com/c/959081 and InstallBytecodeArray. When the
// trampoline is embedded, we need to ensure that CopyCode creates a copy
// of the builtin itself (and not just the trampoline).
case kInterpreterEntryTrampoline: case kInterpreterEntryTrampoline:
return false; return false;
default: default:
......
...@@ -314,8 +314,8 @@ void InstallBytecodeArray(Handle<BytecodeArray> bytecode_array, ...@@ -314,8 +314,8 @@ void InstallBytecodeArray(Handle<BytecodeArray> bytecode_array,
return; return;
} }
Handle<Code> code = isolate->factory()->CopyCode( Handle<Code> code = isolate->factory()->CopyCode(Handle<Code>::cast(
BUILTIN_CODE(isolate, InterpreterEntryTrampoline)); isolate->factory()->interpreter_entry_trampoline_for_profiling()));
Handle<InterpreterData> interpreter_data = Handle<InterpreterData>::cast( Handle<InterpreterData> interpreter_data = Handle<InterpreterData>::cast(
isolate->factory()->NewStruct(INTERPRETER_DATA_TYPE, TENURED)); isolate->factory()->NewStruct(INTERPRETER_DATA_TYPE, TENURED));
......
...@@ -5254,6 +5254,11 @@ void Heap::SetBuiltinsConstantsTable(FixedArray* cache) { ...@@ -5254,6 +5254,11 @@ void Heap::SetBuiltinsConstantsTable(FixedArray* cache) {
set_builtins_constants_table(cache); set_builtins_constants_table(cache);
} }
void Heap::SetInterpreterEntryTrampolineForProfiling(Code code) {
DCHECK_EQ(Builtins::kInterpreterEntryTrampoline, code->builtin_index());
set_interpreter_entry_trampoline_for_profiling(code);
}
void Heap::AddDirtyJSWeakFactory( void Heap::AddDirtyJSWeakFactory(
JSWeakFactory* weak_factory, JSWeakFactory* weak_factory,
std::function<void(HeapObject* object, ObjectSlot slot, Object* target)> std::function<void(HeapObject* object, ObjectSlot slot, Object* target)>
......
...@@ -683,6 +683,14 @@ class Heap { ...@@ -683,6 +683,14 @@ class Heap {
void SetBuiltinsConstantsTable(FixedArray* cache); void SetBuiltinsConstantsTable(FixedArray* cache);
// A full copy of the interpreter entry trampoline, used as a template to
// create copies of the builtin at runtime. The copies are used to create
// better profiling information for ticks in bytecode execution. Note that
// this is always a copy of the full builtin, i.e. not the off-heap
// trampoline.
// See also: FLAG_interpreted_frames_native_stack.
void SetInterpreterEntryTrampolineForProfiling(Code code);
// Add weak_factory into the dirty_js_weak_factories list. // Add weak_factory into the dirty_js_weak_factories list.
void AddDirtyJSWeakFactory( void AddDirtyJSWeakFactory(
JSWeakFactory* weak_factory, JSWeakFactory* weak_factory,
......
...@@ -702,6 +702,8 @@ void Heap::CreateInitialObjects() { ...@@ -702,6 +702,8 @@ void Heap::CreateInitialObjects() {
set_self_reference_marker( set_self_reference_marker(
*factory->NewSelfReferenceMarker(TENURED_READ_ONLY)); *factory->NewSelfReferenceMarker(TENURED_READ_ONLY));
set_interpreter_entry_trampoline_for_profiling(roots.undefined_value());
// Create the code_stubs dictionary. The initial size is set to avoid // Create the code_stubs dictionary. The initial size is set to avoid
// expanding the dictionary during bootstrapping. // expanding the dictionary during bootstrapping.
set_code_stubs(*SimpleNumberDictionary::New(isolate(), 128)); set_code_stubs(*SimpleNumberDictionary::New(isolate(), 128));
......
...@@ -3285,6 +3285,17 @@ bool Isolate::Init(StartupDeserializer* des) { ...@@ -3285,6 +3285,17 @@ bool Isolate::Init(StartupDeserializer* des) {
builtins_constants_table_builder_ = new BuiltinsConstantsTableBuilder(this); builtins_constants_table_builder_ = new BuiltinsConstantsTableBuilder(this);
} }
setup_delegate_->SetupBuiltins(this); setup_delegate_->SetupBuiltins(this);
if (create_heap_objects) {
// Create a copy of the the interpreter entry trampoline and store it
// on the root list. It is used as a template for further copies that
// may later be created to help profile interpreted code.
// TODO(jgruber): Merge this with the block below once
// FLAG_embedded_builtins is always true.
HandleScope handle_scope(this);
Handle<Code> code =
factory()->CopyCode(BUILTIN_CODE(this, InterpreterEntryTrampoline));
heap_.SetInterpreterEntryTrampolineForProfiling(*code);
}
if (FLAG_embedded_builtins && create_heap_objects) { if (FLAG_embedded_builtins && create_heap_objects) {
builtins_constants_table_builder_->Finalize(); builtins_constants_table_builder_->Finalize();
delete builtins_constants_table_builder_; delete builtins_constants_table_builder_;
......
...@@ -289,7 +289,9 @@ class RootVisitor; ...@@ -289,7 +289,9 @@ class RootVisitor;
/* JSWeakFactory objects which need cleanup */ \ /* JSWeakFactory objects which need cleanup */ \
V(Object*, dirty_js_weak_factories, DirtyJSWeakFactories) \ V(Object*, dirty_js_weak_factories, DirtyJSWeakFactories) \
/* KeepDuringJob set for JS WeakRefs */ \ /* KeepDuringJob set for JS WeakRefs */ \
V(HeapObject*, weak_refs_keep_during_job, WeakRefsKeepDuringJob) V(HeapObject*, weak_refs_keep_during_job, WeakRefsKeepDuringJob) \
V(HeapObject*, interpreter_entry_trampoline_for_profiling, \
InterpreterEntryTrampolineForProfiling)
// Entries in this list are limited to Smis and are not visited during GC. // Entries in this list are limited to Smis and are not visited during GC.
#define SMI_ROOT_LIST(V) \ #define SMI_ROOT_LIST(V) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment