Commit 17a5a3b7 authored by Andrew Comminos's avatar Andrew Comminos Committed by Commit Bot

[cpu-profiler] Clear code entries from BytecodeFlushEvents

When the CPU profiler receives a bytecode flush event, ensure that we
clear the appropriate CodeEntry.

Bug: v8:11054
Change-Id: I94e771e42192b75ea6d317738e4f2d5b76533dc8
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2691826Reviewed-by: 's avatarPeter Marshall <petermarshall@chromium.org>
Commit-Queue: Andrew Comminos <acomminos@fb.com>
Cr-Commit-Position: refs/heads/master@{#72684}
parent ec6df835
......@@ -64,6 +64,10 @@ TickSample* SamplingEventsProcessor::StartTickSample() {
return &evt->sample;
}
void BytecodeFlushEventRecord::UpdateCodeMap(CodeMap* code_map) {
code_map->ClearCodesInRange(instruction_start, instruction_start + 1);
}
void SamplingEventsProcessor::FinishTickSample() {
ticks_buffer_.FinishEnqueue();
}
......
......@@ -196,6 +196,7 @@ void ProfilerEventsProcessor::CodeEventHandler(
case CodeEventRecord::CODE_CREATION:
case CodeEventRecord::CODE_MOVE:
case CodeEventRecord::CODE_DISABLE_OPT:
case CodeEventRecord::BYTECODE_FLUSH:
Enqueue(evt_rec);
break;
case CodeEventRecord::CODE_DEOPT: {
......
......@@ -34,7 +34,8 @@ class Symbolizer;
V(CODE_MOVE, CodeMoveEventRecord) \
V(CODE_DISABLE_OPT, CodeDisableOptEventRecord) \
V(CODE_DEOPT, CodeDeoptEventRecord) \
V(REPORT_BUILTIN, ReportBuiltinEventRecord)
V(REPORT_BUILTIN, ReportBuiltinEventRecord) \
V(BYTECODE_FLUSH, BytecodeFlushEventRecord)
class CodeEventRecord {
public:
......@@ -111,6 +112,13 @@ class TickSampleEventRecord {
TickSample sample;
};
class BytecodeFlushEventRecord : public CodeEventRecord {
public:
Address instruction_start;
V8_INLINE void UpdateCodeMap(CodeMap* code_map);
};
// A record type for sending code events (e.g. create, move, delete) to the
// profiling thread.
class CodeEventsContainer {
......
......@@ -406,6 +406,7 @@ class V8_EXPORT_PRIVATE CodeMap {
void AddCode(Address addr, CodeEntry* entry, unsigned size);
void MoveCode(Address from, Address to);
void ClearCodesInRange(Address start, Address end);
CodeEntry* FindEntry(Address addr, Address* out_instruction_start = nullptr);
void Print();
......@@ -417,7 +418,6 @@ class V8_EXPORT_PRIVATE CodeMap {
unsigned size;
};
void ClearCodesInRange(Address start, Address end);
void DeleteCodeEntry(CodeEntry*);
std::map<Address, CodeEntryMapInfo> code_map_;
......
......@@ -300,7 +300,11 @@ void ProfilerListener::CodeDeoptEvent(Handle<Code> code, DeoptimizeKind kind,
}
void ProfilerListener::BytecodeFlushEvent(Address compiled_data_start) {
// TODO(acomminos): Post flush event to profiler thread.
CodeEventsContainer evt_rec(CodeEventRecord::BYTECODE_FLUSH);
BytecodeFlushEventRecord* rec = &evt_rec.BytecodeFlushEventRecord_;
rec->instruction_start = compiled_data_start + BytecodeArray::kHeaderSize;
DispatchCodeEvent(evt_rec);
}
const char* ProfilerListener::GetName(Vector<const char> name) {
......
......@@ -4074,6 +4074,77 @@ TEST(FastApiCPUProfiler) {
#endif
}
TEST(BytecodeFlushEventsEagerLogging) {
#ifndef V8_LITE_MODE
FLAG_opt = false;
FLAG_always_opt = false;
i::FLAG_optimize_for_size = false;
#endif // V8_LITE_MODE
i::FLAG_flush_bytecode = true;
i::FLAG_allow_natives_syntax = true;
TestSetup test_setup;
ManualGCScope manual_gc_scope;
CcTest::InitializeVM();
v8::Isolate* isolate = CcTest::isolate();
Isolate* i_isolate = CcTest::i_isolate();
Factory* factory = i_isolate->factory();
CpuProfiler profiler(i_isolate, kDebugNaming, kEagerLogging);
CodeMap* code_map = profiler.code_map_for_test();
{
v8::HandleScope scope(isolate);
v8::Context::New(isolate)->Enter();
const char* source =
"function foo() {"
" var x = 42;"
" var y = 42;"
" var z = x + y;"
"};"
"foo()";
Handle<String> foo_name = factory->InternalizeUtf8String("foo");
// This compile will add the code to the compilation cache.
{
v8::HandleScope scope(isolate);
CompileRun(source);
}
// Check function is compiled.
Handle<Object> func_value =
Object::GetProperty(i_isolate, i_isolate->global_object(), foo_name)
.ToHandleChecked();
CHECK(func_value->IsJSFunction());
Handle<JSFunction> function = Handle<JSFunction>::cast(func_value);
CHECK(function->shared().is_compiled());
i::BytecodeArray compiled_data =
function->shared().GetBytecodeArray(i_isolate);
i::Address bytecode_start = compiled_data.GetFirstBytecodeAddress();
CHECK(code_map->FindEntry(bytecode_start));
// The code will survive at least two GCs.
CcTest::CollectAllGarbage();
CcTest::CollectAllGarbage();
CHECK(function->shared().is_compiled());
// Simulate several GCs that use full marking.
const int kAgingThreshold = 6;
for (int i = 0; i < kAgingThreshold; i++) {
CcTest::CollectAllGarbage();
}
// foo should no longer be in the compilation cache
CHECK(!function->shared().is_compiled());
CHECK(!function->is_compiled());
CHECK(!code_map->FindEntry(bytecode_start));
}
}
} // namespace test_cpu_profiler
} // namespace internal
} // namespace v8
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