From: jkummerow@chromium.org Date: Mon, 27 Feb 2012 07:49:14 +0000 (+0000) Subject: Profiler experiments: Fix debugger in the presence of self-optimization headers X-Git-Tag: upstream/4.7.83~17263 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a19c50afb49e6e1800a5c836b25264b6d3dd57c0;p=platform%2Fupstream%2Fv8.git Profiler experiments: Fix debugger in the presence of self-optimization headers Review URL: https://chromiumcodereview.appspot.com/9466012 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10834 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index b48e842..51e9208 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -109,6 +109,11 @@ class JumpPatchSite BASE_EMBEDDED { }; +int FullCodeGenerator::self_optimization_header_size() { + return 24; +} + + // Generate code for a JS function. On entry to the function the receiver // and arguments have been pushed on the stack left to right. The actual // argument count matches the formal parameter count expected by the @@ -130,13 +135,6 @@ void FullCodeGenerator::Generate() { SetFunctionPosition(function()); Comment cmnt(masm_, "[ function compiled by full code generator"); -#ifdef DEBUG - if (strlen(FLAG_stop_at) > 0 && - info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { - __ stop("stop-at"); - } -#endif - // We can optionally optimize based on counters rather than statistical // sampling. if (info->ShouldSelfOptimize()) { @@ -144,6 +142,7 @@ void FullCodeGenerator::Generate() { PrintF("[adding self-optimization header to %s]\n", *info->function()->debug_name()->ToCString()); } + has_self_optimization_header_ = true; MaybeObject* maybe_cell = isolate()->heap()->AllocateJSGlobalPropertyCell( Smi::FromInt(Compiler::kCallsUntilPrimitiveOpt)); JSGlobalPropertyCell* cell; @@ -155,9 +154,17 @@ void FullCodeGenerator::Generate() { Handle compile_stub( isolate()->builtins()->builtin(Builtins::kLazyRecompile)); __ Jump(compile_stub, RelocInfo::CODE_TARGET, eq); + ASSERT(masm_->pc_offset() == self_optimization_header_size()); } } +#ifdef DEBUG + if (strlen(FLAG_stop_at) > 0 && + info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { + __ stop("stop-at"); + } +#endif + // Strict mode functions and builtins need to replace the receiver // with undefined when called as functions (without an explicit // receiver object). r5 is zero for method calls and non-zero for diff --git a/src/debug.cc b/src/debug.cc index f2c4dda..2058d48 100644 --- a/src/debug.cc +++ b/src/debug.cc @@ -37,6 +37,7 @@ #include "debug.h" #include "deoptimizer.h" #include "execution.h" +#include "full-codegen.h" #include "global-handles.h" #include "ic.h" #include "ic-inl.h" @@ -1752,7 +1753,6 @@ static bool CompileFullCodeForDebugging(Handle shared, ASSERT(new_code->has_debug_break_slots()); ASSERT(current_code->is_compiled_optimizable() == new_code->is_compiled_optimizable()); - ASSERT(current_code->instruction_size() <= new_code->instruction_size()); } #endif return result; @@ -1830,6 +1830,13 @@ static void RedirectActivationsToRecompiledCodeOnThread( // break slots. debug_break_slot_count++; } + if (frame_code->has_self_optimization_header() && + !new_code->has_self_optimization_header()) { + delta -= FullCodeGenerator::self_optimization_header_size(); + } else { + ASSERT(frame_code->has_self_optimization_header() == + new_code->has_self_optimization_header()); + } int debug_break_slot_bytes = debug_break_slot_count * Assembler::kDebugBreakSlotLength; if (FLAG_trace_deopt) { diff --git a/src/full-codegen.cc b/src/full-codegen.cc index 3d10e96..9639542 100644 --- a/src/full-codegen.cc +++ b/src/full-codegen.cc @@ -302,6 +302,7 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) { Code::Flags flags = Code::ComputeFlags(Code::FUNCTION); Handle code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info); code->set_optimizable(info->IsOptimizable()); + code->set_self_optimization_header(cgen.has_self_optimization_header_); cgen.PopulateDeoptimizationData(code); cgen.PopulateTypeFeedbackInfo(code); cgen.PopulateTypeFeedbackCells(code); @@ -365,6 +366,7 @@ void FullCodeGenerator::PopulateDeoptimizationData(Handle code) { void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle code) { Handle info = isolate()->factory()->NewTypeFeedbackInfo(); info->set_ic_total_count(ic_total_count_); + ASSERT(!isolate()->heap()->InNewSpace(*info)); code->set_type_feedback_info(*info); } diff --git a/src/full-codegen.h b/src/full-codegen.h index c1dec15..0ffb885 100644 --- a/src/full-codegen.h +++ b/src/full-codegen.h @@ -90,10 +90,15 @@ class FullCodeGenerator: public AstVisitor { stack_checks_(2), // There's always at least one. type_feedback_cells_(info->HasDeoptimizationSupport() ? info->function()->ast_node_count() : 0), - ic_total_count_(0) { } + ic_total_count_(0), + has_self_optimization_header_(false) { } static bool MakeCode(CompilationInfo* info); + // Returns the platform-specific size in bytes of the self-optimization + // header. + static int self_optimization_header_size(); + // Encode state and pc-offset as a BitField. // Only use 30 bits because we encode the result as a smi. class StateField : public BitField { }; @@ -786,6 +791,7 @@ class FullCodeGenerator: public AstVisitor { ZoneList stack_checks_; ZoneList type_feedback_cells_; int ic_total_count_; + bool has_self_optimization_header_; Handle handler_table_; Handle profiling_counter_; diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index 469ead9..afb8a7f 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -100,6 +100,11 @@ class JumpPatchSite BASE_EMBEDDED { }; +int FullCodeGenerator::self_optimization_header_size() { + return 13; +} + + // Generate code for a JS function. On entry to the function the receiver // and arguments have been pushed on the stack left to right, with the // return address on top of them. The actual argument count matches the @@ -122,13 +127,6 @@ void FullCodeGenerator::Generate() { SetFunctionPosition(function()); Comment cmnt(masm_, "[ function compiled by full code generator"); -#ifdef DEBUG - if (strlen(FLAG_stop_at) > 0 && - info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { - __ int3(); - } -#endif - // We can optionally optimize based on counters rather than statistical // sampling. if (info->ShouldSelfOptimize()) { @@ -136,6 +134,7 @@ void FullCodeGenerator::Generate() { PrintF("[adding self-optimization header to %s]\n", *info->function()->debug_name()->ToCString()); } + has_self_optimization_header_ = true; MaybeObject* maybe_cell = isolate()->heap()->AllocateJSGlobalPropertyCell( Smi::FromInt(Compiler::kCallsUntilPrimitiveOpt)); JSGlobalPropertyCell* cell; @@ -146,9 +145,17 @@ void FullCodeGenerator::Generate() { isolate()->builtins()->builtin(Builtins::kLazyRecompile)); STATIC_ASSERT(kSmiTag == 0); __ j(zero, compile_stub); + ASSERT(masm_->pc_offset() == self_optimization_header_size()); } } +#ifdef DEBUG + if (strlen(FLAG_stop_at) > 0 && + info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { + __ int3(); + } +#endif + // Strict mode functions and builtins need to replace the receiver // with undefined when called as functions (without an explicit // receiver object). ecx is zero for method calls and non-zero for diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc index fd0f487..c8239e3 100644 --- a/src/mips/full-codegen-mips.cc +++ b/src/mips/full-codegen-mips.cc @@ -119,6 +119,11 @@ class JumpPatchSite BASE_EMBEDDED { }; +int FullCodeGenerator::self_optimization_header_size() { + return 0; // TODO(jkummerow): determine correct value. +} + + // Generate code for a JS function. On entry to the function the receiver // and arguments have been pushed on the stack left to right. The actual // argument count matches the formal parameter count expected by the @@ -140,13 +145,6 @@ void FullCodeGenerator::Generate() { SetFunctionPosition(function()); Comment cmnt(masm_, "[ function compiled by full code generator"); -#ifdef DEBUG - if (strlen(FLAG_stop_at) > 0 && - info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { - __ stop("stop-at"); - } -#endif - // We can optionally optimize based on counters rather than statistical // sampling. if (info->ShouldSelfOptimize()) { @@ -154,6 +152,7 @@ void FullCodeGenerator::Generate() { PrintF("[adding self-optimization header to %s]\n", *info->function()->debug_name()->ToCString()); } + has_self_optimization_header_ = true; MaybeObject* maybe_cell = isolate()->heap()->AllocateJSGlobalPropertyCell( Smi::FromInt(Compiler::kCallsUntilPrimitiveOpt)); JSGlobalPropertyCell* cell; @@ -165,9 +164,17 @@ void FullCodeGenerator::Generate() { Handle compile_stub( isolate()->builtins()->builtin(Builtins::kLazyRecompile)); __ Jump(compile_stub, RelocInfo::CODE_TARGET, eq, a3, Operand(zero_reg)); + ASSERT(masm_->pc_offset() == self_optimization_header_size()); } } +#ifdef DEBUG + if (strlen(FLAG_stop_at) > 0 && + info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { + __ stop("stop-at"); + } +#endif + // Strict mode functions and builtins need to replace the receiver // with undefined when called as functions (without an explicit // receiver object). t1 is zero for method calls and non-zero for diff --git a/src/objects-inl.h b/src/objects-inl.h index f4d8c42..bc6217b 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -3089,6 +3089,21 @@ void Code::set_compiled_optimizable(bool value) { } +bool Code::has_self_optimization_header() { + ASSERT(kind() == FUNCTION); + byte flags = READ_BYTE_FIELD(this, kFullCodeFlags); + return FullCodeFlagsHasSelfOptimizationHeader::decode(flags); +} + + +void Code::set_self_optimization_header(bool value) { + ASSERT(kind() == FUNCTION); + byte flags = READ_BYTE_FIELD(this, kFullCodeFlags); + flags = FullCodeFlagsHasSelfOptimizationHeader::update(flags, value); + WRITE_BYTE_FIELD(this, kFullCodeFlags, flags); +} + + int Code::allow_osr_at_loop_nesting_level() { ASSERT(kind() == FUNCTION); return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset); diff --git a/src/objects.h b/src/objects.h index 632e7d4..be75fab 100644 --- a/src/objects.h +++ b/src/objects.h @@ -4207,6 +4207,11 @@ class Code: public HeapObject { inline bool is_compiled_optimizable(); inline void set_compiled_optimizable(bool value); + // [has_self_optimization_header]: For FUNCTION kind, tells if it has + // a self-optimization header. + inline bool has_self_optimization_header(); + inline void set_self_optimization_header(bool value); + // [allow_osr_at_loop_nesting_level]: For FUNCTION kind, tells for // how long the function has been marked for OSR and therefore which // level of loop nesting we are willing to do on-stack replacement @@ -4426,6 +4431,7 @@ class Code: public HeapObject { public BitField {}; // NOLINT class FullCodeFlagsHasDebugBreakSlotsField: public BitField {}; class FullCodeFlagsIsCompiledOptimizable: public BitField {}; + class FullCodeFlagsHasSelfOptimizationHeader: public BitField {}; static const int kBinaryOpReturnTypeOffset = kBinaryOpTypeOffset + 1; diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index 5057220..9c03053 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -100,6 +100,11 @@ class JumpPatchSite BASE_EMBEDDED { }; +int FullCodeGenerator::self_optimization_header_size() { + return 20; +} + + // Generate code for a JS function. On entry to the function the receiver // and arguments have been pushed on the stack left to right, with the // return address on top of them. The actual argument count matches the @@ -120,13 +125,6 @@ void FullCodeGenerator::Generate() { SetFunctionPosition(function()); Comment cmnt(masm_, "[ function compiled by full code generator"); -#ifdef DEBUG - if (strlen(FLAG_stop_at) > 0 && - info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { - __ int3(); - } -#endif - // We can optionally optimize based on counters rather than statistical // sampling. if (info->ShouldSelfOptimize()) { @@ -134,6 +132,7 @@ void FullCodeGenerator::Generate() { PrintF("[adding self-optimization header to %s]\n", *info->function()->debug_name()->ToCString()); } + has_self_optimization_header_ = true; MaybeObject* maybe_cell = isolate()->heap()->AllocateJSGlobalPropertyCell( Smi::FromInt(Compiler::kCallsUntilPrimitiveOpt)); JSGlobalPropertyCell* cell; @@ -145,9 +144,17 @@ void FullCodeGenerator::Generate() { Handle compile_stub( isolate()->builtins()->builtin(Builtins::kLazyRecompile)); __ j(zero, compile_stub, RelocInfo::CODE_TARGET); + ASSERT(masm_->pc_offset() == self_optimization_header_size()); } } +#ifdef DEBUG + if (strlen(FLAG_stop_at) > 0 && + info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { + __ int3(); + } +#endif + // Strict mode functions and builtins need to replace the receiver // with undefined when called as functions (without an explicit // receiver object). rcx is zero for method calls and non-zero for