Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(236)

Side by Side Diff: src/profiler/tick-sample.cc

Issue 2189513002: Move SimulatorHelper into V8 out of profiler clients. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Address alph's comments Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/profiler/tick-sample.h" 5 #include "src/profiler/tick-sample.h"
6 6
7 #include "include/v8-profiler.h" 7 #include "include/v8-profiler.h"
8 #include "src/frames-inl.h" 8 #include "src/frames-inl.h"
9 #include "src/msan.h" 9 #include "src/msan.h"
10 #include "src/simulator.h" 10 #include "src/simulator.h"
11 #include "src/vm-state-inl.h" 11 #include "src/vm-state-inl.h"
12 12
13 namespace v8 { 13 namespace v8 {
14
15 namespace { 14 namespace {
16 15
17 bool IsSamePage(i::byte* ptr1, i::byte* ptr2) { 16 bool IsSamePage(i::byte* ptr1, i::byte* ptr2) {
18 const uint32_t kPageSize = 4096; 17 const uint32_t kPageSize = 4096;
19 uintptr_t mask = ~static_cast<uintptr_t>(kPageSize - 1); 18 uintptr_t mask = ~static_cast<uintptr_t>(kPageSize - 1);
20 return (reinterpret_cast<uintptr_t>(ptr1) & mask) == 19 return (reinterpret_cast<uintptr_t>(ptr1) & mask) ==
21 (reinterpret_cast<uintptr_t>(ptr2) & mask); 20 (reinterpret_cast<uintptr_t>(ptr2) & mask);
22 } 21 }
23 22
24 // Check if the code at specified address could potentially be a 23 // Check if the code at specified address could potentially be a
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 if (!memcmp(pc, pattern->bytes + offset, pattern->bytes_count - offset)) 69 if (!memcmp(pc, pattern->bytes + offset, pattern->bytes_count - offset))
71 return true; 70 return true;
72 } 71 }
73 } 72 }
74 } 73 }
75 return false; 74 return false;
76 } 75 }
77 76
78 } // namespace 77 } // namespace
79 78
79 namespace internal {
80 namespace {
81
82 #if defined(USE_SIMULATOR)
83 class SimulatorHelper {
84 public:
85 // Returns true if register values were successfully retrieved
86 // from the simulator, otherwise returns false.
87 static bool FillRegisters(Isolate* isolate, v8::RegisterState* state);
88 };
89
90 bool SimulatorHelper::FillRegisters(Isolate* isolate,
91 v8::RegisterState* state) {
92 Simulator* simulator = isolate->thread_local_top()->simulator_;
93 // Check if there is active simulator.
94 if (simulator == NULL) return false;
95 #if V8_TARGET_ARCH_ARM
96 if (!simulator->has_bad_pc()) {
97 state->pc = reinterpret_cast<Address>(simulator->get_pc());
98 }
99 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
100 state->fp =
101 reinterpret_cast<Address>(simulator->get_register(Simulator::r11));
102 #elif V8_TARGET_ARCH_ARM64
103 state->pc = reinterpret_cast<Address>(simulator->pc());
104 state->sp = reinterpret_cast<Address>(simulator->sp());
105 state->fp = reinterpret_cast<Address>(simulator->fp());
106 #elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
107 if (!simulator->has_bad_pc()) {
108 state->pc = reinterpret_cast<Address>(simulator->get_pc());
109 }
110 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
111 state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
112 #elif V8_TARGET_ARCH_PPC
113 if (!simulator->has_bad_pc()) {
114 state->pc = reinterpret_cast<Address>(simulator->get_pc());
115 }
116 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
117 state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
118 #elif V8_TARGET_ARCH_S390
119 if (!simulator->has_bad_pc()) {
120 state->pc = reinterpret_cast<Address>(simulator->get_pc());
121 }
122 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
123 state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
124 #endif
125 if (state->sp == 0 || state->fp == 0) {
126 // It possible that the simulator is interrupted while it is updating
127 // the sp or fp register. ARM64 simulator does this in two steps:
128 // first setting it to zero and then setting it to the new value.
129 // Bailout if sp/fp doesn't contain the new value.
130 //
131 // FIXME: The above doesn't really solve the issue.
132 // If a 64-bit target is executed on a 32-bit host even the final
133 // write is non-atomic, so it might obtain a half of the result.
134 // Moreover as long as the register set code uses memcpy (as of now),
135 // it is not guaranteed to be atomic even when both host and target
136 // are of same bitness.
137 return false;
138 }
139 return true;
140 }
141 #endif // USE_SIMULATOR
142
143 } // namespace
144 } // namespace internal
145
80 // 146 //
81 // StackTracer implementation 147 // StackTracer implementation
82 // 148 //
83 DISABLE_ASAN void TickSample::Init(Isolate* v8_isolate, 149 DISABLE_ASAN void TickSample::Init(Isolate* v8_isolate,
84 const RegisterState& regs, 150 const RegisterState& reg_state,
alph 2016/08/09 19:03:41 state
lpy 2016/08/10 05:50:03 TickSample already has a different type of data me
85 RecordCEntryFrame record_c_entry_frame, 151 RecordCEntryFrame record_c_entry_frame,
86 bool update_stats) { 152 bool update_stats, bool update_state) {
87 this->update_stats = update_stats; 153 this->update_stats = update_stats;
88
89 SampleInfo info; 154 SampleInfo info;
90 if (GetStackSample(v8_isolate, const_cast<RegisterState&>(regs), 155 RegisterState regs = reg_state;
91 record_c_entry_frame, reinterpret_cast<void**>(&stack[0]), 156 if (!GetStackSample(v8_isolate, &regs, record_c_entry_frame, stack,
92 kMaxFramesCount, &info)) { 157 kMaxFramesCount, &info, update_state)) {
93 state = info.vm_state;
94 pc = regs.pc;
95 frames_count = static_cast<unsigned>(info.frames_count);
96 has_external_callback = info.external_callback_entry != nullptr;
97 if (has_external_callback) {
98 external_callback_entry = info.external_callback_entry;
99 } else if (frames_count) {
100 // sp register may point at an arbitrary place in memory, make
101 // sure MSAN doesn't complain about it.
102 MSAN_MEMORY_IS_INITIALIZED(regs.sp, sizeof(void*));
103 // Sample potential return address value for frameless invocation of
104 // stubs (we'll figure out later, if this value makes sense).
105 tos = i::Memory::Address_at(reinterpret_cast<i::Address>(regs.sp));
106 } else {
107 tos = nullptr;
108 }
109 } else {
110 // It is executing JS but failed to collect a stack trace. 158 // It is executing JS but failed to collect a stack trace.
111 // Mark the sample as spoiled. 159 // Mark the sample as spoiled.
112 pc = nullptr; 160 pc = nullptr;
161 return;
162 }
163
164 state = info.vm_state;
165 pc = regs.pc;
166 frames_count = static_cast<unsigned>(info.frames_count);
167 has_external_callback = info.external_callback_entry != nullptr;
168 if (has_external_callback) {
169 external_callback_entry = info.external_callback_entry;
170 } else if (frames_count) {
171 // sp register may point at an arbitrary place in memory, make
172 // sure MSAN doesn't complain about it.
173 MSAN_MEMORY_IS_INITIALIZED(regs.sp, sizeof(void*));
174 // Sample potential return address value for frameless invocation of
175 // stubs (we'll figure out later, if this value makes sense).
176 tos = i::Memory::Address_at(reinterpret_cast<i::Address>(regs.sp));
177 } else {
178 tos = nullptr;
113 } 179 }
114 } 180 }
115 181
116 bool TickSample::GetStackSample(Isolate* v8_isolate, const RegisterState& regs, 182 bool TickSample::GetStackSample(Isolate* v8_isolate, RegisterState* regs,
117 RecordCEntryFrame record_c_entry_frame, 183 RecordCEntryFrame record_c_entry_frame,
118 void** frames, size_t frames_limit, 184 void** frames, size_t frames_limit,
119 v8::SampleInfo* sample_info) { 185 v8::SampleInfo* sample_info,
186 bool update_state) {
120 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 187 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
121 sample_info->frames_count = 0; 188 sample_info->frames_count = 0;
122 sample_info->vm_state = isolate->current_vm_state(); 189 sample_info->vm_state = isolate->current_vm_state();
123 sample_info->external_callback_entry = nullptr; 190 sample_info->external_callback_entry = nullptr;
124 if (sample_info->vm_state == GC) return true; 191 if (sample_info->vm_state == GC) return true;
125 192
126 i::Address js_entry_sp = isolate->js_entry_sp(); 193 i::Address js_entry_sp = isolate->js_entry_sp();
127 if (js_entry_sp == nullptr) return true; // Not executing JS now. 194 if (js_entry_sp == nullptr) return true; // Not executing JS now.
128 DCHECK(regs.sp);
129 195
130 if (regs.pc && IsNoFrameRegion(static_cast<i::Address>(regs.pc))) { 196 #if defined(USE_SIMULATOR)
131 // Can't collect stack. 197 if (update_state) {
alph 2016/08/09 19:03:41 update_state is never referenced when not under si
lpy 2016/08/10 05:50:03 Done.
198 if (!i::SimulatorHelper::FillRegisters(isolate, regs)) return false;
199 }
200 #endif
201 DCHECK(regs->sp);
202
203 if (regs->pc && IsNoFrameRegion(static_cast<i::Address>(regs->pc))) {
204 // The frame is not setup, so it'd be hard to iterate the stack. Bailout.
132 return false; 205 return false;
133 } 206 }
134 207
135 i::ExternalCallbackScope* scope = isolate->external_callback_scope(); 208 i::ExternalCallbackScope* scope = isolate->external_callback_scope();
136 i::Address handler = i::Isolate::handler(isolate->thread_local_top()); 209 i::Address handler = i::Isolate::handler(isolate->thread_local_top());
137 // If there is a handler on top of the external callback scope then 210 // If there is a handler on top of the external callback scope then
138 // we have already entrered JavaScript again and the external callback 211 // we have already entrered JavaScript again and the external callback
139 // is not the top function. 212 // is not the top function.
140 if (scope && scope->scope_address() < handler) { 213 if (scope && scope->scope_address() < handler) {
141 sample_info->external_callback_entry = 214 sample_info->external_callback_entry =
142 *scope->callback_entrypoint_address(); 215 *scope->callback_entrypoint_address();
143 } 216 }
144 217
145 i::SafeStackFrameIterator it(isolate, reinterpret_cast<i::Address>(regs.fp), 218 i::SafeStackFrameIterator it(isolate, reinterpret_cast<i::Address>(regs->fp),
146 reinterpret_cast<i::Address>(regs.sp), 219 reinterpret_cast<i::Address>(regs->sp),
147 js_entry_sp); 220 js_entry_sp);
148 221
149 // If at this point iterator does not see any frames, 222 // If at this point iterator does not see any frames,
150 // is usually means something is wrong with the FP, 223 // is usually means something is wrong with the FP,
151 // e.g. it is used as a general purpose register in the function. 224 // e.g. it is used as a general purpose register in the function.
152 // Bailout. 225 // Bailout.
153 if (it.done()) return false; 226 if (it.done()) return false;
154 227
155 size_t i = 0; 228 size_t i = 0;
156 if (record_c_entry_frame == kIncludeCEntryFrame && 229 if (record_c_entry_frame == kIncludeCEntryFrame &&
(...skipping 16 matching lines...) Expand all
173 frames[i++] = bytecode_array + i::BytecodeArray::kHeaderSize + 246 frames[i++] = bytecode_array + i::BytecodeArray::kHeaderSize +
174 frame->GetBytecodeOffset(); 247 frame->GetBytecodeOffset();
175 } 248 }
176 sample_info->frames_count = i; 249 sample_info->frames_count = i;
177 return true; 250 return true;
178 } 251 }
179 252
180 namespace internal { 253 namespace internal {
181 254
182 void TickSample::Init(Isolate* isolate, const v8::RegisterState& state, 255 void TickSample::Init(Isolate* isolate, const v8::RegisterState& state,
183 RecordCEntryFrame record_c_entry_frame, 256 RecordCEntryFrame record_c_entry_frame, bool update_stats,
184 bool update_stats) { 257 bool update_state) {
185 v8::TickSample::Init(reinterpret_cast<v8::Isolate*>(isolate), state, 258 v8::TickSample::Init(reinterpret_cast<v8::Isolate*>(isolate), state,
186 record_c_entry_frame, update_stats); 259 record_c_entry_frame, update_stats, update_state);
187 if (pc == nullptr) return; 260 if (pc == nullptr) return;
188 timestamp = base::TimeTicks::HighResolutionNow(); 261 timestamp = base::TimeTicks::HighResolutionNow();
189 } 262 }
190 263
191 #if defined(USE_SIMULATOR)
192 bool SimulatorHelper::FillRegisters(Isolate* isolate,
193 v8::RegisterState* state) {
194 Simulator* simulator = isolate->thread_local_top()->simulator_;
195 // Check if there is active simulator.
196 if (simulator == NULL) return false;
197 #if V8_TARGET_ARCH_ARM
198 if (!simulator->has_bad_pc()) {
199 state->pc = reinterpret_cast<Address>(simulator->get_pc());
200 }
201 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
202 state->fp =
203 reinterpret_cast<Address>(simulator->get_register(Simulator::r11));
204 #elif V8_TARGET_ARCH_ARM64
205 state->pc = reinterpret_cast<Address>(simulator->pc());
206 state->sp = reinterpret_cast<Address>(simulator->sp());
207 state->fp = reinterpret_cast<Address>(simulator->fp());
208 #elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
209 if (!simulator->has_bad_pc()) {
210 state->pc = reinterpret_cast<Address>(simulator->get_pc());
211 }
212 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
213 state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
214 #elif V8_TARGET_ARCH_PPC
215 if (!simulator->has_bad_pc()) {
216 state->pc = reinterpret_cast<Address>(simulator->get_pc());
217 }
218 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
219 state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
220 #elif V8_TARGET_ARCH_S390
221 if (!simulator->has_bad_pc()) {
222 state->pc = reinterpret_cast<Address>(simulator->get_pc());
223 }
224 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
225 state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
226 #endif
227 if (state->sp == 0 || state->fp == 0) {
228 // It possible that the simulator is interrupted while it is updating
229 // the sp or fp register. ARM64 simulator does this in two steps:
230 // first setting it to zero and then setting it to the new value.
231 // Bailout if sp/fp doesn't contain the new value.
232 //
233 // FIXME: The above doesn't really solve the issue.
234 // If a 64-bit target is executed on a 32-bit host even the final
235 // write is non-atomic, so it might obtain a half of the result.
236 // Moreover as long as the register set code uses memcpy (as of now),
237 // it is not guaranteed to be atomic even when both host and target
238 // are of same bitness.
239 return false;
240 }
241 return true;
242 }
243 #endif // USE_SIMULATOR
244
245 } // namespace internal 264 } // namespace internal
246 } // namespace v8 265 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698