OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/api.h" | 5 #include "src/api.h" |
6 | 6 |
7 #include <string.h> // For memcpy, strlen. | 7 #include <string.h> // For memcpy, strlen. |
8 #ifdef V8_USE_ADDRESS_SANITIZER | 8 #ifdef V8_USE_ADDRESS_SANITIZER |
9 #include <sanitizer/asan_interface.h> | 9 #include <sanitizer/asan_interface.h> |
10 #endif // V8_USE_ADDRESS_SANITIZER | 10 #endif // V8_USE_ADDRESS_SANITIZER |
(...skipping 18 matching lines...) Expand all Loading... | |
29 #include "src/char-predicates-inl.h" | 29 #include "src/char-predicates-inl.h" |
30 #include "src/code-stubs.h" | 30 #include "src/code-stubs.h" |
31 #include "src/compiler.h" | 31 #include "src/compiler.h" |
32 #include "src/context-measure.h" | 32 #include "src/context-measure.h" |
33 #include "src/contexts.h" | 33 #include "src/contexts.h" |
34 #include "src/conversions-inl.h" | 34 #include "src/conversions-inl.h" |
35 #include "src/counters.h" | 35 #include "src/counters.h" |
36 #include "src/debug/debug.h" | 36 #include "src/debug/debug.h" |
37 #include "src/deoptimizer.h" | 37 #include "src/deoptimizer.h" |
38 #include "src/execution.h" | 38 #include "src/execution.h" |
39 #include "src/frames-inl.h" | |
39 #include "src/gdb-jit.h" | 40 #include "src/gdb-jit.h" |
40 #include "src/global-handles.h" | 41 #include "src/global-handles.h" |
41 #include "src/icu_util.h" | 42 #include "src/icu_util.h" |
42 #include "src/isolate-inl.h" | 43 #include "src/isolate-inl.h" |
43 #include "src/json-parser.h" | 44 #include "src/json-parser.h" |
44 #include "src/json-stringifier.h" | 45 #include "src/json-stringifier.h" |
45 #include "src/messages.h" | 46 #include "src/messages.h" |
46 #include "src/parsing/parser.h" | 47 #include "src/parsing/parser.h" |
47 #include "src/parsing/scanner-character-streams.h" | 48 #include "src/parsing/scanner-character-streams.h" |
48 #include "src/pending-compilation-error-handler.h" | 49 #include "src/pending-compilation-error-handler.h" |
49 #include "src/profiler/cpu-profiler.h" | 50 #include "src/profiler/cpu-profiler.h" |
50 #include "src/profiler/heap-profiler.h" | 51 #include "src/profiler/heap-profiler.h" |
51 #include "src/profiler/heap-snapshot-generator-inl.h" | 52 #include "src/profiler/heap-snapshot-generator-inl.h" |
52 #include "src/profiler/profile-generator-inl.h" | 53 #include "src/profiler/profile-generator-inl.h" |
53 #include "src/profiler/tick-sample.h" | 54 #include "src/profiler/simulator-helper.h" |
54 #include "src/property-descriptor.h" | 55 #include "src/property-descriptor.h" |
55 #include "src/property-details.h" | 56 #include "src/property-details.h" |
56 #include "src/property.h" | 57 #include "src/property.h" |
57 #include "src/prototype.h" | 58 #include "src/prototype.h" |
58 #include "src/runtime-profiler.h" | 59 #include "src/runtime-profiler.h" |
59 #include "src/runtime/runtime.h" | 60 #include "src/runtime/runtime.h" |
60 #include "src/simulator.h" | 61 #include "src/simulator.h" |
61 #include "src/snapshot/natives.h" | 62 #include "src/snapshot/natives.h" |
62 #include "src/snapshot/snapshot.h" | 63 #include "src/snapshot/snapshot.h" |
63 #include "src/startup-data-util.h" | 64 #include "src/startup-data-util.h" |
(...skipping 7493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7557 isolate->heap()->CollectCodeStatistics(); | 7558 isolate->heap()->CollectCodeStatistics(); |
7558 | 7559 |
7559 code_statistics->code_and_metadata_size_ = isolate->code_and_metadata_size(); | 7560 code_statistics->code_and_metadata_size_ = isolate->code_and_metadata_size(); |
7560 code_statistics->bytecode_and_metadata_size_ = | 7561 code_statistics->bytecode_and_metadata_size_ = |
7561 isolate->bytecode_and_metadata_size(); | 7562 isolate->bytecode_and_metadata_size(); |
7562 return true; | 7563 return true; |
7563 } | 7564 } |
7564 | 7565 |
7565 void Isolate::GetStackSample(const RegisterState& state, void** frames, | 7566 void Isolate::GetStackSample(const RegisterState& state, void** frames, |
7566 size_t frames_limit, SampleInfo* sample_info) { | 7567 size_t frames_limit, SampleInfo* sample_info) { |
7568 #if defined(USE_SIMULATOR) | |
7567 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); | 7569 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); |
7568 #if defined(USE_SIMULATOR) | |
7569 RegisterState regs; | 7570 RegisterState regs; |
7570 regs.pc = state.pc; | 7571 regs.pc = state.pc; |
7571 regs.sp = state.sp; | 7572 regs.sp = state.sp; |
7572 regs.fp = state.fp; | 7573 regs.fp = state.fp; |
7573 if (!i::SimulatorHelper::FillRegisters(isolate, ®s)) { | 7574 if (!i::SimulatorHelper::FillRegisters(isolate, ®s)) { |
7574 sample_info->frames_count = 0; | 7575 sample_info->frames_count = 0; |
7575 sample_info->vm_state = OTHER; | 7576 sample_info->vm_state = OTHER; |
7576 sample_info->external_callback_entry = nullptr; | 7577 sample_info->external_callback_entry = nullptr; |
7577 return; | 7578 return; |
7578 } | 7579 } |
7579 #else | 7580 #else |
7580 const RegisterState& regs = state; | 7581 const RegisterState& regs = state; |
7581 #endif | 7582 #endif |
7582 i::TickSample::GetStackSample(isolate, regs, i::TickSample::kSkipCEntryFrame, | 7583 TickSample::GetStackSample(this, regs, TickSample::kSkipCEntryFrame, frames, |
7583 frames, frames_limit, sample_info); | 7584 frames_limit, sample_info); |
7584 } | 7585 } |
7585 | 7586 |
7586 size_t Isolate::NumberOfPhantomHandleResetsSinceLastCall() { | 7587 size_t Isolate::NumberOfPhantomHandleResetsSinceLastCall() { |
7587 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); | 7588 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); |
7588 size_t result = isolate->global_handles()->NumberOfPhantomHandleResets(); | 7589 size_t result = isolate->global_handles()->NumberOfPhantomHandleResets(); |
7589 isolate->global_handles()->ResetNumberOfPhantomHandleResets(); | 7590 isolate->global_handles()->ResetNumberOfPhantomHandleResets(); |
7590 return result; | 7591 return result; |
7591 } | 7592 } |
7592 | 7593 |
7593 void Isolate::SetEventLogger(LogEventCallback that) { | 7594 void Isolate::SetEventLogger(LogEventCallback that) { |
(...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8252 Local<Value> value) { | 8253 Local<Value> value) { |
8253 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); | 8254 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); |
8254 ENTER_V8(isolate); | 8255 ENTER_V8(isolate); |
8255 i::Handle<i::Object> val = Utils::OpenHandle(*value); | 8256 i::Handle<i::Object> val = Utils::OpenHandle(*value); |
8256 i::Handle<i::JSArray> result; | 8257 i::Handle<i::JSArray> result; |
8257 if (!i::Runtime::GetInternalProperties(isolate, val).ToHandle(&result)) | 8258 if (!i::Runtime::GetInternalProperties(isolate, val).ToHandle(&result)) |
8258 return MaybeLocal<Array>(); | 8259 return MaybeLocal<Array>(); |
8259 return Utils::ToLocal(result); | 8260 return Utils::ToLocal(result); |
8260 } | 8261 } |
8261 | 8262 |
8263 namespace { | |
8264 | |
8265 bool IsSamePage(i::byte* ptr1, i::byte* ptr2) { | |
8266 const uint32_t kPageSize = 4096; | |
8267 uintptr_t mask = ~static_cast<uintptr_t>(kPageSize - 1); | |
8268 return (reinterpret_cast<uintptr_t>(ptr1) & mask) == | |
8269 (reinterpret_cast<uintptr_t>(ptr2) & mask); | |
8270 } | |
8271 | |
8272 // Check if the code at specified address could potentially be a | |
8273 // frame setup code. | |
8274 bool IsNoFrameRegion(i::Address address) { | |
8275 struct Pattern { | |
8276 int bytes_count; | |
8277 i::byte bytes[8]; | |
8278 int offsets[4]; | |
8279 }; | |
8280 i::byte* pc = reinterpret_cast<i::byte*>(address); | |
8281 static Pattern patterns[] = { | |
8282 #if V8_HOST_ARCH_IA32 | |
8283 // push %ebp | |
8284 // mov %esp,%ebp | |
8285 {3, {0x55, 0x89, 0xe5}, {0, 1, -1}}, | |
8286 // pop %ebp | |
8287 // ret N | |
8288 {2, {0x5d, 0xc2}, {0, 1, -1}}, | |
8289 // pop %ebp | |
8290 // ret | |
8291 {2, {0x5d, 0xc3}, {0, 1, -1}}, | |
8292 #elif V8_HOST_ARCH_X64 | |
8293 // pushq %rbp | |
8294 // movq %rsp,%rbp | |
8295 {4, {0x55, 0x48, 0x89, 0xe5}, {0, 1, -1}}, | |
8296 // popq %rbp | |
8297 // ret N | |
8298 {2, {0x5d, 0xc2}, {0, 1, -1}}, | |
8299 // popq %rbp | |
8300 // ret | |
8301 {2, {0x5d, 0xc3}, {0, 1, -1}}, | |
8302 #endif | |
8303 {0, {}, {}} | |
8304 }; | |
8305 for (Pattern* pattern = patterns; pattern->bytes_count; ++pattern) { | |
8306 for (int* offset_ptr = pattern->offsets; *offset_ptr != -1; ++offset_ptr) { | |
8307 int offset = *offset_ptr; | |
8308 if (!offset || IsSamePage(pc, pc - offset)) { | |
8309 MSAN_MEMORY_IS_INITIALIZED(pc - offset, pattern->bytes_count); | |
8310 if (!memcmp(pc - offset, pattern->bytes, pattern->bytes_count)) | |
8311 return true; | |
8312 } else { | |
8313 // It is not safe to examine bytes on another page as it might not be | |
8314 // allocated thus causing a SEGFAULT. | |
8315 // Check the pattern part that's on the same page and | |
8316 // pessimistically assume it could be the entire pattern match. | |
8317 MSAN_MEMORY_IS_INITIALIZED(pc, pattern->bytes_count - offset); | |
8318 if (!memcmp(pc, pattern->bytes + offset, pattern->bytes_count - offset)) | |
8319 return true; | |
8320 } | |
8321 } | |
8322 } | |
8323 return false; | |
8324 } | |
8325 | |
8326 } // namespace | |
8327 | |
8328 // | |
8329 // StackTracer implementation | |
8330 // | |
8331 DISABLE_ASAN void TickSample::Init(Isolate* v8_isolate, | |
alph
2016/06/28 22:09:01
Don't move that much logic into api.cc
Keep it in
lpy
2016/06/28 23:02:53
Done.
| |
8332 const RegisterState& regs, | |
8333 RecordCEntryFrame record_c_entry_frame, | |
8334 bool update_stats) { | |
8335 this->update_stats = update_stats; | |
8336 | |
8337 SampleInfo info; | |
8338 if (GetStackSample(v8_isolate, const_cast<RegisterState&>(regs), | |
8339 record_c_entry_frame, reinterpret_cast<void**>(&stack[0]), | |
8340 kMaxFramesCount, &info)) { | |
8341 state = info.vm_state; | |
8342 pc = regs.pc; | |
8343 frames_count = static_cast<unsigned>(info.frames_count); | |
8344 has_external_callback = info.external_callback_entry != nullptr; | |
8345 if (has_external_callback) { | |
8346 external_callback_entry = info.external_callback_entry; | |
8347 } else if (frames_count) { | |
8348 // sp register may point at an arbitrary place in memory, make | |
8349 // sure MSAN doesn't complain about it. | |
8350 MSAN_MEMORY_IS_INITIALIZED(regs.sp, sizeof(void*)); | |
8351 // Sample potential return address value for frameless invocation of | |
8352 // stubs (we'll figure out later, if this value makes sense). | |
8353 tos = i::Memory::Address_at(reinterpret_cast<i::Address>(regs.sp)); | |
8354 } else { | |
8355 tos = nullptr; | |
8356 } | |
8357 } else { | |
8358 // It is executing JS but failed to collect a stack trace. | |
8359 // Mark the sample as spoiled. | |
8360 pc = nullptr; | |
8361 } | |
8362 } | |
8363 | |
8364 bool TickSample::GetStackSample(Isolate* v8_isolate, const RegisterState& regs, | |
8365 RecordCEntryFrame record_c_entry_frame, | |
8366 void** frames, size_t frames_limit, | |
8367 v8::SampleInfo* sample_info) { | |
8368 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); | |
8369 sample_info->frames_count = 0; | |
8370 sample_info->vm_state = isolate->current_vm_state(); | |
8371 sample_info->external_callback_entry = nullptr; | |
8372 if (sample_info->vm_state == GC) return true; | |
8373 | |
8374 i::Address js_entry_sp = isolate->js_entry_sp(); | |
8375 if (js_entry_sp == nullptr) return true; // Not executing JS now. | |
8376 DCHECK(regs.sp); | |
8377 | |
8378 if (regs.pc && IsNoFrameRegion(static_cast<i::Address>(regs.pc))) { | |
8379 // Can't collect stack. | |
8380 return false; | |
8381 } | |
8382 | |
8383 i::ExternalCallbackScope* scope = isolate->external_callback_scope(); | |
8384 i::Address handler = i::Isolate::handler(isolate->thread_local_top()); | |
8385 // If there is a handler on top of the external callback scope then | |
8386 // we have already entrered JavaScript again and the external callback | |
8387 // is not the top function. | |
8388 if (scope && scope->scope_address() < handler) { | |
8389 sample_info->external_callback_entry = | |
8390 *scope->callback_entrypoint_address(); | |
8391 } | |
8392 | |
8393 i::SafeStackFrameIterator it(isolate, reinterpret_cast<i::Address>(regs.fp), | |
8394 reinterpret_cast<i::Address>(regs.sp), | |
8395 js_entry_sp); | |
8396 size_t i = 0; | |
8397 if (record_c_entry_frame == kIncludeCEntryFrame && !it.done() && | |
8398 it.top_frame_type() == i::StackFrame::EXIT) { | |
8399 frames[i++] = isolate->c_function(); | |
8400 } | |
8401 while (!it.done() && i < frames_limit) { | |
8402 if (it.frame()->is_interpreted()) { | |
8403 // For interpreted frames use the bytecode array pointer as the pc. | |
8404 i::InterpretedFrame* frame = | |
8405 static_cast<i::InterpretedFrame*>(it.frame()); | |
8406 // Since the sampler can interrupt execution at any point the | |
8407 // bytecode_array might be garbage, so don't dereference it. | |
8408 i::Address bytecode_array = | |
8409 reinterpret_cast<i::Address>(frame->GetBytecodeArray()) - | |
8410 i::kHeapObjectTag; | |
8411 frames[i++] = bytecode_array + i::BytecodeArray::kHeaderSize + | |
8412 frame->GetBytecodeOffset(); | |
8413 } else { | |
8414 frames[i++] = it.frame()->pc(); | |
8415 } | |
8416 it.Advance(); | |
8417 } | |
8418 sample_info->frames_count = i; | |
8419 return true; | |
8420 } | |
8262 | 8421 |
8263 Local<String> CpuProfileNode::GetFunctionName() const { | 8422 Local<String> CpuProfileNode::GetFunctionName() const { |
8264 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this); | 8423 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this); |
8265 i::Isolate* isolate = node->isolate(); | 8424 i::Isolate* isolate = node->isolate(); |
8266 const i::CodeEntry* entry = node->entry(); | 8425 const i::CodeEntry* entry = node->entry(); |
8267 i::Handle<i::String> name = | 8426 i::Handle<i::String> name = |
8268 isolate->factory()->InternalizeUtf8String(entry->name()); | 8427 isolate->factory()->InternalizeUtf8String(entry->name()); |
8269 if (!entry->has_name_prefix()) { | 8428 if (!entry->has_name_prefix()) { |
8270 return ToApiHandle<String>(name); | 8429 return ToApiHandle<String>(name); |
8271 } else { | 8430 } else { |
(...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8924 Address callback_address = | 9083 Address callback_address = |
8925 reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback)); | 9084 reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback)); |
8926 VMState<EXTERNAL> state(isolate); | 9085 VMState<EXTERNAL> state(isolate); |
8927 ExternalCallbackScope call_scope(isolate, callback_address); | 9086 ExternalCallbackScope call_scope(isolate, callback_address); |
8928 callback(info); | 9087 callback(info); |
8929 } | 9088 } |
8930 | 9089 |
8931 | 9090 |
8932 } // namespace internal | 9091 } // namespace internal |
8933 } // namespace v8 | 9092 } // namespace v8 |
OLD | NEW |