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

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: Update 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
« no previous file with comments | « src/profiler/tick-sample.h ('k') | test/cctest/libsampler/test-sampler.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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,
85 RecordCEntryFrame record_c_entry_frame, 151 RecordCEntryFrame record_c_entry_frame,
86 bool update_stats) { 152 bool update_stats,
153 bool use_simulator_reg_state) {
87 this->update_stats = update_stats; 154 this->update_stats = update_stats;
88
89 SampleInfo info; 155 SampleInfo info;
90 if (GetStackSample(v8_isolate, const_cast<RegisterState&>(regs), 156 RegisterState regs = reg_state;
91 record_c_entry_frame, reinterpret_cast<void**>(&stack[0]), 157 if (!GetStackSample(v8_isolate, &regs, record_c_entry_frame, stack,
92 kMaxFramesCount, &info)) { 158 kMaxFramesCount, &info, use_simulator_reg_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. 159 // It is executing JS but failed to collect a stack trace.
111 // Mark the sample as spoiled. 160 // Mark the sample as spoiled.
112 pc = nullptr; 161 pc = nullptr;
162 return;
163 }
164
165 state = info.vm_state;
166 pc = regs.pc;
167 frames_count = static_cast<unsigned>(info.frames_count);
168 has_external_callback = info.external_callback_entry != nullptr;
169 if (has_external_callback) {
170 external_callback_entry = info.external_callback_entry;
171 } else if (frames_count) {
172 // sp register may point at an arbitrary place in memory, make
173 // sure MSAN doesn't complain about it.
174 MSAN_MEMORY_IS_INITIALIZED(regs.sp, sizeof(void*));
175 // Sample potential return address value for frameless invocation of
176 // stubs (we'll figure out later, if this value makes sense).
177 tos = i::Memory::Address_at(reinterpret_cast<i::Address>(regs.sp));
178 } else {
179 tos = nullptr;
113 } 180 }
114 } 181 }
115 182
116 bool TickSample::GetStackSample(Isolate* v8_isolate, const RegisterState& regs, 183 bool TickSample::GetStackSample(Isolate* v8_isolate, RegisterState* regs,
117 RecordCEntryFrame record_c_entry_frame, 184 RecordCEntryFrame record_c_entry_frame,
118 void** frames, size_t frames_limit, 185 void** frames, size_t frames_limit,
119 v8::SampleInfo* sample_info) { 186 v8::SampleInfo* sample_info,
187 bool use_simulator_reg_state) {
120 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 188 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
121 sample_info->frames_count = 0; 189 sample_info->frames_count = 0;
122 sample_info->vm_state = isolate->current_vm_state(); 190 sample_info->vm_state = isolate->current_vm_state();
123 sample_info->external_callback_entry = nullptr; 191 sample_info->external_callback_entry = nullptr;
124 if (sample_info->vm_state == GC) return true; 192 if (sample_info->vm_state == GC) return true;
125 193
126 i::Address js_entry_sp = isolate->js_entry_sp(); 194 i::Address js_entry_sp = isolate->js_entry_sp();
127 if (js_entry_sp == nullptr) return true; // Not executing JS now. 195 if (js_entry_sp == nullptr) return true; // Not executing JS now.
128 DCHECK(regs.sp);
129 196
130 if (regs.pc && IsNoFrameRegion(static_cast<i::Address>(regs.pc))) { 197 #if defined(USE_SIMULATOR)
131 // Can't collect stack. 198 if (use_simulator_reg_state) {
199 if (!i::SimulatorHelper::FillRegisters(isolate, regs)) return false;
200 }
201 #else
202 USE(use_simulator_reg_state);
203 #endif
204 DCHECK(regs->sp);
205
206 if (regs->pc && IsNoFrameRegion(static_cast<i::Address>(regs->pc))) {
207 // The frame is not setup, so it'd be hard to iterate the stack. Bailout.
132 return false; 208 return false;
133 } 209 }
134 210
135 i::ExternalCallbackScope* scope = isolate->external_callback_scope(); 211 i::ExternalCallbackScope* scope = isolate->external_callback_scope();
136 i::Address handler = i::Isolate::handler(isolate->thread_local_top()); 212 i::Address handler = i::Isolate::handler(isolate->thread_local_top());
137 // If there is a handler on top of the external callback scope then 213 // If there is a handler on top of the external callback scope then
138 // we have already entrered JavaScript again and the external callback 214 // we have already entrered JavaScript again and the external callback
139 // is not the top function. 215 // is not the top function.
140 if (scope && scope->scope_address() < handler) { 216 if (scope && scope->scope_address() < handler) {
141 sample_info->external_callback_entry = 217 sample_info->external_callback_entry =
142 *scope->callback_entrypoint_address(); 218 *scope->callback_entrypoint_address();
143 } 219 }
144 220
145 i::SafeStackFrameIterator it(isolate, reinterpret_cast<i::Address>(regs.fp), 221 i::SafeStackFrameIterator it(isolate, reinterpret_cast<i::Address>(regs->fp),
146 reinterpret_cast<i::Address>(regs.sp), 222 reinterpret_cast<i::Address>(regs->sp),
147 js_entry_sp); 223 js_entry_sp);
148 224
149 // If at this point iterator does not see any frames, 225 // If at this point iterator does not see any frames,
150 // is usually means something is wrong with the FP, 226 // is usually means something is wrong with the FP,
151 // e.g. it is used as a general purpose register in the function. 227 // e.g. it is used as a general purpose register in the function.
152 // Bailout. 228 // Bailout.
153 if (it.done()) return false; 229 if (it.done()) return false;
154 230
155 size_t i = 0; 231 size_t i = 0;
156 if (record_c_entry_frame == kIncludeCEntryFrame && 232 if (record_c_entry_frame == kIncludeCEntryFrame &&
(...skipping 16 matching lines...) Expand all
173 frames[i++] = bytecode_array + i::BytecodeArray::kHeaderSize + 249 frames[i++] = bytecode_array + i::BytecodeArray::kHeaderSize +
174 frame->GetBytecodeOffset(); 250 frame->GetBytecodeOffset();
175 } 251 }
176 sample_info->frames_count = i; 252 sample_info->frames_count = i;
177 return true; 253 return true;
178 } 254 }
179 255
180 namespace internal { 256 namespace internal {
181 257
182 void TickSample::Init(Isolate* isolate, const v8::RegisterState& state, 258 void TickSample::Init(Isolate* isolate, const v8::RegisterState& state,
183 RecordCEntryFrame record_c_entry_frame, 259 RecordCEntryFrame record_c_entry_frame, bool update_stats,
184 bool update_stats) { 260 bool use_simulator_reg_state) {
185 v8::TickSample::Init(reinterpret_cast<v8::Isolate*>(isolate), state, 261 v8::TickSample::Init(reinterpret_cast<v8::Isolate*>(isolate), state,
186 record_c_entry_frame, update_stats); 262 record_c_entry_frame, update_stats,
263 use_simulator_reg_state);
187 if (pc == nullptr) return; 264 if (pc == nullptr) return;
188 timestamp = base::TimeTicks::HighResolutionNow(); 265 timestamp = base::TimeTicks::HighResolutionNow();
189 } 266 }
190 267
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 268 } // namespace internal
246 } // namespace v8 269 } // namespace v8
OLDNEW
« no previous file with comments | « src/profiler/tick-sample.h ('k') | test/cctest/libsampler/test-sampler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698