143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org// Copyright 2014 the V8 project authors. All rights reserved.
243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org// Redistribution and use in source and binary forms, with or without
343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org// modification, are permitted provided that the following conditions are
443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org// met:
543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org//
643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org//     * Redistributions of source code must retain the above copyright
743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org//       notice, this list of conditions and the following disclaimer.
843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org//     * Redistributions in binary form must reproduce the above
943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org//       copyright notice, this list of conditions and the following
1043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org//       disclaimer in the documentation and/or other materials provided
1143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org//       with the distribution.
1243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org//     * Neither the name of Google Inc. nor the names of its
1343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org//       contributors may be used to endorse or promote products derived
1443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org//       from this software without specific prior written permission.
1543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org//
1643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
28196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "test/cctest/trace-extension.h"
2943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
30196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/sampler.h"
31196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "test/cctest/cctest.h"
3243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
3343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.orgnamespace v8 {
3443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.orgnamespace internal {
3543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
3643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.orgconst char* TraceExtension::kSource =
3743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    "native function trace();"
3843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    "native function js_trace();"
3943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    "native function js_entry_sp();"
4043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    "native function js_entry_sp_level2();";
4143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
4243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
4343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.orgv8::Handle<v8::FunctionTemplate> TraceExtension::GetNativeFunctionTemplate(
4443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    v8::Isolate* isolate, v8::Handle<v8::String> name) {
4543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  if (name->Equals(v8::String::NewFromUtf8(isolate, "trace"))) {
4643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    return v8::FunctionTemplate::New(isolate, TraceExtension::Trace);
4743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  } else if (name->Equals(v8::String::NewFromUtf8(isolate, "js_trace"))) {
4843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    return v8::FunctionTemplate::New(isolate, TraceExtension::JSTrace);
4943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  } else if (name->Equals(v8::String::NewFromUtf8(isolate, "js_entry_sp"))) {
5043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    return v8::FunctionTemplate::New(isolate, TraceExtension::JSEntrySP);
5143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  } else if (name->Equals(v8::String::NewFromUtf8(isolate,
5243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org                                                  "js_entry_sp_level2"))) {
5343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    return v8::FunctionTemplate::New(isolate, TraceExtension::JSEntrySPLevel2);
5443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  } else {
5543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    CHECK(false);
5643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    return v8::Handle<v8::FunctionTemplate>();
5743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  }
5843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org}
5943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
6043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
6143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.orgAddress TraceExtension::GetFP(const v8::FunctionCallbackInfo<v8::Value>& args) {
6243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  // Convert frame pointer from encoding as smis in the arguments to a pointer.
6343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  CHECK_EQ(2, args.Length());  // Ignore second argument on 32-bit platform.
6443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org#if defined(V8_HOST_ARCH_32_BIT)
6543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  Address fp = *reinterpret_cast<Address*>(*args[0]);
6643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org#elif defined(V8_HOST_ARCH_64_BIT)
6743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  int64_t low_bits = *reinterpret_cast<uint64_t*>(*args[0]) >> 32;
6843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  int64_t high_bits = *reinterpret_cast<uint64_t*>(*args[1]);
6943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  Address fp = reinterpret_cast<Address>(high_bits | low_bits);
7043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org#else
7143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org#error Host architecture is neither 32-bit nor 64-bit.
7243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org#endif
7343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  printf("Trace: %p\n", fp);
7443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  return fp;
7543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org}
7643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
7743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
7843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.orgstatic struct {
7943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  TickSample* sample;
8043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org} trace_env = { NULL };
8143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
8243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
8343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.orgvoid TraceExtension::InitTraceEnv(TickSample* sample) {
8443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  trace_env.sample = sample;
8543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org}
8643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
8743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
8843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.orgvoid TraceExtension::DoTrace(Address fp) {
8943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  RegisterState regs;
9043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  regs.fp = fp;
9143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  // sp is only used to define stack high bound
9243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  regs.sp =
9343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      reinterpret_cast<Address>(trace_env.sample) - 10240;
9443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  trace_env.sample->Init(CcTest::i_isolate(), regs);
9543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org}
9643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
9743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
9843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.orgvoid TraceExtension::Trace(const v8::FunctionCallbackInfo<v8::Value>& args) {
9943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  DoTrace(GetFP(args));
10043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org}
10143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
10243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
10343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org// Hide c_entry_fp to emulate situation when sampling is done while
10443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org// pure JS code is being executed
10543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.orgstatic void DoTraceHideCEntryFPAddress(Address fp) {
10643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  v8::internal::Address saved_c_frame_fp =
10743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      *(CcTest::i_isolate()->c_entry_fp_address());
10843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  CHECK(saved_c_frame_fp);
10943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  *(CcTest::i_isolate()->c_entry_fp_address()) = 0;
11043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  i::TraceExtension::DoTrace(fp);
11143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  *(CcTest::i_isolate()->c_entry_fp_address()) = saved_c_frame_fp;
11243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org}
11343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
11443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
11543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.orgvoid TraceExtension::JSTrace(const v8::FunctionCallbackInfo<v8::Value>& args) {
11643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  DoTraceHideCEntryFPAddress(GetFP(args));
11743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org}
11843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
11943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
12043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.orgAddress TraceExtension::GetJsEntrySp() {
12143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  CHECK_NE(NULL, CcTest::i_isolate()->thread_local_top());
12243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  return CcTest::i_isolate()->js_entry_sp();
12343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org}
12443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
12543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
12643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.orgvoid TraceExtension::JSEntrySP(
12743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    const v8::FunctionCallbackInfo<v8::Value>& args) {
12843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  CHECK_NE(0, GetJsEntrySp());
12943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org}
13043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
13143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
13243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.orgvoid TraceExtension::JSEntrySPLevel2(
13343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    const v8::FunctionCallbackInfo<v8::Value>& args) {
13443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  v8::HandleScope scope(args.GetIsolate());
13543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  const Address js_entry_sp = GetJsEntrySp();
13643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  CHECK_NE(0, js_entry_sp);
13743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  CompileRun("js_entry_sp();");
13843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  CHECK_EQ(js_entry_sp, GetJsEntrySp());
13943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org}
14043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
14143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org
14243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org} }  // namespace v8::internal
143