13
13
namespace v8 {
14
14
namespace internal {
15
15
16
- ProfilerListener::ProfilerListener (Isolate* isolate)
17
- : function_and_resource_names_(isolate->heap ()) {}
16
+ ProfilerListener::ProfilerListener (Isolate* isolate,
17
+ CodeEventObserver* observer)
18
+ : isolate_(isolate),
19
+ observer_ (observer),
20
+ function_and_resource_names_(isolate->heap ()->HashSeed()) {}
18
21
19
22
ProfilerListener::~ProfilerListener () = default ;
20
23
21
24
void ProfilerListener::CallbackEvent (Name* name, Address entry_point) {
22
25
CodeEventsContainer evt_rec (CodeEventRecord::CODE_CREATION);
23
26
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_ ;
24
- rec->start = entry_point;
27
+ rec->instruction_start = entry_point;
25
28
rec->entry = NewCodeEntry (CodeEventListener::CALLBACK_TAG, GetName (name));
26
- rec->size = 1 ;
29
+ rec->instruction_size = 1 ;
27
30
DispatchCodeEvent (evt_rec);
28
31
}
29
32
30
33
void ProfilerListener::CodeCreateEvent (CodeEventListener::LogEventsAndTags tag,
31
34
AbstractCode* code, const char * name) {
32
35
CodeEventsContainer evt_rec (CodeEventRecord::CODE_CREATION);
33
36
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_ ;
34
- rec->start = code->address ();
37
+ rec->instruction_start = code->instruction_start ();
35
38
rec->entry = NewCodeEntry (
36
- tag, GetFunctionName (name), CodeEntry:: kEmptyNamePrefix ,
39
+ tag, GetFunctionName (name),
37
40
CodeEntry::kEmptyResourceName , CpuProfileNode::kNoLineNumberInfo ,
38
- CpuProfileNode::kNoColumnNumberInfo , NULL , code->instruction_start ());
41
+ CpuProfileNode::kNoColumnNumberInfo , nullptr , code->instruction_start ());
39
42
RecordInliningInfo (rec->entry , code);
40
- rec->size = code->ExecutableSize ();
43
+ rec->instruction_size = code->instruction_size ();
41
44
DispatchCodeEvent (evt_rec);
42
45
}
43
46
44
47
void ProfilerListener::CodeCreateEvent (CodeEventListener::LogEventsAndTags tag,
45
48
AbstractCode* code, Name* name) {
46
49
CodeEventsContainer evt_rec (CodeEventRecord::CODE_CREATION);
47
50
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_ ;
48
- rec->start = code->address ();
51
+ rec->instruction_start = code->instruction_start ();
49
52
rec->entry = NewCodeEntry (
50
- tag, GetFunctionName (name), CodeEntry:: kEmptyNamePrefix ,
53
+ tag, GetFunctionName (name),
51
54
CodeEntry::kEmptyResourceName , CpuProfileNode::kNoLineNumberInfo ,
52
- CpuProfileNode::kNoColumnNumberInfo , NULL , code->instruction_start ());
55
+ CpuProfileNode::kNoColumnNumberInfo , nullptr , code->instruction_start ());
53
56
RecordInliningInfo (rec->entry , code);
54
- rec->size = code->ExecutableSize ();
57
+ rec->instruction_size = code->instruction_size ();
55
58
DispatchCodeEvent (evt_rec);
56
59
}
57
60
@@ -61,15 +64,15 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
61
64
Name* script_name) {
62
65
CodeEventsContainer evt_rec (CodeEventRecord::CODE_CREATION);
63
66
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_ ;
64
- rec->start = code->address ();
67
+ rec->instruction_start = code->instruction_start ();
65
68
rec->entry = NewCodeEntry (
66
- tag, GetFunctionName (shared->DebugName ()), CodeEntry:: kEmptyNamePrefix ,
69
+ tag, GetFunctionName (shared->DebugName ()),
67
70
GetName (InferScriptName (script_name, shared)),
68
71
CpuProfileNode::kNoLineNumberInfo , CpuProfileNode::kNoColumnNumberInfo ,
69
- NULL , code->instruction_start ());
72
+ nullptr , code->instruction_start ());
70
73
RecordInliningInfo (rec->entry , code);
71
74
rec->entry ->FillFunctionInfo (shared);
72
- rec->size = code->ExecutableSize ();
75
+ rec->instruction_size = code->instruction_size ();
73
76
DispatchCodeEvent (evt_rec);
74
77
}
75
78
@@ -80,13 +83,11 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
80
83
int column) {
81
84
CodeEventsContainer evt_rec (CodeEventRecord::CODE_CREATION);
82
85
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_ ;
83
- rec->start = abstract_code->address ();
84
- JITLineInfoTable* line_table = NULL ;
86
+ rec->instruction_start = abstract_code->instruction_start ();
87
+ std::unique_ptr<SourcePositionTable> line_table;
85
88
if (shared->script ()->IsScript ()) {
86
89
Script* script = Script::cast (shared->script ());
87
- line_table = new JITLineInfoTable ();
88
- int offset = abstract_code->IsCode () ? Code::kHeaderSize
89
- : BytecodeArray::kHeaderSize ;
90
+ line_table.reset (new SourcePositionTable ());
90
91
for (SourcePositionTableIterator it (abstract_code->source_position_table ());
91
92
!it.done (); it.Advance ()) {
92
93
// TODO(alph,tebbi) Skipping inlined positions for now, because they might
@@ -95,48 +96,46 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
95
96
continue ;
96
97
int position = it.source_position ().ScriptOffset ();
97
98
int line_number = script->GetLineNumber (position) + 1 ;
98
- int pc_offset = it.code_offset () + offset;
99
- line_table->SetPosition (pc_offset, line_number);
99
+ line_table->SetPosition (it.code_offset (), line_number);
100
100
}
101
101
}
102
- rec->entry = NewCodeEntry (
103
- tag, GetFunctionName (shared->DebugName ()), CodeEntry:: kEmptyNamePrefix ,
104
- GetName (InferScriptName (script_name, shared)), line, column, line_table ,
105
- abstract_code->instruction_start ());
102
+ rec->entry =
103
+ NewCodeEntry ( tag, GetFunctionName (shared->DebugName ()),
104
+ GetName (InferScriptName (script_name, shared)), line, column,
105
+ std::move (line_table), abstract_code->instruction_start ());
106
106
RecordInliningInfo (rec->entry , abstract_code);
107
- RecordDeoptInlinedFrames (rec->entry , abstract_code);
108
107
rec->entry ->FillFunctionInfo (shared);
109
- rec->size = abstract_code->ExecutableSize ();
108
+ rec->instruction_size = abstract_code->instruction_size ();
110
109
DispatchCodeEvent (evt_rec);
111
110
}
112
111
113
112
void ProfilerListener::CodeCreateEvent (CodeEventListener::LogEventsAndTags tag,
114
113
AbstractCode* code, int args_count) {
115
114
CodeEventsContainer evt_rec (CodeEventRecord::CODE_CREATION);
116
115
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_ ;
117
- rec->start = code->address ();
116
+ rec->instruction_start = code->instruction_start ();
118
117
rec->entry = NewCodeEntry (
119
- tag, GetName (args_count), " args_count: " , CodeEntry::kEmptyResourceName ,
118
+ tag, GetName (args_count), CodeEntry::kEmptyResourceName ,
120
119
CpuProfileNode::kNoLineNumberInfo , CpuProfileNode::kNoColumnNumberInfo ,
121
- NULL , code->instruction_start ());
120
+ nullptr , code->instruction_start ());
122
121
RecordInliningInfo (rec->entry , code);
123
- rec->size = code->ExecutableSize ();
122
+ rec->instruction_size = code->instruction_size ();
124
123
DispatchCodeEvent (evt_rec);
125
124
}
126
125
127
- void ProfilerListener::CodeMoveEvent (AbstractCode* from, Address to) {
126
+ void ProfilerListener::CodeMoveEvent (AbstractCode* from, AbstractCode* to) {
128
127
CodeEventsContainer evt_rec (CodeEventRecord::CODE_MOVE);
129
128
CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_ ;
130
- rec->from = from->address ();
131
- rec->to = to;
129
+ rec->from_instruction_start = from->instruction_start ();
130
+ rec->to_instruction_start = to-> instruction_start () ;
132
131
DispatchCodeEvent (evt_rec);
133
132
}
134
133
135
134
void ProfilerListener::CodeDisableOptEvent (AbstractCode* code,
136
135
SharedFunctionInfo* shared) {
137
136
CodeEventsContainer evt_rec (CodeEventRecord::CODE_DISABLE_OPT);
138
137
CodeDisableOptEventRecord* rec = &evt_rec.CodeDisableOptEventRecord_ ;
139
- rec->start = code->address ();
138
+ rec->instruction_start = code->instruction_start ();
140
139
rec->bailout_reason = GetBailoutReason (shared->disable_optimization_reason ());
141
140
DispatchCodeEvent (evt_rec);
142
141
}
@@ -146,44 +145,48 @@ void ProfilerListener::CodeDeoptEvent(Code* code, DeoptKind kind, Address pc,
146
145
CodeEventsContainer evt_rec (CodeEventRecord::CODE_DEOPT);
147
146
CodeDeoptEventRecord* rec = &evt_rec.CodeDeoptEventRecord_ ;
148
147
Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo (code, pc);
149
- rec->start = code->address ();
148
+ rec->instruction_start = code->instruction_start ();
150
149
rec->deopt_reason = DeoptimizeReasonToString (info.deopt_reason );
151
150
rec->deopt_id = info.deopt_id ;
152
151
rec->pc = reinterpret_cast <void *>(pc);
153
152
rec->fp_to_sp_delta = fp_to_sp_delta;
153
+
154
+ // When a function is deoptimized, we store the deoptimized frame information
155
+ // for the use of GetDeoptInfos().
156
+ AttachDeoptInlinedFrames (code, rec);
154
157
DispatchCodeEvent (evt_rec);
155
158
}
156
159
157
160
void ProfilerListener::GetterCallbackEvent (Name* name, Address entry_point) {
158
161
CodeEventsContainer evt_rec (CodeEventRecord::CODE_CREATION);
159
162
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_ ;
160
- rec->start = entry_point;
163
+ rec->instruction_start = entry_point;
161
164
rec->entry =
162
- NewCodeEntry (CodeEventListener::CALLBACK_TAG, GetName (name), " get " );
163
- rec->size = 1 ;
165
+ NewCodeEntry (CodeEventListener::CALLBACK_TAG, GetConsName ( " get " , name) );
166
+ rec->instruction_size = 1 ;
164
167
DispatchCodeEvent (evt_rec);
165
168
}
166
169
167
170
void ProfilerListener::RegExpCodeCreateEvent (AbstractCode* code,
168
171
String* source) {
169
172
CodeEventsContainer evt_rec (CodeEventRecord::CODE_CREATION);
170
173
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_ ;
171
- rec->start = code->address ();
174
+ rec->instruction_start = code->instruction_start ();
172
175
rec->entry = NewCodeEntry (
173
- CodeEventListener::REG_EXP_TAG, GetName (source), " RegExp: " ,
176
+ CodeEventListener::REG_EXP_TAG, GetConsName ( " RegExp: " , source) ,
174
177
CodeEntry::kEmptyResourceName , CpuProfileNode::kNoLineNumberInfo ,
175
- CpuProfileNode::kNoColumnNumberInfo , NULL , code->instruction_start ());
176
- rec->size = code->ExecutableSize ();
178
+ CpuProfileNode::kNoColumnNumberInfo , nullptr , code->instruction_start ());
179
+ rec->instruction_size = code->instruction_size ();
177
180
DispatchCodeEvent (evt_rec);
178
181
}
179
182
180
183
void ProfilerListener::SetterCallbackEvent (Name* name, Address entry_point) {
181
184
CodeEventsContainer evt_rec (CodeEventRecord::CODE_CREATION);
182
185
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_ ;
183
- rec->start = entry_point;
186
+ rec->instruction_start = entry_point;
184
187
rec->entry =
185
- NewCodeEntry (CodeEventListener::CALLBACK_TAG, GetName (name), " set " );
186
- rec->size = 1 ;
188
+ NewCodeEntry (CodeEventListener::CALLBACK_TAG, GetConsName ( " set " , name) );
189
+ rec->instruction_size = 1 ;
187
190
DispatchCodeEvent (evt_rec);
188
191
}
189
192
@@ -212,7 +215,7 @@ void ProfilerListener::RecordInliningInfo(CodeEntry* entry,
212
215
DCHECK_EQ (Translation::BEGIN, opcode);
213
216
it.Skip (Translation::NumberOfOperandsFor (opcode));
214
217
int depth = 0 ;
215
- std::vector<CodeEntry* > inline_stack;
218
+ std::vector<std::unique_ptr< CodeEntry> > inline_stack;
216
219
while (it.HasNext () &&
217
220
Translation::BEGIN !=
218
221
(opcode = static_cast <Translation::Opcode>(it.Next ()))) {
@@ -234,29 +237,31 @@ void ProfilerListener::RecordInliningInfo(CodeEntry* entry,
234
237
235
238
CodeEntry* inline_entry =
236
239
new CodeEntry (entry->tag (), GetFunctionName (shared_info->DebugName ()),
237
- CodeEntry:: kEmptyNamePrefix , resource_name,
240
+ resource_name,
238
241
CpuProfileNode::kNoLineNumberInfo ,
239
242
CpuProfileNode::kNoColumnNumberInfo , nullptr ,
240
243
code->instruction_start ());
241
244
inline_entry->FillFunctionInfo (shared_info);
242
- inline_stack.push_back (inline_entry);
245
+ inline_stack.emplace_back (inline_entry);
243
246
}
244
247
if (!inline_stack.empty ()) {
245
248
entry->AddInlineStack (pc_offset, std::move (inline_stack));
246
249
}
247
250
}
248
251
}
249
252
250
- void ProfilerListener::RecordDeoptInlinedFrames (CodeEntry* entry,
251
- AbstractCode* abstract_code) {
252
- if (abstract_code->kind () != AbstractCode::OPTIMIZED_FUNCTION) return ;
253
- Handle <Code> code (abstract_code->GetCode ());
254
-
253
+ void ProfilerListener::AttachDeoptInlinedFrames (Code* code,
254
+ CodeDeoptEventRecord* rec) {
255
+ int deopt_id = rec->deopt_id ;
255
256
SourcePosition last_position = SourcePosition::Unknown ();
256
257
int mask = RelocInfo::ModeMask (RelocInfo::DEOPT_ID) |
257
258
RelocInfo::ModeMask (RelocInfo::DEOPT_SCRIPT_OFFSET) |
258
259
RelocInfo::ModeMask (RelocInfo::DEOPT_INLINING_ID);
259
- for (RelocIterator it (*code, mask); !it.done (); it.next ()) {
260
+
261
+ rec->deopt_frames = nullptr ;
262
+ rec->deopt_frame_count = 0 ;
263
+
264
+ for (RelocIterator it (code, mask); !it.done (); it.next ()) {
260
265
RelocInfo* info = it.rinfo ();
261
266
if (info->rmode () == RelocInfo::DEOPT_SCRIPT_OFFSET) {
262
267
int script_offset = static_cast <int >(info->data ());
@@ -267,52 +272,39 @@ void ProfilerListener::RecordDeoptInlinedFrames(CodeEntry* entry,
267
272
continue ;
268
273
}
269
274
if (info->rmode () == RelocInfo::DEOPT_ID) {
270
- int deopt_id = static_cast <int >(info->data ());
275
+ if ( deopt_id ! = static_cast <int >(info->data ())) continue ;
271
276
DCHECK (last_position.IsKnown ());
272
- std::vector<CpuProfileDeoptFrame> inlined_frames;
273
- for (SourcePositionInfo& pos_info : last_position.InliningStack (code)) {
274
- DCHECK (pos_info.position .ScriptOffset () != kNoSourcePosition );
277
+
278
+ // SourcePosition::InliningStack allocates a handle for the SFI of each
279
+ // frame. These don't escape this function, but quickly add up. This
280
+ // scope limits their lifetime.
281
+ HandleScope scope (isolate_);
282
+ std::vector<SourcePositionInfo> stack =
283
+ last_position.InliningStack (handle (code));
284
+ CpuProfileDeoptFrame* deopt_frames =
285
+ new CpuProfileDeoptFrame[stack.size ()];
286
+
287
+ int deopt_frame_count = 0 ;
288
+ for (SourcePositionInfo& pos_info : stack) {
289
+ if (pos_info.position .ScriptOffset () == kNoSourcePosition ) continue ;
275
290
if (!pos_info.function ->script ()->IsScript ()) continue ;
276
291
int script_id = Script::cast (pos_info.function ->script ())->id ();
277
292
size_t offset = static_cast <size_t >(pos_info.position .ScriptOffset ());
278
- inlined_frames.push_back (CpuProfileDeoptFrame ({script_id, offset}));
279
- }
280
- if (!inlined_frames.empty () &&
281
- !entry->HasDeoptInlinedFramesFor (deopt_id)) {
282
- entry->AddDeoptInlinedFrames (deopt_id, std::move (inlined_frames));
293
+ deopt_frames[deopt_frame_count++] = {script_id, offset};
283
294
}
295
+ rec->deopt_frames = deopt_frames;
296
+ rec->deopt_frame_count = deopt_frame_count;
297
+ break ;
284
298
}
285
299
}
286
300
}
287
301
288
302
CodeEntry* ProfilerListener::NewCodeEntry (
289
303
CodeEventListener::LogEventsAndTags tag, const char * name,
290
- const char * name_prefix, const char * resource_name, int line_number,
291
- int column_number, JITLineInfoTable* line_info, Address instruction_start) {
292
- std::unique_ptr<CodeEntry> code_entry = base::make_unique<CodeEntry>(
293
- tag, name, name_prefix, resource_name, line_number, column_number,
294
- line_info, instruction_start);
295
- CodeEntry* raw_code_entry = code_entry.get ();
296
- code_entries_.push_back (std::move (code_entry));
297
- return raw_code_entry;
298
- }
299
-
300
- void ProfilerListener::AddObserver (CodeEventObserver* observer) {
301
- base::LockGuard<base::Mutex> guard (&mutex_);
302
- if (observers_.empty ()) {
303
- code_entries_.clear ();
304
- }
305
- if (std::find (observers_.begin (), observers_.end (), observer) ==
306
- observers_.end ()) {
307
- observers_.push_back (observer);
308
- }
309
- }
310
-
311
- void ProfilerListener::RemoveObserver (CodeEventObserver* observer) {
312
- base::LockGuard<base::Mutex> guard (&mutex_);
313
- auto it = std::find (observers_.begin (), observers_.end (), observer);
314
- if (it == observers_.end ()) return ;
315
- observers_.erase (it);
304
+ const char * resource_name, int line_number, int column_number,
305
+ std::unique_ptr<SourcePositionTable> line_info, Address instruction_start) {
306
+ return new CodeEntry (tag, name, resource_name, line_number, column_number,
307
+ std::move (line_info), instruction_start);
316
308
}
317
309
318
310
} // namespace internal
0 commit comments