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

Side by Side Diff: test/cctest/test-log-stack-tracer.cc

Issue 3311002: Remove CodeGenerator::PatchInlineRuntimeEntry and replace its single use in t... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 3 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/codegen-x64.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2010 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.
2 // 27 //
3 // Tests of profiler-related functions from log.h 28 // Tests of profiler-related functions from log.h
4 29
5 #ifdef ENABLE_LOGGING_AND_PROFILING 30 #ifdef ENABLE_LOGGING_AND_PROFILING
6 31
7 #include <stdlib.h> 32 #include <stdlib.h>
8 33
9 #include "v8.h" 34 #include "v8.h"
10 35
11 #include "codegen.h" 36 #include "codegen.h"
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 } else if (name->Equals(String::New("js_entry_sp_level2"))) { 125 } else if (name->Equals(String::New("js_entry_sp_level2"))) {
101 return v8::FunctionTemplate::New(TraceExtension::JSEntrySPLevel2); 126 return v8::FunctionTemplate::New(TraceExtension::JSEntrySPLevel2);
102 } else { 127 } else {
103 CHECK(false); 128 CHECK(false);
104 return v8::Handle<v8::FunctionTemplate>(); 129 return v8::Handle<v8::FunctionTemplate>();
105 } 130 }
106 } 131 }
107 132
108 133
109 Address TraceExtension::GetFP(const v8::Arguments& args) { 134 Address TraceExtension::GetFP(const v8::Arguments& args) {
110 CHECK_EQ(1, args.Length()); 135 // Convert frame pointer from encoding as smis in the arguments to a pointer.
111 // CodeGenerator::GenerateGetFramePointer pushes EBP / RBP value 136 CHECK_EQ(2, args.Length()); // Ignore second argument on 32-bit platform.
112 // on stack. In 64-bit mode we can't use Smi operations code because 137 #if defined(V8_HOST_ARCH_32_BIT)
113 // they check that value is within Smi bounds.
114 Address fp = *reinterpret_cast<Address*>(*args[0]); 138 Address fp = *reinterpret_cast<Address*>(*args[0]);
139 #elif defined(V8_HOST_ARCH_64_BIT)
140 int64_t low_bits = *reinterpret_cast<uint64_t*>(*args[0]) >> 32;
141 int64_t high_bits = *reinterpret_cast<uint64_t*>(*args[1]);
142 Address fp = reinterpret_cast<Address>(high_bits | low_bits);
143 #else
144 #error Host architecture is neither 32-bit nor 64-bit.
145 #endif
115 printf("Trace: %p\n", fp); 146 printf("Trace: %p\n", fp);
116 return fp; 147 return fp;
117 } 148 }
118 149
119 150
120 v8::Handle<v8::Value> TraceExtension::Trace(const v8::Arguments& args) { 151 v8::Handle<v8::Value> TraceExtension::Trace(const v8::Arguments& args) {
121 DoTrace(GetFP(args)); 152 DoTrace(GetFP(args));
122 return v8::Undefined(); 153 return v8::Undefined();
123 } 154 }
124 155
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 static void SetGlobalProperty(const char* name, Local<Value> value) { 234 static void SetGlobalProperty(const char* name, Local<Value> value) {
204 env->Global()->Set(String::New(name), value); 235 env->Global()->Set(String::New(name), value);
205 } 236 }
206 237
207 238
208 static Handle<v8::internal::String> NewString(const char* s) { 239 static Handle<v8::internal::String> NewString(const char* s) {
209 return i::Factory::NewStringFromAscii(i::CStrVector(s)); 240 return i::Factory::NewStringFromAscii(i::CStrVector(s));
210 } 241 }
211 242
212 243
213 namespace v8 { 244 // This C++ function is called as a constructor, to grab the frame pointer
214 namespace internal { 245 // from the calling function. When this function runs, the stack contains
246 // a C_Entry frame and a Construct frame above the calling function's frame.
247 static v8::Handle<Value> construct_call(const v8::Arguments& args) {
248 i::StackFrameIterator frame_iterator;
249 CHECK(frame_iterator.frame()->is_exit());
250 frame_iterator.Advance();
251 CHECK(frame_iterator.frame()->is_construct());
252 frame_iterator.Advance();
253 i::StackFrame* calling_frame = frame_iterator.frame();
254 CHECK(calling_frame->is_java_script());
215 255
216 class CodeGeneratorPatcher { 256 #if defined(V8_HOST_ARCH_32_BIT)
217 public: 257 int32_t low_bits = reinterpret_cast<intptr_t>(calling_frame->fp());
218 CodeGeneratorPatcher() { 258 args.This()->Set(v8_str("low_bits"), v8_num(low_bits >> 1));
219 CodeGenerator::InlineRuntimeLUT gen_get_frame_pointer = 259 #elif defined(V8_HOST_ARCH_64_BIT)
220 {&CodeGenerator::GenerateGetFramePointer, "_GetFramePointer", 0}; 260 int32_t low_bits = reinterpret_cast<uintptr_t>(calling_frame->fp());
221 // _RandomHeapNumber is just used as a dummy function that has zero 261 int32_t high_bits = reinterpret_cast<uintptr_t>(calling_frame->fp()) >> 32;
222 // arguments, the same as the _GetFramePointer function we actually patch 262 args.This()->Set(v8_str("low_bits"), v8_num(low_bits));
223 // in. 263 args.This()->Set(v8_str("high_bits"), v8_num(high_bits));
224 bool result = CodeGenerator::PatchInlineRuntimeEntry( 264 #else
225 NewString("_RandomHeapNumber"), 265 #error Host architecture is neither 32-bit nor 64-bit.
226 gen_get_frame_pointer, &old_inline_entry); 266 #endif
227 CHECK(result); 267 return args.This();
228 } 268 }
229 269
230 ~CodeGeneratorPatcher() {
231 CHECK(CodeGenerator::PatchInlineRuntimeEntry(
232 NewString("_GetFramePointer"),
233 old_inline_entry, NULL));
234 }
235 270
236 private: 271 // Use the API to create a JSFunction object that calls the above C++ function.
237 CodeGenerator::InlineRuntimeLUT old_inline_entry; 272 void CreateFramePointerGrabberConstructor(const char* constructor_name) {
238 }; 273 Local<v8::FunctionTemplate> constructor_template =
239 274 v8::FunctionTemplate::New(construct_call);
240 } } // namespace v8::internal 275 constructor_template->SetClassName(v8_str("FPGrabber"));
276 Local<Function> fun = constructor_template->GetFunction();
277 env->Global()->Set(v8_str(constructor_name), fun);
278 }
241 279
242 280
243 // Creates a global function named 'func_name' that calls the tracing 281 // Creates a global function named 'func_name' that calls the tracing
244 // function 'trace_func_name' with an actual EBP register value, 282 // function 'trace_func_name' with an actual EBP register value,
245 // shifted right to be presented as Smi. 283 // encoded as one or two Smis.
246 static void CreateTraceCallerFunction(const char* func_name, 284 static void CreateTraceCallerFunction(const char* func_name,
247 const char* trace_func_name) { 285 const char* trace_func_name) {
248 i::EmbeddedVector<char, 256> trace_call_buf; 286 i::EmbeddedVector<char, 256> trace_call_buf;
249 i::OS::SNPrintF(trace_call_buf, "%s(%%_GetFramePointer());", trace_func_name); 287 i::OS::SNPrintF(trace_call_buf,
288 "fp = new FPGrabber(); %s(fp.low_bits, fp.high_bits);",
289 trace_func_name);
290
291 // Create the FPGrabber function, which grabs the caller's frame pointer
292 // when called as a constructor.
293 CreateFramePointerGrabberConstructor("FPGrabber");
250 294
251 // Compile the script. 295 // Compile the script.
252 i::CodeGeneratorPatcher patcher;
253 bool allow_natives_syntax = i::FLAG_allow_natives_syntax;
254 i::FLAG_allow_natives_syntax = true;
255 Handle<JSFunction> func = CompileFunction(trace_call_buf.start()); 296 Handle<JSFunction> func = CompileFunction(trace_call_buf.start());
256 CHECK(!func.is_null()); 297 CHECK(!func.is_null());
257 i::FLAG_allow_natives_syntax = allow_natives_syntax;
258 func->shared()->set_name(*NewString(func_name)); 298 func->shared()->set_name(*NewString(func_name));
259 299
260 #ifdef DEBUG 300 #ifdef DEBUG
261 v8::internal::Code* func_code = func->code(); 301 v8::internal::Code* func_code = func->code();
262 CHECK(func_code->IsCode()); 302 CHECK(func_code->IsCode());
263 func_code->Print(); 303 func_code->Print();
264 #endif 304 #endif
265 305
266 SetGlobalProperty(func_name, v8::ToApi<Value>(func)); 306 SetGlobalProperty(func_name, v8::ToApi<Value>(func));
267 CHECK_EQ(*func, *GetGlobalJSFunction(func_name)); 307 CHECK_EQ(*func, *GetGlobalJSFunction(func_name));
268 } 308 }
269 309
270 310
271 // This test verifies that stack tracing works when called during 311 // This test verifies that stack tracing works when called during
272 // execution of a native function called from JS code. In this case, 312 // execution of a native function called from JS code. In this case,
273 // StackTracer uses Top::c_entry_fp as a starting point for stack 313 // StackTracer uses Top::c_entry_fp as a starting point for stack
274 // walking. 314 // walking.
275 TEST(CFromJSStackTrace) { 315 TEST(CFromJSStackTrace) {
276 // TODO(711): The hack of replacing the inline runtime function
277 // RandomHeapNumber with GetFrameNumber does not work with the way
278 // the full compiler generates inline runtime calls.
279 i::FLAG_full_compiler = false;
280 i::FLAG_always_full_compiler = false;
281
282 TickSample sample; 316 TickSample sample;
283 InitTraceEnv(&sample); 317 InitTraceEnv(&sample);
284 318
285 InitializeVM(); 319 InitializeVM();
286 v8::HandleScope scope; 320 v8::HandleScope scope;
287 // Create global function JSFuncDoTrace which calls 321 // Create global function JSFuncDoTrace which calls
288 // extension function trace() with the current frame pointer value. 322 // extension function trace() with the current frame pointer value.
289 CreateTraceCallerFunction("JSFuncDoTrace", "trace"); 323 CreateTraceCallerFunction("JSFuncDoTrace", "trace");
290 Local<Value> result = CompileRun( 324 Local<Value> result = CompileRun(
291 "function JSTrace() {" 325 "function JSTrace() {"
(...skipping 15 matching lines...) Expand all
307 CheckObjectIsJSFunction("JSTrace", sample.stack[1]); 341 CheckObjectIsJSFunction("JSTrace", sample.stack[1]);
308 } 342 }
309 343
310 344
311 // This test verifies that stack tracing works when called during 345 // This test verifies that stack tracing works when called during
312 // execution of JS code. However, as calling StackTracer requires 346 // execution of JS code. However, as calling StackTracer requires
313 // entering native code, we can only emulate pure JS by erasing 347 // entering native code, we can only emulate pure JS by erasing
314 // Top::c_entry_fp value. In this case, StackTracer uses passed frame 348 // Top::c_entry_fp value. In this case, StackTracer uses passed frame
315 // pointer value as a starting point for stack walking. 349 // pointer value as a starting point for stack walking.
316 TEST(PureJSStackTrace) { 350 TEST(PureJSStackTrace) {
317 // TODO(711): The hack of replacing the inline runtime function
318 // RandomHeapNumber with GetFrameNumber does not work with the way
319 // the full compiler generates inline runtime calls.
320 i::FLAG_full_compiler = false;
321 i::FLAG_always_full_compiler = false;
322
323 TickSample sample; 351 TickSample sample;
324 InitTraceEnv(&sample); 352 InitTraceEnv(&sample);
325 353
326 InitializeVM(); 354 InitializeVM();
327 v8::HandleScope scope; 355 v8::HandleScope scope;
328 // Create global function JSFuncDoTrace which calls 356 // Create global function JSFuncDoTrace which calls
329 // extension function js_trace() with the current frame pointer value. 357 // extension function js_trace() with the current frame pointer value.
330 CreateTraceCallerFunction("JSFuncDoTrace", "js_trace"); 358 CreateTraceCallerFunction("JSFuncDoTrace", "js_trace");
331 Local<Value> result = CompileRun( 359 Local<Value> result = CompileRun(
332 "function JSTrace() {" 360 "function JSTrace() {"
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 CHECK_EQ(0, GetJsEntrySp()); 428 CHECK_EQ(0, GetJsEntrySp());
401 CompileRun("a = 1; b = a + 1;"); 429 CompileRun("a = 1; b = a + 1;");
402 CHECK_EQ(0, GetJsEntrySp()); 430 CHECK_EQ(0, GetJsEntrySp());
403 CompileRun("js_entry_sp();"); 431 CompileRun("js_entry_sp();");
404 CHECK_EQ(0, GetJsEntrySp()); 432 CHECK_EQ(0, GetJsEntrySp());
405 CompileRun("js_entry_sp_level2();"); 433 CompileRun("js_entry_sp_level2();");
406 CHECK_EQ(0, GetJsEntrySp()); 434 CHECK_EQ(0, GetJsEntrySp());
407 } 435 }
408 436
409 #endif // ENABLE_LOGGING_AND_PROFILING 437 #endif // ENABLE_LOGGING_AND_PROFILING
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698