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

Side by Side Diff: src/ia32/full-codegen-ia32.cc

Issue 9633012: Profiler experiments: merge self-optimization code into interrupt-at-exit (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 9 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/ia32/deoptimizer-ia32.cc ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 // frames-ia32.h for its layout. 120 // frames-ia32.h for its layout.
121 void FullCodeGenerator::Generate() { 121 void FullCodeGenerator::Generate() {
122 CompilationInfo* info = info_; 122 CompilationInfo* info = info_;
123 handler_table_ = 123 handler_table_ =
124 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); 124 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
125 profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell( 125 profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell(
126 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget))); 126 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget)));
127 SetFunctionPosition(function()); 127 SetFunctionPosition(function());
128 Comment cmnt(masm_, "[ function compiled by full code generator"); 128 Comment cmnt(masm_, "[ function compiled by full code generator");
129 129
130 // We can optionally optimize based on counters rather than statistical
131 // sampling.
132 if (info->ShouldSelfOptimize()) {
133 if (FLAG_trace_opt_verbose) {
134 PrintF("[adding self-optimization header to %s]\n",
135 *info->function()->debug_name()->ToCString());
136 }
137 has_self_optimization_header_ = true;
138 MaybeObject* maybe_cell = isolate()->heap()->AllocateJSGlobalPropertyCell(
139 Smi::FromInt(Compiler::kCallsUntilPrimitiveOpt));
140 JSGlobalPropertyCell* cell;
141 if (maybe_cell->To(&cell)) {
142 __ sub(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)),
143 Immediate(Smi::FromInt(1)));
144 Handle<Code> compile_stub(
145 isolate()->builtins()->builtin(Builtins::kLazyRecompile));
146 STATIC_ASSERT(kSmiTag == 0);
147 __ j(zero, compile_stub);
148 ASSERT(masm_->pc_offset() == self_optimization_header_size());
149 }
150 }
151
152 #ifdef DEBUG 130 #ifdef DEBUG
153 if (strlen(FLAG_stop_at) > 0 && 131 if (strlen(FLAG_stop_at) > 0 &&
154 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 132 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
155 __ int3(); 133 __ int3();
156 } 134 }
157 #endif 135 #endif
158 136
159 // Strict mode functions and builtins need to replace the receiver 137 // Strict mode functions and builtins need to replace the receiver
160 // with undefined when called as functions (without an explicit 138 // with undefined when called as functions (without an explicit
161 // receiver object). ecx is zero for method calls and non-zero for 139 // receiver object). ecx is zero for method calls and non-zero for
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 EmitReturnSequence(); 301 EmitReturnSequence();
324 } 302 }
325 } 303 }
326 304
327 305
328 void FullCodeGenerator::ClearAccumulator() { 306 void FullCodeGenerator::ClearAccumulator() {
329 __ Set(eax, Immediate(Smi::FromInt(0))); 307 __ Set(eax, Immediate(Smi::FromInt(0)));
330 } 308 }
331 309
332 310
311 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
312 __ mov(ebx, Immediate(profiling_counter_));
313 __ sub(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
314 Immediate(Smi::FromInt(delta)));
315 }
316
317
318 void FullCodeGenerator::EmitProfilingCounterReset() {
319 int reset_value = FLAG_interrupt_budget;
320 if (info_->ShouldSelfOptimize() && !FLAG_retry_self_opt) {
321 // Self-optimization is a one-off thing: if it fails, don't try again.
322 reset_value = Smi::kMaxValue;
323 }
324 __ mov(ebx, Immediate(profiling_counter_));
325 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
326 Immediate(Smi::FromInt(reset_value)));
327 }
328
329
333 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt, 330 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt,
334 Label* back_edge_target) { 331 Label* back_edge_target) {
335 Comment cmnt(masm_, "[ Stack check"); 332 Comment cmnt(masm_, "[ Stack check");
336 Label ok; 333 Label ok;
337 334
338 if (FLAG_count_based_interrupts) { 335 if (FLAG_count_based_interrupts) {
339 int weight = 1; 336 int weight = 1;
340 if (FLAG_weighted_back_edges) { 337 if (FLAG_weighted_back_edges) {
341 ASSERT(back_edge_target->is_bound()); 338 ASSERT(back_edge_target->is_bound());
342 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); 339 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
343 weight = Min(127, Max(1, distance / 100)); 340 weight = Min(127, Max(1, distance / 100));
344 } 341 }
345 if (Serializer::enabled()) { 342 EmitProfilingCounterDecrement(weight);
346 __ mov(ebx, Immediate(profiling_counter_));
347 __ sub(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
348 Immediate(Smi::FromInt(weight)));
349 } else {
350 // This version is slightly faster, but not snapshot safe.
351 __ sub(Operand::Cell(profiling_counter_),
352 Immediate(Smi::FromInt(weight)));
353 }
354 __ j(positive, &ok, Label::kNear); 343 __ j(positive, &ok, Label::kNear);
355 InterruptStub stub; 344 InterruptStub stub;
356 __ CallStub(&stub); 345 __ CallStub(&stub);
357 } else { 346 } else {
358 // Count based interrupts happen often enough when they are enabled 347 // Count based interrupts happen often enough when they are enabled
359 // that the additional stack checks are not necessary (they would 348 // that the additional stack checks are not necessary (they would
360 // only check for interrupts). 349 // only check for interrupts).
361 ExternalReference stack_limit = 350 ExternalReference stack_limit =
362 ExternalReference::address_of_stack_limit(isolate()); 351 ExternalReference::address_of_stack_limit(isolate());
363 __ cmp(esp, Operand::StaticVariable(stack_limit)); 352 __ cmp(esp, Operand::StaticVariable(stack_limit));
364 __ j(above_equal, &ok, Label::kNear); 353 __ j(above_equal, &ok, Label::kNear);
365 StackCheckStub stub; 354 StackCheckStub stub;
366 __ CallStub(&stub); 355 __ CallStub(&stub);
367 } 356 }
368 357
369 // Record a mapping of this PC offset to the OSR id. This is used to find 358 // Record a mapping of this PC offset to the OSR id. This is used to find
370 // the AST id from the unoptimized code in order to use it as a key into 359 // the AST id from the unoptimized code in order to use it as a key into
371 // the deoptimization input data found in the optimized code. 360 // the deoptimization input data found in the optimized code.
372 RecordStackCheck(stmt->OsrEntryId()); 361 RecordStackCheck(stmt->OsrEntryId());
373 362
374 // Loop stack checks can be patched to perform on-stack replacement. In 363 // Loop stack checks can be patched to perform on-stack replacement. In
375 // order to decide whether or not to perform OSR we embed the loop depth 364 // order to decide whether or not to perform OSR we embed the loop depth
376 // in a test instruction after the call so we can extract it from the OSR 365 // in a test instruction after the call so we can extract it from the OSR
377 // builtin. 366 // builtin.
378 ASSERT(loop_depth() > 0); 367 ASSERT(loop_depth() > 0);
379 __ test(eax, Immediate(Min(loop_depth(), Code::kMaxLoopNestingMarker))); 368 __ test(eax, Immediate(Min(loop_depth(), Code::kMaxLoopNestingMarker)));
380 369
381 if (FLAG_count_based_interrupts) { 370 if (FLAG_count_based_interrupts) {
382 // Reset the countdown. 371 EmitProfilingCounterReset();
383 if (Serializer::enabled()) {
384 __ mov(ebx, Immediate(profiling_counter_));
385 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
386 Immediate(Smi::FromInt(FLAG_interrupt_budget)));
387 } else {
388 __ mov(Operand::Cell(profiling_counter_),
389 Immediate(Smi::FromInt(FLAG_interrupt_budget)));
390 }
391 } 372 }
392 373
393 __ bind(&ok); 374 __ bind(&ok);
394 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 375 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
395 // Record a mapping of the OSR id to this PC. This is used if the OSR 376 // Record a mapping of the OSR id to this PC. This is used if the OSR
396 // entry becomes the target of a bailout. We don't expect it to be, but 377 // entry becomes the target of a bailout. We don't expect it to be, but
397 // we want it to work if it is. 378 // we want it to work if it is.
398 PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); 379 PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
399 } 380 }
400 381
401 382
402 void FullCodeGenerator::EmitReturnSequence() { 383 void FullCodeGenerator::EmitReturnSequence() {
403 Comment cmnt(masm_, "[ Return sequence"); 384 Comment cmnt(masm_, "[ Return sequence");
404 if (return_label_.is_bound()) { 385 if (return_label_.is_bound()) {
405 __ jmp(&return_label_); 386 __ jmp(&return_label_);
406 } else { 387 } else {
407 // Common return label 388 // Common return label
408 __ bind(&return_label_); 389 __ bind(&return_label_);
409 if (FLAG_trace) { 390 if (FLAG_trace) {
410 __ push(eax); 391 __ push(eax);
411 __ CallRuntime(Runtime::kTraceExit, 1); 392 __ CallRuntime(Runtime::kTraceExit, 1);
412 } 393 }
413 if (FLAG_interrupt_at_exit) { 394 if (FLAG_interrupt_at_exit || FLAG_self_optimization) {
414 // Pretend that the exit is a backwards jump to the entry. 395 // Pretend that the exit is a backwards jump to the entry.
415 int weight = 1; 396 int weight = 1;
416 if (FLAG_weighted_back_edges) { 397 if (info_->ShouldSelfOptimize()) {
398 weight = FLAG_interrupt_budget / FLAG_self_opt_count;
399 } else if (FLAG_weighted_back_edges) {
417 int distance = masm_->pc_offset(); 400 int distance = masm_->pc_offset();
418 weight = Min(127, Max(1, distance / 100)); 401 weight = Min(127, Max(1, distance / 100));
419 } 402 }
420 if (Serializer::enabled()) { 403 EmitProfilingCounterDecrement(weight);
421 __ mov(ebx, Immediate(profiling_counter_));
422 __ sub(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
423 Immediate(Smi::FromInt(weight)));
424 } else {
425 // This version is slightly faster, but not snapshot safe.
426 __ sub(Operand::Cell(profiling_counter_),
427 Immediate(Smi::FromInt(weight)));
428 }
429 Label ok; 404 Label ok;
430 __ j(positive, &ok, Label::kNear); 405 __ j(positive, &ok, Label::kNear);
431 __ push(eax); 406 __ push(eax);
432 InterruptStub stub; 407 if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) {
433 __ CallStub(&stub); 408 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
409 __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1);
410 } else {
411 InterruptStub stub;
412 __ CallStub(&stub);
413 }
434 __ pop(eax); 414 __ pop(eax);
435 // Reset the countdown. 415 EmitProfilingCounterReset();
436 if (Serializer::enabled()) {
437 __ mov(ebx, Immediate(profiling_counter_));
438 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
439 Immediate(Smi::FromInt(FLAG_interrupt_budget)));
440 } else {
441 __ mov(Operand::Cell(profiling_counter_),
442 Immediate(Smi::FromInt(FLAG_interrupt_budget)));
443 }
444 __ bind(&ok); 416 __ bind(&ok);
445 } 417 }
446 #ifdef DEBUG 418 #ifdef DEBUG
447 // Add a label for checking the size of the code used for returning. 419 // Add a label for checking the size of the code used for returning.
448 Label check_exit_codesize; 420 Label check_exit_codesize;
449 masm_->bind(&check_exit_codesize); 421 masm_->bind(&check_exit_codesize);
450 #endif 422 #endif
451 SetSourcePosition(function()->end_position() - 1); 423 SetSourcePosition(function()->end_position() - 1);
452 __ RecordJSReturn(); 424 __ RecordJSReturn();
453 // Do not use the leave instruction here because it is too short to 425 // Do not use the leave instruction here because it is too short to
(...skipping 4012 matching lines...) Expand 10 before | Expand all | Expand 10 after
4466 *context_length = 0; 4438 *context_length = 0;
4467 return previous_; 4439 return previous_;
4468 } 4440 }
4469 4441
4470 4442
4471 #undef __ 4443 #undef __
4472 4444
4473 } } // namespace v8::internal 4445 } } // namespace v8::internal
4474 4446
4475 #endif // V8_TARGET_ARCH_IA32 4447 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/deoptimizer-ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698