blob: 19f8cd88cfa6e91401f6a0ede2abecd2bd672241 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2014 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "test/cctest/trace-extension.h"
29
Ben Murdochc5610432016-08-08 18:44:38 +010030#include "src/profiler/tick-sample.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000031#include "src/vm-state-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032#include "test/cctest/cctest.h"
33
34namespace v8 {
35namespace internal {
36
37const char* TraceExtension::kSource =
38 "native function trace();"
39 "native function js_trace();"
40 "native function js_entry_sp();"
41 "native function js_entry_sp_level2();";
42
43
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044v8::Local<v8::FunctionTemplate> TraceExtension::GetNativeFunctionTemplate(
45 v8::Isolate* isolate, v8::Local<v8::String> name) {
46 v8::Local<v8::Context> context = isolate->GetCurrentContext();
47 if (name->Equals(context, v8::String::NewFromUtf8(isolate, "trace",
48 v8::NewStringType::kNormal)
49 .ToLocalChecked())
50 .FromJust()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051 return v8::FunctionTemplate::New(isolate, TraceExtension::Trace);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000052 } else if (name->Equals(context,
53 v8::String::NewFromUtf8(isolate, "js_trace",
54 v8::NewStringType::kNormal)
55 .ToLocalChecked())
56 .FromJust()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000057 return v8::FunctionTemplate::New(isolate, TraceExtension::JSTrace);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058 } else if (name->Equals(context,
59 v8::String::NewFromUtf8(isolate, "js_entry_sp",
60 v8::NewStringType::kNormal)
61 .ToLocalChecked())
62 .FromJust()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000063 return v8::FunctionTemplate::New(isolate, TraceExtension::JSEntrySP);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064 } else if (name->Equals(context,
65 v8::String::NewFromUtf8(isolate, "js_entry_sp_level2",
66 v8::NewStringType::kNormal)
67 .ToLocalChecked())
68 .FromJust()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000069 return v8::FunctionTemplate::New(isolate, TraceExtension::JSEntrySPLevel2);
70 } else {
71 CHECK(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072 return v8::Local<v8::FunctionTemplate>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000073 }
74}
75
76
77Address TraceExtension::GetFP(const v8::FunctionCallbackInfo<v8::Value>& args) {
78 // Convert frame pointer from encoding as smis in the arguments to a pointer.
79 CHECK_EQ(2, args.Length()); // Ignore second argument on 32-bit platform.
80#if defined(V8_HOST_ARCH_32_BIT)
81 Address fp = *reinterpret_cast<Address*>(*args[0]);
82#elif defined(V8_HOST_ARCH_64_BIT)
83 int64_t low_bits = *reinterpret_cast<uint64_t*>(*args[0]) >> 32;
84 int64_t high_bits = *reinterpret_cast<uint64_t*>(*args[1]);
85 Address fp = reinterpret_cast<Address>(high_bits | low_bits);
86#else
87#error Host architecture is neither 32-bit nor 64-bit.
88#endif
Ben Murdoch61f157c2016-09-16 13:49:30 +010089 printf("Trace: %p\n", static_cast<void*>(fp));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000090 return fp;
91}
92
93
94static struct {
95 TickSample* sample;
96} trace_env = { NULL };
97
98
99void TraceExtension::InitTraceEnv(TickSample* sample) {
100 trace_env.sample = sample;
101}
102
103
104void TraceExtension::DoTrace(Address fp) {
105 RegisterState regs;
106 regs.fp = fp;
107 // sp is only used to define stack high bound
108 regs.sp =
109 reinterpret_cast<Address>(trace_env.sample) - 10240;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400110 trace_env.sample->Init(CcTest::i_isolate(), regs,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100111 TickSample::kSkipCEntryFrame, true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112}
113
114
115void TraceExtension::Trace(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000116 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
117 i::VMState<EXTERNAL> state(isolate);
118 Address address = reinterpret_cast<Address>(
119 reinterpret_cast<intptr_t>(&TraceExtension::Trace));
120 i::ExternalCallbackScope call_scope(isolate, address);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000121 DoTrace(GetFP(args));
122}
123
124
125// Hide c_entry_fp to emulate situation when sampling is done while
126// pure JS code is being executed
127static void DoTraceHideCEntryFPAddress(Address fp) {
128 v8::internal::Address saved_c_frame_fp =
129 *(CcTest::i_isolate()->c_entry_fp_address());
130 CHECK(saved_c_frame_fp);
131 *(CcTest::i_isolate()->c_entry_fp_address()) = 0;
132 i::TraceExtension::DoTrace(fp);
133 *(CcTest::i_isolate()->c_entry_fp_address()) = saved_c_frame_fp;
134}
135
136
137void TraceExtension::JSTrace(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
139 i::VMState<EXTERNAL> state(isolate);
140 Address address = reinterpret_cast<Address>(
141 reinterpret_cast<intptr_t>(&TraceExtension::JSTrace));
142 i::ExternalCallbackScope call_scope(isolate, address);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000143 DoTraceHideCEntryFPAddress(GetFP(args));
144}
145
146
147Address TraceExtension::GetJsEntrySp() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000148 CHECK(CcTest::i_isolate()->thread_local_top());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000149 return CcTest::i_isolate()->js_entry_sp();
150}
151
152
153void TraceExtension::JSEntrySP(
154 const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155 CHECK(GetJsEntrySp());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000156}
157
158
159void TraceExtension::JSEntrySPLevel2(
160 const v8::FunctionCallbackInfo<v8::Value>& args) {
161 v8::HandleScope scope(args.GetIsolate());
162 const Address js_entry_sp = GetJsEntrySp();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000163 CHECK(js_entry_sp);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000164 CompileRun("js_entry_sp();");
165 CHECK_EQ(js_entry_sp, GetJsEntrySp());
166}
167
168
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169} // namespace internal
170} // namespace v8