OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
2 // | 2 // |
3 // Tests of profiler-related functions from log.h | 3 // Tests of profiler-related functions from log.h |
4 | 4 |
5 #include <stdlib.h> | 5 #include <stdlib.h> |
6 | 6 |
7 #include "v8.h" | 7 #include "v8.h" |
8 | 8 |
9 #include "log.h" | 9 #include "log.h" |
10 #include "cctest.h" | 10 #include "cctest.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 trace_env.sample->sp = trace_env.sample->fp - sizeof(unsigned int); | 44 trace_env.sample->sp = trace_env.sample->fp - sizeof(unsigned int); |
45 trace_env.tracer->Trace(trace_env.sample); | 45 trace_env.tracer->Trace(trace_env.sample); |
46 } | 46 } |
47 | 47 |
48 | 48 |
49 static void CFuncDoTrace() { | 49 static void CFuncDoTrace() { |
50 unsigned int fp; | 50 unsigned int fp; |
51 #ifdef __GNUC__ | 51 #ifdef __GNUC__ |
52 fp = reinterpret_cast<unsigned int>(__builtin_frame_address(0)); | 52 fp = reinterpret_cast<unsigned int>(__builtin_frame_address(0)); |
53 #elif defined _MSC_VER | 53 #elif defined _MSC_VER |
54 __asm mov [fp], ebp | 54 __asm mov [fp], ebp // NOLINT |
55 #endif | 55 #endif |
56 DoTrace(fp); | 56 DoTrace(fp); |
57 } | 57 } |
58 | 58 |
59 | 59 |
60 static void CFunc(int i) { | 60 static void CFunc(int i) { |
61 for (int j = i; j >= 0; --j) { | 61 for (int j = i; j >= 0; --j) { |
62 CFuncDoTrace(); | 62 CFuncDoTrace(); |
63 } | 63 } |
64 } | 64 } |
65 | 65 |
66 | 66 |
67 static void CheckRetAddrIsInFunction(unsigned int ret_addr, | 67 static void CheckRetAddrIsInFunction(unsigned int ret_addr, |
68 unsigned int func_start_addr, | 68 unsigned int func_start_addr, |
69 unsigned int func_len) { | 69 unsigned int func_len) { |
70 printf("CheckRetAddrIsInFunction: %08x %08x %08x\n", | 70 printf("CheckRetAddrIsInFunction: %08x %08x %08x\n", |
71 func_start_addr, ret_addr, func_start_addr + func_len); | 71 func_start_addr, ret_addr, func_start_addr + func_len); |
72 CHECK_GE(ret_addr, func_start_addr); | 72 CHECK_GE(ret_addr, func_start_addr); |
73 CHECK_GE(func_start_addr + func_len, ret_addr); | 73 CHECK_GE(func_start_addr + func_len, ret_addr); |
74 } | 74 } |
75 | 75 |
76 | 76 |
77 #ifdef DEBUG | 77 #ifdef DEBUG |
78 static const int kMaxCFuncLen = 0x40; // seems enough for a small C function | 78 static const int kMaxCFuncLen = 0x40; // seems enough for a small C function |
79 | 79 |
80 static void CheckRetAddrIsInCFunction(unsigned int ret_addr, | 80 static void CheckRetAddrIsInCFunction(unsigned int ret_addr, |
81 unsigned int func_start_addr) { | 81 unsigned int func_start_addr) { |
82 CheckRetAddrIsInFunction(ret_addr, func_start_addr, kMaxCFuncLen); | 82 CheckRetAddrIsInFunction(ret_addr, func_start_addr, kMaxCFuncLen); |
83 } | 83 } |
84 #endif | 84 #endif |
85 | 85 |
86 | 86 |
87 TEST(PureCStackTrace) { | 87 TEST(PureCStackTrace) { |
88 TickSample sample; | 88 TickSample sample; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 static Local<Value> GetGlobalProperty(const char* name) { | 159 static Local<Value> GetGlobalProperty(const char* name) { |
160 return env->Global()->Get(String::New(name)); | 160 return env->Global()->Get(String::New(name)); |
161 } | 161 } |
162 | 162 |
163 | 163 |
164 static void SetGlobalProperty(const char* name, Local<Value> value) { | 164 static void SetGlobalProperty(const char* name, Local<Value> value) { |
165 env->Global()->Set(String::New(name), value); | 165 env->Global()->Set(String::New(name), value); |
166 } | 166 } |
167 | 167 |
168 | 168 |
169 static bool Patch(byte* from, size_t num, byte* original, byte* patch, size_t pa
tch_len) { | 169 static bool Patch(byte* from, |
| 170 size_t num, |
| 171 byte* original, |
| 172 byte* patch, |
| 173 size_t patch_len) { |
170 byte* to = from + num; | 174 byte* to = from + num; |
171 do { | 175 do { |
172 from = (byte*)memchr(from, *original, to - from); | 176 from = static_cast<byte*>(memchr(from, *original, to - from)); |
173 CHECK(from != NULL); | 177 CHECK(from != NULL); |
174 if (memcmp(original, from, patch_len) == 0) { | 178 if (memcmp(original, from, patch_len) == 0) { |
175 memcpy(from, patch, patch_len); | 179 memcpy(from, patch, patch_len); |
176 return true; | 180 return true; |
177 } else { | 181 } else { |
178 from++; | 182 from++; |
179 } | 183 } |
180 } while (to - from > 0); | 184 } while (to - from > 0); |
181 return false; | 185 return false; |
182 } | 186 } |
183 | 187 |
184 | 188 |
185 TEST(PureJSStackTrace) { | 189 TEST(PureJSStackTrace) { |
186 TickSample sample; | 190 TickSample sample; |
187 StackTracer tracer(reinterpret_cast<unsigned int>(&sample)); | 191 StackTracer tracer(reinterpret_cast<unsigned int>(&sample)); |
188 InitTraceEnv(&tracer, &sample); | 192 InitTraceEnv(&tracer, &sample); |
189 | 193 |
190 InitializeVM(); | 194 InitializeVM(); |
191 v8::HandleScope scope; | 195 v8::HandleScope scope; |
192 Handle<JSFunction> call_trace = CompileFunction("trace(0x6666);"); | 196 Handle<JSFunction> call_trace = CompileFunction("trace(0x6666);"); |
193 CHECK(!call_trace.is_null()); | 197 CHECK(!call_trace.is_null()); |
194 v8::internal::Code* call_trace_code = call_trace->code(); | 198 v8::internal::Code* call_trace_code = call_trace->code(); |
195 CHECK(call_trace_code->IsCode()); | 199 CHECK(call_trace_code->IsCode()); |
196 | 200 |
197 byte original[] = { 0x68, 0xcc, 0xcc, 0x00, 0x00 }; // push 0xcccc (= 0x6666 <
< 1) | 201 // push 0xcccc (= 0x6666 << 1) |
198 byte patch[] = { 0x89, 0xe8, 0xd1, 0xe8, 0x50 }; // mov eax,ebp; shr eax; push
eax; | 202 byte original[] = { 0x68, 0xcc, 0xcc, 0x00, 0x00 }; |
| 203 // mov eax,ebp; shr eax; push eax; |
| 204 byte patch[] = { 0x89, 0xe8, 0xd1, 0xe8, 0x50 }; |
199 // Patch generated code to replace pushing of a constant with | 205 // Patch generated code to replace pushing of a constant with |
200 // pushing of ebp contents in a Smi | 206 // pushing of ebp contents in a Smi |
201 CHECK(Patch(call_trace_code->instruction_start(), | 207 CHECK(Patch(call_trace_code->instruction_start(), |
202 call_trace_code->instruction_size(), | 208 call_trace_code->instruction_size(), |
203 original, patch, sizeof(patch))); | 209 original, patch, sizeof(patch))); |
204 | 210 |
205 SetGlobalProperty("JSFuncDoTrace", v8::ToApi<Value>(call_trace)); | 211 SetGlobalProperty("JSFuncDoTrace", v8::ToApi<Value>(call_trace)); |
206 | 212 |
207 CompileRun( | 213 CompileRun( |
208 "function JSTrace() {" | 214 "function JSTrace() {" |
209 " JSFuncDoTrace();" | 215 " JSFuncDoTrace();" |
210 "};\n" | 216 "};\n" |
211 "JSTrace();"); | 217 "JSTrace();"); |
212 Handle<JSFunction> js_trace(JSFunction::cast(*(v8::Utils::OpenHandle( | 218 Handle<JSFunction> js_trace(JSFunction::cast(*(v8::Utils::OpenHandle( |
213 *GetGlobalProperty("JSTrace"))))); | 219 *GetGlobalProperty("JSTrace"))))); |
214 v8::internal::Code* js_trace_code = js_trace->code(); | 220 v8::internal::Code* js_trace_code = js_trace->code(); |
215 CheckRetAddrIsInFunction(reinterpret_cast<unsigned int>(sample.stack[0]), | 221 CheckRetAddrIsInFunction( |
216 reinterpret_cast<unsigned int>(js_trace_code->instruc
tion_start()), | 222 reinterpret_cast<unsigned int>(sample.stack[0]), |
217 js_trace_code->instruction_size()); | 223 reinterpret_cast<unsigned int>(js_trace_code->instruction_start()), |
| 224 js_trace_code->instruction_size()); |
218 CHECK_EQ(0, sample.stack[1]); | 225 CHECK_EQ(0, sample.stack[1]); |
219 } | 226 } |
OLD | NEW |