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

Unified Diff: test/cctest/test-log-ia32.cc

Issue 108015: Restore stack backtrace tests removed in revision 1785. (Closed)
Patch Set: Addressed Kevin's comments Created 11 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ia32/codegen-ia32.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/cctest/test-log-ia32.cc
diff --git a/test/cctest/test-log-ia32.cc b/test/cctest/test-log-ia32.cc
index dde8512090ccabea85bbe7d5195077ac581605a0..43cb294b17fcb8881de91e52c5fbdde2de9c2bd7 100644
--- a/test/cctest/test-log-ia32.cc
+++ b/test/cctest/test-log-ia32.cc
@@ -8,9 +8,11 @@
#include "v8.h"
+#include "codegen.h"
#include "log.h"
#include "top.h"
#include "cctest.h"
+#include "disassembler.h"
using v8::Function;
using v8::Local;
@@ -20,12 +22,15 @@ using v8::String;
using v8::Value;
using v8::internal::byte;
+using v8::internal::Address;
using v8::internal::Handle;
using v8::internal::JSFunction;
using v8::internal::StackTracer;
using v8::internal::TickSample;
using v8::internal::Top;
+namespace i = v8::internal;
+
static v8::Persistent<v8::Context> env;
@@ -42,8 +47,8 @@ static void InitTraceEnv(StackTracer* tracer, TickSample* sample) {
}
-static void DoTrace(unsigned int fp) {
- trace_env.sample->fp = fp;
+static void DoTrace(Address fp) {
+ trace_env.sample->fp = reinterpret_cast<uintptr_t>(fp);
// sp is only used to define stack high bound
trace_env.sample->sp =
reinterpret_cast<unsigned int>(trace_env.sample) - 10240;
@@ -53,7 +58,7 @@ static void DoTrace(unsigned int fp) {
// Hide c_entry_fp to emulate situation when sampling is done while
// pure JS code is being executed
-static void DoTraceHideCEntryFPAddress(unsigned int fp) {
+static void DoTraceHideCEntryFPAddress(Address fp) {
v8::internal::Address saved_c_frame_fp = *(Top::c_entry_fp_address());
CHECK(saved_c_frame_fp);
*(Top::c_entry_fp_address()) = 0;
@@ -62,6 +67,28 @@ static void DoTraceHideCEntryFPAddress(unsigned int fp) {
}
+static void CheckRetAddrIsInFunction(const char* func_name,
+ Address ret_addr,
+ Address func_start_addr,
+ unsigned int func_len) {
+ printf("CheckRetAddrIsInFunction \"%s\": %p %p %p\n",
+ func_name, func_start_addr, ret_addr, func_start_addr + func_len);
+ CHECK_GE(ret_addr, func_start_addr);
+ CHECK_GE(func_start_addr + func_len, ret_addr);
+}
+
+
+static void CheckRetAddrIsInJSFunction(const char* func_name,
+ Address ret_addr,
+ Handle<JSFunction> func) {
+ v8::internal::Code* func_code = func->code();
+ CheckRetAddrIsInFunction(
+ func_name, ret_addr,
+ func_code->instruction_start(),
+ func_code->ExecutableSize());
+}
+
+
// --- T r a c e E x t e n s i o n ---
class TraceExtension : public v8::Extension {
@@ -72,7 +99,7 @@ class TraceExtension : public v8::Extension {
static v8::Handle<v8::Value> Trace(const v8::Arguments& args);
static v8::Handle<v8::Value> JSTrace(const v8::Arguments& args);
private:
- static unsigned int GetFP(const v8::Arguments& args);
+ static Address GetFP(const v8::Arguments& args);
static const char* kSource;
};
@@ -95,10 +122,10 @@ v8::Handle<v8::FunctionTemplate> TraceExtension::GetNativeFunction(
}
-unsigned int TraceExtension::GetFP(const v8::Arguments& args) {
+Address TraceExtension::GetFP(const v8::Arguments& args) {
CHECK_EQ(1, args.Length());
- unsigned int fp = args[0]->Int32Value() << 2;
- printf("Trace: %08x\n", fp);
+ Address fp = reinterpret_cast<Address>(args[0]->Int32Value() << 2);
+ printf("Trace: %p\n", fp);
return fp;
}
@@ -119,10 +146,162 @@ static TraceExtension kTraceExtension;
v8::DeclareExtension kTraceExtensionDeclaration(&kTraceExtension);
+static void InitializeVM() {
+ if (env.IsEmpty()) {
+ v8::HandleScope scope;
+ const char* extensions[] = { "v8/trace" };
+ v8::ExtensionConfiguration config(1, extensions);
+ env = v8::Context::New(&config);
+ }
+ v8::HandleScope scope;
+ env->Enter();
+}
+
+
+static Handle<JSFunction> CompileFunction(const char* source) {
+ return v8::Utils::OpenHandle(*Script::Compile(String::New(source)));
+}
+
+
+static void CompileRun(const char* source) {
+ Script::Compile(String::New(source))->Run();
+}
+
+
+static Local<Value> GetGlobalProperty(const char* name) {
+ return env->Global()->Get(String::New(name));
+}
+
+
+static Handle<JSFunction> GetGlobalJSFunction(const char* name) {
+ Handle<JSFunction> js_func(JSFunction::cast(
+ *(v8::Utils::OpenHandle(
+ *GetGlobalProperty(name)))));
+ return js_func;
+}
+
+
+static void CheckRetAddrIsInJSFunction(const char* func_name,
+ Address ret_addr) {
+ CheckRetAddrIsInJSFunction(func_name, ret_addr,
+ GetGlobalJSFunction(func_name));
+}
+
+
+static void SetGlobalProperty(const char* name, Local<Value> value) {
+ env->Global()->Set(String::New(name), value);
+}
+
+
+static Handle<v8::internal::String> NewString(const char* s) {
+ return i::Factory::NewStringFromAscii(i::CStrVector(s));
+}
+
+
+namespace v8 { namespace internal {
+
+class CodeGeneratorPatcher {
+ public:
+ CodeGeneratorPatcher() {
+ CodeGenerator::InlineRuntimeLUT genGetFramePointer =
+ {&CodeGenerator::GenerateGetFramePointer, "_GetFramePointer"};
+ // _FastCharCodeAt is not used in our tests.
+ bool result = CodeGenerator::PatchInlineRuntimeEntry(
+ NewString("_FastCharCodeAt"),
+ genGetFramePointer, &oldInlineEntry);
+ CHECK(result);
+ }
+
+ ~CodeGeneratorPatcher() {
+ CHECK(CodeGenerator::PatchInlineRuntimeEntry(
+ NewString("_GetFramePointer"),
+ oldInlineEntry, NULL));
+ }
+
+ private:
+ CodeGenerator::InlineRuntimeLUT oldInlineEntry;
+};
+
+} } // namespace v8::internal
+
+
+// Creates a global function named 'func_name' that calls the tracing
+// function 'trace_func_name' with an actual EBP register value,
+// shifted right to be presented as Smi.
+static void CreateTraceCallerFunction(const char* func_name,
+ const char* trace_func_name) {
+ i::EmbeddedVector<char, 256> trace_call_buf;
+ i::OS::SNPrintF(trace_call_buf, "%s(%%_GetFramePointer());", trace_func_name);
+
+ // Compile the script.
+ i::CodeGeneratorPatcher patcher;
+ bool allow_natives_syntax = i::FLAG_allow_natives_syntax;
+ i::FLAG_allow_natives_syntax = true;
+ Handle<JSFunction> func = CompileFunction(trace_call_buf.start());
+ CHECK(!func.is_null());
+ i::FLAG_allow_natives_syntax = allow_natives_syntax;
+
+#ifdef DEBUG
+ v8::internal::Code* func_code = func->code();
+ CHECK(func_code->IsCode());
+ func_code->Print();
+#endif
+
+ SetGlobalProperty(func_name, v8::ToApi<Value>(func));
+}
+
+
+TEST(CFromJSStackTrace) {
+ TickSample sample;
+ StackTracer tracer(reinterpret_cast<uintptr_t>(&sample));
+ InitTraceEnv(&tracer, &sample);
+
+ InitializeVM();
+ v8::HandleScope scope;
+ CreateTraceCallerFunction("JSFuncDoTrace", "trace");
+ CompileRun(
+ "function JSTrace() {"
+ " JSFuncDoTrace();"
+ "};\n"
+ "JSTrace();");
+ CHECK_GT(sample.frames_count, 1);
+ // Stack sampling will start from the first JS function, i.e. "JSFuncDoTrace"
+ CheckRetAddrIsInJSFunction("JSFuncDoTrace",
+ sample.stack[0]);
+ CheckRetAddrIsInJSFunction("JSTrace",
+ sample.stack[1]);
+}
+
+
+TEST(PureJSStackTrace) {
+ TickSample sample;
+ StackTracer tracer(reinterpret_cast<uintptr_t>(&sample));
+ InitTraceEnv(&tracer, &sample);
+
+ InitializeVM();
+ v8::HandleScope scope;
+ CreateTraceCallerFunction("JSFuncDoTrace", "js_trace");
+ CompileRun(
+ "function JSTrace() {"
+ " JSFuncDoTrace();"
+ "};\n"
+ "function OuterJSTrace() {"
+ " JSTrace();"
+ "};\n"
+ "OuterJSTrace();");
+ CHECK_GT(sample.frames_count, 1);
+ // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace"
+ CheckRetAddrIsInJSFunction("JSTrace",
+ sample.stack[0]);
+ CheckRetAddrIsInJSFunction("OuterJSTrace",
+ sample.stack[1]);
+}
+
+
static void CFuncDoTrace() {
- unsigned int fp;
+ Address fp;
#ifdef __GNUC__
- fp = reinterpret_cast<unsigned int>(__builtin_frame_address(0));
+ fp = reinterpret_cast<Address>(__builtin_frame_address(0));
#elif defined _MSC_VER
__asm mov [fp], ebp // NOLINT
#endif
@@ -142,7 +321,7 @@ static int CFunc(int depth) {
TEST(PureCStackTrace) {
TickSample sample;
- StackTracer tracer(reinterpret_cast<unsigned int>(&sample));
+ StackTracer tracer(reinterpret_cast<uintptr_t>(&sample));
InitTraceEnv(&tracer, &sample);
// Check that sampler doesn't crash
CHECK_EQ(10, CFunc(10));
« no previous file with comments | « src/ia32/codegen-ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698