144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org// Copyright 2011 the V8 project authors. All rights reserved. 23cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// Redistribution and use in source and binary forms, with or without 33cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// modification, are permitted provided that the following conditions are 43cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// met: 53cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// 63cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// * Redistributions of source code must retain the above copyright 73cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// notice, this list of conditions and the following disclaimer. 83cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// * Redistributions in binary form must reproduce the above 93cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// copyright notice, this list of conditions and the following 103cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// disclaimer in the documentation and/or other materials provided 113cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// with the distribution. 123cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// * Neither the name of Google Inc. nor the names of its 133cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// contributors may be used to endorse or promote products derived 143cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// from this software without specific prior written permission. 153cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// 163cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.org// 28061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.org// Tests of profiler-related functions from log.h 29061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.org 30061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.org#include <stdlib.h> 31061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.org 32196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h" 33061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.org 34196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/api.h" 35196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/codegen.h" 36196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/disassembler.h" 37196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/isolate.h" 38196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/log.h" 39196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/sampler.h" 40196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/vm-state-inl.h" 41196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "test/cctest/cctest.h" 42196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "test/cctest/trace-extension.h" 43061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.org 44061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.orgusing v8::Function; 45061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.orgusing v8::Local; 46061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.orgusing v8::Object; 47061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.orgusing v8::Script; 48061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.orgusing v8::String; 49061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.orgusing v8::Value; 50061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.org 51061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.orgusing v8::internal::byte; 529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgusing v8::internal::Address; 53061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.orgusing v8::internal::Handle; 54ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgusing v8::internal::Isolate; 55061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.orgusing v8::internal::JSFunction; 56061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.orgusing v8::internal::TickSample; 57061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.org 58061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.org 593a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgstatic bool IsAddressWithinFuncCode(JSFunction* function, Address addr) { 603a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org i::Code* code = function->code(); 613a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org return code->contains(addr); 623a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org} 633a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 64e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org 65528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.orgstatic bool IsAddressWithinFuncCode(v8::Local<v8::Context> context, 66528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org const char* func_name, 67528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org Address addr) { 68528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org v8::Local<v8::Value> func = context->Global()->Get(v8_str(func_name)); 693a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org CHECK(func->IsFunction()); 703a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org JSFunction* js_func = JSFunction::cast(*v8::Utils::OpenHandle(*func)); 713a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org return IsAddressWithinFuncCode(js_func, addr); 729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org} 739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 749085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 753cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// This C++ function is called as a constructor, to grab the frame pointer 763cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// from the calling function. When this function runs, the stack contains 773cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// a C_Entry frame and a Construct frame above the calling function's frame. 781510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgstatic void construct_call(const v8::FunctionCallbackInfo<v8::Value>& args) { 79c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); 80c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org i::StackFrameIterator frame_iterator(isolate); 813cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org CHECK(frame_iterator.frame()->is_exit()); 823cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org frame_iterator.Advance(); 833cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org CHECK(frame_iterator.frame()->is_construct()); 843cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org frame_iterator.Advance(); 853cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org i::StackFrame* calling_frame = frame_iterator.frame(); 863cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org CHECK(calling_frame->is_java_script()); 873cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org 883cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org#if defined(V8_HOST_ARCH_32_BIT) 894a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org int32_t low_bits = reinterpret_cast<int32_t>(calling_frame->fp()); 903cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org args.This()->Set(v8_str("low_bits"), v8_num(low_bits >> 1)); 913cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org#elif defined(V8_HOST_ARCH_64_BIT) 924a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org uint64_t fp = reinterpret_cast<uint64_t>(calling_frame->fp()); 93f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org int32_t low_bits = static_cast<int32_t>(fp & 0xffffffff); 94f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org int32_t high_bits = static_cast<int32_t>(fp >> 32); 953cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org args.This()->Set(v8_str("low_bits"), v8_num(low_bits)); 963cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org args.This()->Set(v8_str("high_bits"), v8_num(high_bits)); 973cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org#else 983cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org#error Host architecture is neither 32-bit nor 64-bit. 993cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org#endif 1001510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org args.GetReturnValue().Set(args.This()); 1013cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org} 1029085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 1039085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 1043cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// Use the API to create a JSFunction object that calls the above C++ function. 105528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.orgvoid CreateFramePointerGrabberConstructor(v8::Local<v8::Context> context, 106528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org const char* constructor_name) { 1073cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org Local<v8::FunctionTemplate> constructor_template = 1084f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org v8::FunctionTemplate::New(context->GetIsolate(), construct_call); 1093cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org constructor_template->SetClassName(v8_str("FPGrabber")); 1103cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org Local<Function> fun = constructor_template->GetFunction(); 111528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org context->Global()->Set(v8_str(constructor_name), fun); 1123cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org} 1139085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 1149085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 1159085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Creates a global function named 'func_name' that calls the tracing 1169085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// function 'trace_func_name' with an actual EBP register value, 1173cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org// encoded as one or two Smis. 118528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.orgstatic void CreateTraceCallerFunction(v8::Local<v8::Context> context, 119528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org const char* func_name, 1209085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org const char* trace_func_name) { 1219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org i::EmbeddedVector<char, 256> trace_call_buf; 12270ec1a2160dd946b9578d04d97d631a6d4ab4f8cbmeurer@chromium.org i::SNPrintF(trace_call_buf, 12370ec1a2160dd946b9578d04d97d631a6d4ab4f8cbmeurer@chromium.org "function %s() {" 12470ec1a2160dd946b9578d04d97d631a6d4ab4f8cbmeurer@chromium.org " fp = new FPGrabber();" 12570ec1a2160dd946b9578d04d97d631a6d4ab4f8cbmeurer@chromium.org " %s(fp.low_bits, fp.high_bits);" 12670ec1a2160dd946b9578d04d97d631a6d4ab4f8cbmeurer@chromium.org "}", 12770ec1a2160dd946b9578d04d97d631a6d4ab4f8cbmeurer@chromium.org func_name, trace_func_name); 1283cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org 1293cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org // Create the FPGrabber function, which grabs the caller's frame pointer 1303cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org // when called as a constructor. 131528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org CreateFramePointerGrabberConstructor(context, "FPGrabber"); 1329085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 1339085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org // Compile the script. 134303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org CompileRun(trace_call_buf.start()); 1359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org} 1369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 1379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 138df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org// This test verifies that stack tracing works when called during 139df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org// execution of a native function called from JS code. In this case, 140e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// TickSample::Trace uses Isolate::c_entry_fp as a starting point for stack 141df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org// walking. 1429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgTEST(CFromJSStackTrace) { 14374f333bce721daf6b1f9d7d3d3faa623f77658d7vegorov@chromium.org // BUG(1303) Inlining of JSFuncDoTrace() in JSTrace below breaks this test. 14474f333bce721daf6b1f9d7d3d3faa623f77658d7vegorov@chromium.org i::FLAG_use_inlining = false; 1456ff651481ed0a881f176f6d55e26679ca359792bulan@chromium.org 1469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org TickSample sample; 14743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org i::TraceExtension::InitTraceEnv(&sample); 1489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 149e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org v8::HandleScope scope(CcTest::isolate()); 150528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org v8::Local<v8::Context> context = CcTest::NewContext(TRACE_EXTENSION); 151528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org v8::Context::Scope context_scope(context); 152528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org 153df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org // Create global function JSFuncDoTrace which calls 154df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org // extension function trace() with the current frame pointer value. 155528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org CreateTraceCallerFunction(context, "JSFuncDoTrace", "trace"); 1565d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org Local<Value> result = CompileRun( 1579085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org "function JSTrace() {" 1589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org " JSFuncDoTrace();" 1599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org "};\n" 1605d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org "JSTrace();\n" 1615d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org "true;"); 1625d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org CHECK(!result.IsEmpty()); 163df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org // When stack tracer is invoked, the stack should look as follows: 164df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org // script [JS] 165df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org // JSTrace() [JS] 166df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org // JSFuncDoTrace() [JS] [captures EBP value and encodes it as Smi] 167c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org // trace(EBP) [native (extension)] 168df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org // DoTrace(EBP) [native] 169e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // TickSample::Trace 170a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 17177ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org CHECK(sample.has_external_callback); 17243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org CHECK_EQ(FUNCTION_ADDR(i::TraceExtension::Trace), sample.external_callback); 173a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 174df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org // Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace" 17508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org unsigned base = 0; 176a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org CHECK_GT(sample.frames_count, base + 1); 177531dfe85209e15c3e292569c285a5be54910da7cjkummerow@chromium.org 178528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org CHECK(IsAddressWithinFuncCode( 179528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org context, "JSFuncDoTrace", sample.stack[base + 0])); 180528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org CHECK(IsAddressWithinFuncCode(context, "JSTrace", sample.stack[base + 1])); 1819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org} 1829085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 1839085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 184df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org// This test verifies that stack tracing works when called during 185e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// execution of JS code. However, as calling TickSample::Trace requires 186df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org// entering native code, we can only emulate pure JS by erasing 187e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// Isolate::c_entry_fp value. In this case, TickSample::Trace uses passed frame 188df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org// pointer value as a starting point for stack walking. 1899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgTEST(PureJSStackTrace) { 190a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // This test does not pass with inlining enabled since inlined functions 191a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // don't appear in the stack trace. 192a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org i::FLAG_use_inlining = false; 193a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 1949085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org TickSample sample; 19543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org i::TraceExtension::InitTraceEnv(&sample); 1969085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 197e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org v8::HandleScope scope(CcTest::isolate()); 198528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org v8::Local<v8::Context> context = CcTest::NewContext(TRACE_EXTENSION); 199528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org v8::Context::Scope context_scope(context); 200528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org 201df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org // Create global function JSFuncDoTrace which calls 202df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org // extension function js_trace() with the current frame pointer value. 203528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org CreateTraceCallerFunction(context, "JSFuncDoTrace", "js_trace"); 2045d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org Local<Value> result = CompileRun( 2059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org "function JSTrace() {" 2069085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org " JSFuncDoTrace();" 2079085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org "};\n" 2089085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org "function OuterJSTrace() {" 2099085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org " JSTrace();" 2109085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org "};\n" 2115d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org "OuterJSTrace();\n" 2125d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org "true;"); 2135d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org CHECK(!result.IsEmpty()); 214df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org // When stack tracer is invoked, the stack should look as follows: 215df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org // script [JS] 216df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org // OuterJSTrace() [JS] 217df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org // JSTrace() [JS] 218c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org // JSFuncDoTrace() [JS] 219c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org // js_trace(EBP) [native (extension)] 220df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org // DoTraceHideCEntryFPAddress(EBP) [native] 221e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // TickSample::Trace 222df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org // 223a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 22477ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org CHECK(sample.has_external_callback); 22543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org CHECK_EQ(FUNCTION_ADDR(i::TraceExtension::JSTrace), sample.external_callback); 226a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 2279085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace" 22808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org unsigned base = 0; 229a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org CHECK_GT(sample.frames_count, base + 1); 230528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org CHECK(IsAddressWithinFuncCode(context, "JSTrace", sample.stack[base + 0])); 231528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org CHECK(IsAddressWithinFuncCode( 232528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org context, "OuterJSTrace", sample.stack[base + 1])); 2339085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org} 2349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 2359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 2363811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.orgstatic void CFuncDoTrace(byte dummy_parameter) { 2379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org Address fp; 238bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org#ifdef __GNUC__ 2399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org fp = reinterpret_cast<Address>(__builtin_frame_address(0)); 2403811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org#elif defined _MSC_VER 2413811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org // Approximate a frame pointer address. We compile without base pointers, 2423811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org // so we can't trust ebp/rbp. 2433811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org fp = &dummy_parameter - 2 * sizeof(void*); // NOLINT 2443811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org#else 2453811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org#error Unexpected platform. 246bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org#endif 24743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org i::TraceExtension::DoTrace(fp); 248bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org} 249bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org 250bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org 251bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.orgstatic int CFunc(int depth) { 252bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org if (depth <= 0) { 2533811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org CFuncDoTrace(0); 254bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org return 0; 255bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org } else { 256bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org return CFunc(depth - 1) + 1; 257bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org } 258bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org} 259bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org 260bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org 261df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org// This test verifies that stack tracing doesn't crash when called on 262e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// pure native code. TickSample::Trace only unrolls JS code, so we can't 263df7a284a293865a5fa9390be2e8f82ba3ac8598asgjesse@chromium.org// get any meaningful info here. 264bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.orgTEST(PureCStackTrace) { 265bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org TickSample sample; 26643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org i::TraceExtension::InitTraceEnv(&sample); 267528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org v8::HandleScope scope(CcTest::isolate()); 268528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org v8::Local<v8::Context> context = CcTest::NewContext(TRACE_EXTENSION); 269528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org v8::Context::Scope context_scope(context); 270bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org // Check that sampler doesn't crash 271bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org CHECK_EQ(10, CFunc(10)); 272bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org} 273bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org 274bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org 275e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.orgTEST(JsEntrySp) { 276e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org v8::HandleScope scope(CcTest::isolate()); 277528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org v8::Local<v8::Context> context = CcTest::NewContext(TRACE_EXTENSION); 278528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org v8::Context::Scope context_scope(context); 27943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org CHECK_EQ(0, i::TraceExtension::GetJsEntrySp()); 280e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org CompileRun("a = 1; b = a + 1;"); 28143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org CHECK_EQ(0, i::TraceExtension::GetJsEntrySp()); 282e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org CompileRun("js_entry_sp();"); 28343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org CHECK_EQ(0, i::TraceExtension::GetJsEntrySp()); 284e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org CompileRun("js_entry_sp_level2();"); 28543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org CHECK_EQ(0, i::TraceExtension::GetJsEntrySp()); 286e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org} 287