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

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

Issue 2128613004: Move SimulatorHelper into V8 out of profiler clients. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: addressing comments. Created 4 years, 5 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& regs,
85 RecordCEntryFrame record_c_entry_frame, 151 RecordCEntryFrame record_c_entry_frame,
86 bool update_stats) { 152 bool update_stats) {
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 if (!GetStackSample(v8_isolate, regs, record_c_entry_frame, stack,
91 record_c_entry_frame, reinterpret_cast<void**>(&stack[0]), 156 kMaxFramesCount, &info)) {
92 kMaxFramesCount, &info)) {
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. 157 // It is executing JS but failed to collect a stack trace.
111 // Mark the sample as spoiled. 158 // Mark the sample as spoiled.
112 pc = nullptr; 159 pc = nullptr;
160 return;
161 }
162 state = info.vm_state;
163 pc = regs.pc;
164 frames_count = static_cast<unsigned>(info.frames_count);
165 has_external_callback = info.external_callback_entry != nullptr;
166 if (has_external_callback) {
167 external_callback_entry = info.external_callback_entry;
168 } else if (frames_count) {
169 // sp register may point at an arbitrary place in memory, make
170 // sure MSAN doesn't complain about it.
171 MSAN_MEMORY_IS_INITIALIZED(regs.sp, sizeof(void*));
172 // Sample potential return address value for frameless invocation of
173 // stubs (we'll figure out later, if this value makes sense).
174 tos = i::Memory::Address_at(reinterpret_cast<i::Address>(regs.sp));
175 } else {
176 tos = nullptr;
113 } 177 }
114 } 178 }
115 179
116 bool TickSample::GetStackSample(Isolate* v8_isolate, const RegisterState& regs, 180 bool TickSample::GetStackSample(Isolate* v8_isolate, const RegisterState& state,
117 RecordCEntryFrame record_c_entry_frame, 181 RecordCEntryFrame record_c_entry_frame,
118 void** frames, size_t frames_limit, 182 void** frames, size_t frames_limit,
119 v8::SampleInfo* sample_info) { 183 v8::SampleInfo* sample_info) {
120 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 184 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
121 sample_info->frames_count = 0; 185 sample_info->frames_count = 0;
122 sample_info->vm_state = isolate->current_vm_state(); 186 sample_info->vm_state = isolate->current_vm_state();
123 sample_info->external_callback_entry = nullptr; 187 sample_info->external_callback_entry = nullptr;
124 if (sample_info->vm_state == GC) return true; 188 if (sample_info->vm_state == GC) return true;
125 189
126 i::Address js_entry_sp = isolate->js_entry_sp(); 190 i::Address js_entry_sp = isolate->js_entry_sp();
127 if (js_entry_sp == nullptr) return true; // Not executing JS now. 191 if (js_entry_sp == nullptr) return true; // Not executing JS now.
192
193 #if defined(USE_SIMULATOR)
194 v8::RegisterState regs;
195 if (!i::SimulatorHelper::FillRegisters(isolate, &regs)) return false;
196 #else
197 const v8::RegisterState& regs = state;
198 #endif
128 DCHECK(regs.sp); 199 DCHECK(regs.sp);
129 200
130 if (regs.pc && IsNoFrameRegion(static_cast<i::Address>(regs.pc))) { 201 if (regs.pc && IsNoFrameRegion(static_cast<i::Address>(regs.pc))) {
131 // Can't collect stack. 202 // The frame is not setup, so it'd be hard to iterate the stack. Bailout.
132 return false; 203 return false;
133 } 204 }
134 205
135 i::ExternalCallbackScope* scope = isolate->external_callback_scope(); 206 i::ExternalCallbackScope* scope = isolate->external_callback_scope();
136 i::Address handler = i::Isolate::handler(isolate->thread_local_top()); 207 i::Address handler = i::Isolate::handler(isolate->thread_local_top());
137 // If there is a handler on top of the external callback scope then 208 // If there is a handler on top of the external callback scope then
138 // we have already entrered JavaScript again and the external callback 209 // we have already entrered JavaScript again and the external callback
139 // is not the top function. 210 // is not the top function.
140 if (scope && scope->scope_address() < handler) { 211 if (scope && scope->scope_address() < handler) {
141 sample_info->external_callback_entry = 212 sample_info->external_callback_entry =
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 247
177 void TickSample::Init(Isolate* isolate, const v8::RegisterState& state, 248 void TickSample::Init(Isolate* isolate, const v8::RegisterState& state,
178 RecordCEntryFrame record_c_entry_frame, 249 RecordCEntryFrame record_c_entry_frame,
179 bool update_stats) { 250 bool update_stats) {
180 v8::TickSample::Init(reinterpret_cast<v8::Isolate*>(isolate), state, 251 v8::TickSample::Init(reinterpret_cast<v8::Isolate*>(isolate), state,
181 record_c_entry_frame, update_stats); 252 record_c_entry_frame, update_stats);
182 if (pc == nullptr) return; 253 if (pc == nullptr) return;
183 timestamp = base::TimeTicks::HighResolutionNow(); 254 timestamp = base::TimeTicks::HighResolutionNow();
184 } 255 }
185 256
186 #if defined(USE_SIMULATOR)
187 bool SimulatorHelper::FillRegisters(Isolate* isolate,
188 v8::RegisterState* state) {
189 Simulator* simulator = isolate->thread_local_top()->simulator_;
190 // Check if there is active simulator.
191 if (simulator == NULL) return false;
192 #if V8_TARGET_ARCH_ARM
193 if (!simulator->has_bad_pc()) {
194 state->pc = reinterpret_cast<Address>(simulator->get_pc());
195 }
196 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
197 state->fp =
198 reinterpret_cast<Address>(simulator->get_register(Simulator::r11));
199 #elif V8_TARGET_ARCH_ARM64
200 state->pc = reinterpret_cast<Address>(simulator->pc());
201 state->sp = reinterpret_cast<Address>(simulator->sp());
202 state->fp = reinterpret_cast<Address>(simulator->fp());
203 #elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
204 if (!simulator->has_bad_pc()) {
205 state->pc = reinterpret_cast<Address>(simulator->get_pc());
206 }
207 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
208 state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
209 #elif V8_TARGET_ARCH_PPC
210 if (!simulator->has_bad_pc()) {
211 state->pc = reinterpret_cast<Address>(simulator->get_pc());
212 }
213 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
214 state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
215 #elif V8_TARGET_ARCH_S390
216 if (!simulator->has_bad_pc()) {
217 state->pc = reinterpret_cast<Address>(simulator->get_pc());
218 }
219 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
220 state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
221 #endif
222 if (state->sp == 0 || state->fp == 0) {
223 // It possible that the simulator is interrupted while it is updating
224 // the sp or fp register. ARM64 simulator does this in two steps:
225 // first setting it to zero and then setting it to the new value.
226 // Bailout if sp/fp doesn't contain the new value.
227 //
228 // FIXME: The above doesn't really solve the issue.
229 // If a 64-bit target is executed on a 32-bit host even the final
230 // write is non-atomic, so it might obtain a half of the result.
231 // Moreover as long as the register set code uses memcpy (as of now),
232 // it is not guaranteed to be atomic even when both host and target
233 // are of same bitness.
234 return false;
235 }
236 return true;
237 }
238 #endif // USE_SIMULATOR
239
240 } // namespace internal 257 } // namespace internal
241 } // namespace v8 258 } // 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