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

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 and rebase 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,
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 tmp_state = reg_state;
91 record_c_entry_frame, reinterpret_cast<void**>(&stack[0]), 156 if (!GetStackSample(v8_isolate, tmp_state, 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 #if defined(USE_SIMULATOR)
165 RegisterState regs = update_state ? tmp_state : reg_state;
alph 2016/08/08 21:36:57 It should be fine to always use tmp_state. right?
lpy 2016/08/09 18:31:43 Done.
166 #else
167 const RegisterState& regs = reg_state;
168 #endif
169
170 state = info.vm_state;
171 pc = regs.pc;
172 frames_count = static_cast<unsigned>(info.frames_count);
173 has_external_callback = info.external_callback_entry != nullptr;
174 if (has_external_callback) {
175 external_callback_entry = info.external_callback_entry;
176 } else if (frames_count) {
177 // sp register may point at an arbitrary place in memory, make
178 // sure MSAN doesn't complain about it.
179 MSAN_MEMORY_IS_INITIALIZED(regs.sp, sizeof(void*));
180 // Sample potential return address value for frameless invocation of
181 // stubs (we'll figure out later, if this value makes sense).
182 tos = i::Memory::Address_at(reinterpret_cast<i::Address>(regs.sp));
183 } else {
184 tos = nullptr;
113 } 185 }
114 } 186 }
115 187
116 bool TickSample::GetStackSample(Isolate* v8_isolate, const RegisterState& regs, 188 bool TickSample::GetStackSample(Isolate* v8_isolate, RegisterState& state,
117 RecordCEntryFrame record_c_entry_frame, 189 RecordCEntryFrame record_c_entry_frame,
118 void** frames, size_t frames_limit, 190 void** frames, size_t frames_limit,
119 v8::SampleInfo* sample_info) { 191 v8::SampleInfo* sample_info,
192 bool update_state) {
120 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 193 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
121 sample_info->frames_count = 0; 194 sample_info->frames_count = 0;
122 sample_info->vm_state = isolate->current_vm_state(); 195 sample_info->vm_state = isolate->current_vm_state();
123 sample_info->external_callback_entry = nullptr; 196 sample_info->external_callback_entry = nullptr;
124 if (sample_info->vm_state == GC) return true; 197 if (sample_info->vm_state == GC) return true;
125 198
126 i::Address js_entry_sp = isolate->js_entry_sp(); 199 i::Address js_entry_sp = isolate->js_entry_sp();
127 if (js_entry_sp == nullptr) return true; // Not executing JS now. 200 if (js_entry_sp == nullptr) return true; // Not executing JS now.
201
202 #if defined(USE_SIMULATOR)
203 if (update_state) {
204 if (!i::SimulatorHelper::FillRegisters(isolate, &state)) {
alph 2016/08/08 21:36:57 nit: you can omit {}
lpy 2016/08/09 18:31:43 Done.
205 return false;
206 }
207 }
208 #endif
209 const v8::RegisterState& regs = state;
128 DCHECK(regs.sp); 210 DCHECK(regs.sp);
129 211
130 if (regs.pc && IsNoFrameRegion(static_cast<i::Address>(regs.pc))) { 212 if (regs.pc && IsNoFrameRegion(static_cast<i::Address>(regs.pc))) {
131 // Can't collect stack. 213 // The frame is not setup, so it'd be hard to iterate the stack. Bailout.
132 return false; 214 return false;
133 } 215 }
134 216
135 i::ExternalCallbackScope* scope = isolate->external_callback_scope(); 217 i::ExternalCallbackScope* scope = isolate->external_callback_scope();
136 i::Address handler = i::Isolate::handler(isolate->thread_local_top()); 218 i::Address handler = i::Isolate::handler(isolate->thread_local_top());
137 // If there is a handler on top of the external callback scope then 219 // If there is a handler on top of the external callback scope then
138 // we have already entrered JavaScript again and the external callback 220 // we have already entrered JavaScript again and the external callback
139 // is not the top function. 221 // is not the top function.
140 if (scope && scope->scope_address() < handler) { 222 if (scope && scope->scope_address() < handler) {
141 sample_info->external_callback_entry = 223 sample_info->external_callback_entry =
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 frames[i++] = bytecode_array + i::BytecodeArray::kHeaderSize + 255 frames[i++] = bytecode_array + i::BytecodeArray::kHeaderSize +
174 frame->GetBytecodeOffset(); 256 frame->GetBytecodeOffset();
175 } 257 }
176 sample_info->frames_count = i; 258 sample_info->frames_count = i;
177 return true; 259 return true;
178 } 260 }
179 261
180 namespace internal { 262 namespace internal {
181 263
182 void TickSample::Init(Isolate* isolate, const v8::RegisterState& state, 264 void TickSample::Init(Isolate* isolate, const v8::RegisterState& state,
183 RecordCEntryFrame record_c_entry_frame, 265 RecordCEntryFrame record_c_entry_frame, bool update_stats,
184 bool update_stats) { 266 bool update_state) {
185 v8::TickSample::Init(reinterpret_cast<v8::Isolate*>(isolate), state, 267 v8::TickSample::Init(reinterpret_cast<v8::Isolate*>(isolate), state,
186 record_c_entry_frame, update_stats); 268 record_c_entry_frame, update_stats, update_state);
187 if (pc == nullptr) return; 269 if (pc == nullptr) return;
188 timestamp = base::TimeTicks::HighResolutionNow(); 270 timestamp = base::TimeTicks::HighResolutionNow();
189 } 271 }
190 272
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 273 } // namespace internal
246 } // namespace v8 274 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698