diff options
author | Trevor Norris <trev.norris@gmail.com> | 2014-03-26 11:34:43 -0700 |
---|---|---|
committer | Trevor Norris <trev.norris@gmail.com> | 2014-03-26 11:34:43 -0700 |
commit | b872d9a6e6805992ba5b6f4de6fd7d34f7ea04aa (patch) | |
tree | 66cde1bcf586848156c3d68801adbcdd7a0ae4bb | |
parent | 6079b60d396f1a68f6f6cf0cbc8c70c8471cb670 (diff) | |
download | node-hgraph-backport.tar.gz |
v8: backport HGraphBuilder patchhgraph-backport
Among other things, this patch will allow Node to use IRHydra2.
-rw-r--r-- | deps/v8/src/arm/lithium-arm.cc | 1 | ||||
-rw-r--r-- | deps/v8/src/arm/lithium-arm.h | 2 | ||||
-rw-r--r-- | deps/v8/src/arm/lithium-codegen-arm.cc | 4 | ||||
-rw-r--r-- | deps/v8/src/codegen.cc | 2 | ||||
-rw-r--r-- | deps/v8/src/compiler.cc | 14 | ||||
-rw-r--r-- | deps/v8/src/compiler.h | 5 | ||||
-rw-r--r-- | deps/v8/src/deoptimizer.cc | 13 | ||||
-rw-r--r-- | deps/v8/src/flag-definitions.h | 7 | ||||
-rw-r--r-- | deps/v8/src/hydrogen-instructions.cc | 21 | ||||
-rw-r--r-- | deps/v8/src/hydrogen-instructions.h | 124 | ||||
-rw-r--r-- | deps/v8/src/hydrogen-representation-changes.cc | 5 | ||||
-rw-r--r-- | deps/v8/src/hydrogen.cc | 227 | ||||
-rw-r--r-- | deps/v8/src/hydrogen.h | 89 | ||||
-rw-r--r-- | deps/v8/src/ia32/lithium-codegen-ia32.cc | 4 | ||||
-rw-r--r-- | deps/v8/src/isolate.cc | 3 | ||||
-rw-r--r-- | deps/v8/src/isolate.h | 10 | ||||
-rw-r--r-- | deps/v8/src/lithium-codegen.cc | 8 | ||||
-rw-r--r-- | deps/v8/src/mips/lithium-codegen-mips.cc | 4 | ||||
-rw-r--r-- | deps/v8/src/objects.h | 4 | ||||
-rw-r--r-- | deps/v8/src/x64/lithium-codegen-x64.cc | 4 |
20 files changed, 418 insertions, 133 deletions
diff --git a/deps/v8/src/arm/lithium-arm.cc b/deps/v8/src/arm/lithium-arm.cc index fcd7d3c9a..26a520ac4 100644 --- a/deps/v8/src/arm/lithium-arm.cc +++ b/deps/v8/src/arm/lithium-arm.cc @@ -831,7 +831,6 @@ void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) { void LChunkBuilder::VisitInstruction(HInstruction* current) { HInstruction* old_current = current_instruction_; current_instruction_ = current; - if (current->has_position()) position_ = current->position(); LInstruction* instr = NULL; if (current->CanReplaceWithDummyUses()) { diff --git a/deps/v8/src/arm/lithium-arm.h b/deps/v8/src/arm/lithium-arm.h index 29a176628..982ac2c5a 100644 --- a/deps/v8/src/arm/lithium-arm.h +++ b/deps/v8/src/arm/lithium-arm.h @@ -2580,7 +2580,6 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase { current_block_(NULL), next_block_(NULL), allocator_(allocator), - position_(RelocInfo::kNoPosition), instruction_pending_deoptimization_environment_(NULL), pending_deoptimization_ast_id_(BailoutId::None()) { } @@ -2717,7 +2716,6 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase { HBasicBlock* current_block_; HBasicBlock* next_block_; LAllocator* allocator_; - int position_; LInstruction* instruction_pending_deoptimization_environment_; BailoutId pending_deoptimization_ast_id_; diff --git a/deps/v8/src/arm/lithium-codegen-arm.cc b/deps/v8/src/arm/lithium-codegen-arm.cc index cfcc56da2..2a41541e7 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.cc +++ b/deps/v8/src/arm/lithium-codegen-arm.cc @@ -284,7 +284,8 @@ bool LCodeGen::GenerateDeferredCode() { HValue* value = instructions_->at(code->instruction_index())->hydrogen_value(); - RecordAndWritePosition(value->position()); + RecordAndWritePosition( + chunk()->graph()->SourcePositionToScriptPosition(value->position())); Comment(";;; <@%d,#%d> " "-------------------- Deferred %s --------------------", @@ -913,6 +914,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { translations_.CreateByteArray(isolate()->factory()); data->SetTranslationByteArray(*translations); data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); + data->SetOptimizationId(Smi::FromInt(info_->optimization_id())); Handle<FixedArray> literals = factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); diff --git a/deps/v8/src/codegen.cc b/deps/v8/src/codegen.cc index 13ce2218d..f6c36682d 100644 --- a/deps/v8/src/codegen.cc +++ b/deps/v8/src/codegen.cc @@ -165,6 +165,8 @@ void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) { function->debug_name()->ToCString().get(), tracing_scope.file()); } PrintF(tracing_scope.file(), "--- Optimized code ---\n"); + PrintF(tracing_scope.file(), + "optimization_id = %d\n", info->optimization_id()); } else { PrintF(tracing_scope.file(), "--- Code ---\n"); } diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc index b9e13c166..3b0e5da5d 100644 --- a/deps/v8/src/compiler.cc +++ b/deps/v8/src/compiler.cc @@ -60,7 +60,8 @@ CompilationInfo::CompilationInfo(Handle<Script> script, script_(script), osr_ast_id_(BailoutId::None()), parameter_count_(0), - this_has_uses_(true) { + this_has_uses_(true), + optimization_id_(-1) { Initialize(script->GetIsolate(), BASE, zone); } @@ -72,7 +73,8 @@ CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info, script_(Handle<Script>(Script::cast(shared_info->script()))), osr_ast_id_(BailoutId::None()), parameter_count_(0), - this_has_uses_(true) { + this_has_uses_(true), + optimization_id_(-1) { Initialize(script_->GetIsolate(), BASE, zone); } @@ -86,7 +88,8 @@ CompilationInfo::CompilationInfo(Handle<JSFunction> closure, context_(closure->context()), osr_ast_id_(BailoutId::None()), parameter_count_(0), - this_has_uses_(true) { + this_has_uses_(true), + optimization_id_(-1) { Initialize(script_->GetIsolate(), BASE, zone); } @@ -98,7 +101,8 @@ CompilationInfo::CompilationInfo(HydrogenCodeStub* stub, IsLazy::encode(true)), osr_ast_id_(BailoutId::None()), parameter_count_(0), - this_has_uses_(true) { + this_has_uses_(true), + optimization_id_(-1) { Initialize(isolate, STUB, zone); code_stub_ = stub; } @@ -398,7 +402,7 @@ OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() { // Type-check the function. AstTyper::Run(info()); - graph_builder_ = FLAG_emit_opt_code_positions + graph_builder_ = FLAG_hydrogen_track_positions ? new(info()->zone()) HOptimizedGraphBuilderWithPositions(info()) : new(info()->zone()) HOptimizedGraphBuilder(info()); diff --git a/deps/v8/src/compiler.h b/deps/v8/src/compiler.h index 3bf4db578..d5a132df3 100644 --- a/deps/v8/src/compiler.h +++ b/deps/v8/src/compiler.h @@ -229,6 +229,7 @@ class CompilationInfo { SetMode(OPTIMIZE); osr_ast_id_ = osr_ast_id; unoptimized_code_ = unoptimized; + optimization_id_ = isolate()->NextOptimizationId(); } void DisableOptimization(); @@ -317,6 +318,8 @@ class CompilationInfo { return osr_ast_id_ == osr_ast_id && function.is_identical_to(closure_); } + int optimization_id() const { return optimization_id_; } + protected: CompilationInfo(Handle<Script> script, Zone* zone); @@ -452,6 +455,8 @@ class CompilationInfo { Handle<Foreign> object_wrapper_; + int optimization_id_; + DISALLOW_COPY_AND_ASSIGN(CompilationInfo); }; diff --git a/deps/v8/src/deoptimizer.cc b/deps/v8/src/deoptimizer.cc index 29575d8c0..f1e1d90e7 100644 --- a/deps/v8/src/deoptimizer.cc +++ b/deps/v8/src/deoptimizer.cc @@ -755,6 +755,12 @@ void Deoptimizer::DoComputeOutputFrames() { LOG(isolate(), CodeDeoptEvent(compiled_code_)); } ElapsedTimer timer; + + // Determine basic deoptimization information. The optimized frame is + // described by the input data. + DeoptimizationInputData* input_data = + DeoptimizationInputData::cast(compiled_code_->deoptimization_data()); + if (trace_scope_ != NULL) { timer.Start(); PrintF(trace_scope_->file(), @@ -763,7 +769,8 @@ void Deoptimizer::DoComputeOutputFrames() { reinterpret_cast<intptr_t>(function_)); PrintFunctionName(); PrintF(trace_scope_->file(), - " @%d, FP to SP delta: %d]\n", + " (opt #%d) @%d, FP to SP delta: %d]\n", + input_data->OptimizationId()->value(), bailout_id_, fp_to_sp_delta_); if (bailout_type_ == EAGER || bailout_type_ == SOFT) { @@ -771,10 +778,6 @@ void Deoptimizer::DoComputeOutputFrames() { } } - // Determine basic deoptimization information. The optimized frame is - // described by the input data. - DeoptimizationInputData* input_data = - DeoptimizationInputData::cast(compiled_code_->deoptimization_data()); BailoutId node_id = input_data->AstId(bailout_id_); ByteArray* translations = input_data->TranslationByteArray(); unsigned translation_index = diff --git a/deps/v8/src/flag-definitions.h b/deps/v8/src/flag-definitions.h index c0eaf16da..edab3b41c 100644 --- a/deps/v8/src/flag-definitions.h +++ b/deps/v8/src/flag-definitions.h @@ -806,6 +806,9 @@ DEFINE_bool(redirect_code_traces, false, DEFINE_string(redirect_code_traces_to, NULL, "output deopt information and disassembly into the given file") +DEFINE_bool(hydrogen_track_positions, false, + "track source code positions when building IR") + // // Disassembler only flags // @@ -838,8 +841,6 @@ DEFINE_bool(print_unopt_code, false, "print unoptimized code before " "printing optimized code based on it") DEFINE_bool(print_code_verbose, false, "print more information for code") DEFINE_bool(print_builtin_code, false, "print generated code for builtins") -DEFINE_bool(emit_opt_code_positions, false, - "annotate optimize code with source code positions") #ifdef ENABLE_DISASSEMBLER DEFINE_bool(sodium, false, "print generated code output suitable for use with " @@ -848,7 +849,7 @@ DEFINE_bool(sodium, false, "print generated code output suitable for use with " DEFINE_implication(sodium, print_code_stubs) DEFINE_implication(sodium, print_code) DEFINE_implication(sodium, print_opt_code) -DEFINE_implication(sodium, emit_opt_code_positions) +DEFINE_implication(sodium, hydrogen_track_positions) DEFINE_implication(sodium, code_comments) DEFINE_bool(print_all_code, false, "enable all flags related to printing code") diff --git a/deps/v8/src/hydrogen-instructions.cc b/deps/v8/src/hydrogen-instructions.cc index 2ca0c54a5..d778d3e2b 100644 --- a/deps/v8/src/hydrogen-instructions.cc +++ b/deps/v8/src/hydrogen-instructions.cc @@ -680,6 +680,19 @@ void HValue::ComputeInitialRange(Zone* zone) { } +void HSourcePosition::PrintTo(FILE* out) { + if (IsUnknown()) { + PrintF(out, "<?>"); + } else { + if (FLAG_hydrogen_track_positions) { + PrintF(out, "<%d:%d>", inlining_id(), position()); + } else { + PrintF(out, "<0:%d>", raw()); + } + } +} + + void HInstruction::PrintTo(StringStream* stream) { PrintMnemonicTo(stream); PrintDataTo(stream); @@ -736,8 +749,7 @@ void HInstruction::InsertBefore(HInstruction* next) { next_ = next; previous_ = prev; SetBlock(next->block()); - if (position() == RelocInfo::kNoPosition && - next->position() != RelocInfo::kNoPosition) { + if (!has_position() && next->has_position()) { set_position(next->position()); } } @@ -774,8 +786,7 @@ void HInstruction::InsertAfter(HInstruction* previous) { if (block->last() == previous) { block->set_last(this); } - if (position() == RelocInfo::kNoPosition && - previous->position() != RelocInfo::kNoPosition) { + if (!has_position() && previous->has_position()) { set_position(previous->position()); } } @@ -1647,7 +1658,7 @@ Range* HConstant::InferRange(Zone* zone) { } -int HPhi::position() const { +HSourcePosition HPhi::position() const { return block()->first()->position(); } diff --git a/deps/v8/src/hydrogen-instructions.h b/deps/v8/src/hydrogen-instructions.h index a62f3cebf..85c4bbdf7 100644 --- a/deps/v8/src/hydrogen-instructions.h +++ b/deps/v8/src/hydrogen-instructions.h @@ -537,6 +537,61 @@ class DecompositionResult V8_FINAL BASE_EMBEDDED { typedef EnumSet<GVNFlag, int64_t> GVNFlagSet; +// This class encapsulates encoding and decoding of sources positions from +// which hydrogen values originated. +// When FLAG_track_hydrogen_positions is set this object encodes the +// identifier of the inlining and absolute offset from the start of the +// inlined function. +// When the flag is not set we simply track absolute offset from the +// script start. +class HSourcePosition { + public: + HSourcePosition(const HSourcePosition& other) : value_(other.value_) { } + + static HSourcePosition Unknown() { + return HSourcePosition(RelocInfo::kNoPosition); + } + + bool IsUnknown() const { return value_ == RelocInfo::kNoPosition; } + + int position() const { return PositionField::decode(value_); } + void set_position(int position) { + if (FLAG_hydrogen_track_positions) { + value_ = static_cast<int>(PositionField::update(value_, position)); + } else { + value_ = position; + } + } + + int inlining_id() const { return InliningIdField::decode(value_); } + void set_inlining_id(int inlining_id) { + if (FLAG_hydrogen_track_positions) { + value_ = static_cast<int>(InliningIdField::update(value_, inlining_id)); + } + } + + int raw() const { return value_; } + + void PrintTo(FILE* f); + + private: + typedef BitField<int, 0, 9> InliningIdField; + + // Offset from the start of the inlined function. + typedef BitField<int, 9, 22> PositionField; + + // On HPositionInfo can use this constructor. + explicit HSourcePosition(int value) : value_(value) { } + + friend class HPositionInfo; + + // If FLAG_hydrogen_track_positions is set contains bitfields InliningIdField + // and PositionField. + // Otherwise contains absolute offset from the script start. + int value_; +}; + + class HValue : public ZoneObject { public: static const int kNoNumber = -1; @@ -630,8 +685,12 @@ class HValue : public ZoneObject { flags_(0) {} virtual ~HValue() {} - virtual int position() const { return RelocInfo::kNoPosition; } - virtual int operand_position(int index) const { return position(); } + virtual HSourcePosition position() const { + return HSourcePosition::Unknown(); + } + virtual HSourcePosition operand_position(int index) const { + return position(); + } HBasicBlock* block() const { return block_; } void SetBlock(HBasicBlock* block); @@ -1103,25 +1162,22 @@ class HValue : public ZoneObject { // In the first case it contains intruction's position as a tagged value. // In the second case it points to an array which contains instruction's // position and operands' positions. -// TODO(vegorov): what we really want to track here is a combination of -// source position and a script id because cross script inlining can easily -// result in optimized functions composed of several scripts. class HPositionInfo { public: explicit HPositionInfo(int pos) : data_(TagPosition(pos)) { } - int position() const { + HSourcePosition position() const { if (has_operand_positions()) { - return static_cast<int>(operand_positions()[kInstructionPosIndex]); + return operand_positions()[kInstructionPosIndex]; } - return static_cast<int>(UntagPosition(data_)); + return HSourcePosition(static_cast<int>(UntagPosition(data_))); } - void set_position(int pos) { + void set_position(HSourcePosition pos) { if (has_operand_positions()) { operand_positions()[kInstructionPosIndex] = pos; } else { - data_ = TagPosition(pos); + data_ = TagPosition(pos.raw()); } } @@ -1131,27 +1187,27 @@ class HPositionInfo { } const int length = kFirstOperandPosIndex + operand_count; - intptr_t* positions = - zone->NewArray<intptr_t>(length); + HSourcePosition* positions = + zone->NewArray<HSourcePosition>(length); for (int i = 0; i < length; i++) { - positions[i] = RelocInfo::kNoPosition; + positions[i] = HSourcePosition::Unknown(); } - const int pos = position(); + const HSourcePosition pos = position(); data_ = reinterpret_cast<intptr_t>(positions); set_position(pos); ASSERT(has_operand_positions()); } - int operand_position(int idx) const { + HSourcePosition operand_position(int idx) const { if (!has_operand_positions()) { return position(); } - return static_cast<int>(*operand_position_slot(idx)); + return *operand_position_slot(idx); } - void set_operand_position(int idx, int pos) { + void set_operand_position(int idx, HSourcePosition pos) { *operand_position_slot(idx) = pos; } @@ -1159,7 +1215,7 @@ class HPositionInfo { static const intptr_t kInstructionPosIndex = 0; static const intptr_t kFirstOperandPosIndex = 1; - intptr_t* operand_position_slot(int idx) const { + HSourcePosition* operand_position_slot(int idx) const { ASSERT(has_operand_positions()); return &(operand_positions()[kFirstOperandPosIndex + idx]); } @@ -1168,9 +1224,9 @@ class HPositionInfo { return !IsTaggedPosition(data_); } - intptr_t* operand_positions() const { + HSourcePosition* operand_positions() const { ASSERT(has_operand_positions()); - return reinterpret_cast<intptr_t*>(data_); + return reinterpret_cast<HSourcePosition*>(data_); } static const intptr_t kPositionTag = 1; @@ -1218,23 +1274,23 @@ class HInstruction : public HValue { } // The position is a write-once variable. - virtual int position() const V8_OVERRIDE { - return position_.position(); + virtual HSourcePosition position() const V8_OVERRIDE { + return HSourcePosition(position_.position()); } bool has_position() const { - return position_.position() != RelocInfo::kNoPosition; + return !position().IsUnknown(); } - void set_position(int position) { + void set_position(HSourcePosition position) { ASSERT(!has_position()); - ASSERT(position != RelocInfo::kNoPosition); + ASSERT(!position.IsUnknown()); position_.set_position(position); } - virtual int operand_position(int index) const V8_OVERRIDE { - const int pos = position_.operand_position(index); - return (pos != RelocInfo::kNoPosition) ? pos : position(); + virtual HSourcePosition operand_position(int index) const V8_OVERRIDE { + const HSourcePosition pos = position_.operand_position(index); + return pos.IsUnknown() ? position() : pos; } - void set_operand_position(Zone* zone, int index, int pos) { + void set_operand_position(Zone* zone, int index, HSourcePosition pos) { ASSERT(0 <= index && index < OperandCount()); position_.ensure_storage_for_operand_positions(zone, OperandCount()); position_.set_operand_position(index, pos); @@ -3149,7 +3205,7 @@ class HPhi V8_FINAL : public HValue { bool IsReceiver() const { return merged_index_ == 0; } bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; } - virtual int position() const V8_OVERRIDE; + virtual HSourcePosition position() const V8_OVERRIDE; int merged_index() const { return merged_index_; } @@ -3654,7 +3710,9 @@ class HBinaryOperation : public HTemplateInstruction<3> { return representation(); } - void SetOperandPositions(Zone* zone, int left_pos, int right_pos) { + void SetOperandPositions(Zone* zone, + HSourcePosition left_pos, + HSourcePosition right_pos) { set_operand_position(zone, 1, left_pos); set_operand_position(zone, 2, right_pos); } @@ -4109,7 +4167,9 @@ class HCompareNumericAndBranch : public HTemplateControlInstruction<2, 2> { } virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; - void SetOperandPositions(Zone* zone, int left_pos, int right_pos) { + void SetOperandPositions(Zone* zone, + HSourcePosition left_pos, + HSourcePosition right_pos) { set_operand_position(zone, 0, left_pos); set_operand_position(zone, 1, right_pos); } diff --git a/deps/v8/src/hydrogen-representation-changes.cc b/deps/v8/src/hydrogen-representation-changes.cc index 07fc8be38..7d0720c60 100644 --- a/deps/v8/src/hydrogen-representation-changes.cc +++ b/deps/v8/src/hydrogen-representation-changes.cc @@ -61,10 +61,11 @@ void HRepresentationChangesPhase::InsertRepresentationChangeForUse( if (new_value == NULL) { new_value = new(graph()->zone()) HChange( value, to, is_truncating_to_smi, is_truncating_to_int); - if (use_value->operand_position(use_index) != RelocInfo::kNoPosition) { + if (!use_value->operand_position(use_index).IsUnknown()) { new_value->set_position(use_value->operand_position(use_index)); } else { - ASSERT(!FLAG_emit_opt_code_positions || !graph()->info()->IsOptimizing()); + ASSERT(!FLAG_hydrogen_track_positions || + !graph()->info()->IsOptimizing()); } } diff --git a/deps/v8/src/hydrogen.cc b/deps/v8/src/hydrogen.cc index 7ee8180cc..bf60e6093 100644 --- a/deps/v8/src/hydrogen.cc +++ b/deps/v8/src/hydrogen.cc @@ -141,12 +141,13 @@ void HBasicBlock::RemovePhi(HPhi* phi) { } -void HBasicBlock::AddInstruction(HInstruction* instr, int position) { +void HBasicBlock::AddInstruction(HInstruction* instr, + HSourcePosition position) { ASSERT(!IsStartBlock() || !IsFinished()); ASSERT(!instr->IsLinked()); ASSERT(!IsFinished()); - if (position != RelocInfo::kNoPosition) { + if (!position.IsUnknown()) { instr->set_position(position); } if (first_ == NULL) { @@ -154,10 +155,10 @@ void HBasicBlock::AddInstruction(HInstruction* instr, int position) { ASSERT(!last_environment()->ast_id().IsNone()); HBlockEntry* entry = new(zone()) HBlockEntry(); entry->InitializeAsFirst(this); - if (position != RelocInfo::kNoPosition) { + if (!position.IsUnknown()) { entry->set_position(position); } else { - ASSERT(!FLAG_emit_opt_code_positions || + ASSERT(!FLAG_hydrogen_track_positions || !graph()->info()->IsOptimizing()); } first_ = last_ = entry; @@ -210,7 +211,7 @@ HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id, } -void HBasicBlock::Finish(HControlInstruction* end, int position) { +void HBasicBlock::Finish(HControlInstruction* end, HSourcePosition position) { ASSERT(!IsFinished()); AddInstruction(end, position); end_ = end; @@ -221,7 +222,7 @@ void HBasicBlock::Finish(HControlInstruction* end, int position) { void HBasicBlock::Goto(HBasicBlock* block, - int position, + HSourcePosition position, FunctionState* state, bool add_simulate) { bool drop_extra = state != NULL && @@ -244,7 +245,7 @@ void HBasicBlock::Goto(HBasicBlock* block, void HBasicBlock::AddLeaveInlined(HValue* return_value, FunctionState* state, - int position) { + HSourcePosition position) { HBasicBlock* target = state->function_return(); bool drop_extra = state->inlining_kind() == NORMAL_RETURN; @@ -1032,9 +1033,9 @@ void HGraphBuilder::IfBuilder::End() { current = merge_at_join_blocks_; while (current != NULL) { if (current->deopt_ && current->block_ != NULL) { - builder_->PadEnvironmentForContinuation(current->block_, - merge_block); - builder_->GotoNoSimulate(current->block_, merge_block); + current->block_->FinishExit( + HAbnormalExit::New(builder_->zone(), NULL), + HSourcePosition::Unknown()); } current = current->next_; } @@ -1167,9 +1168,10 @@ HGraph* HGraphBuilder::CreateGraph() { HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { ASSERT(current_block() != NULL); - ASSERT(!FLAG_emit_opt_code_positions || - position_ != RelocInfo::kNoPosition || !info_->IsOptimizing()); - current_block()->AddInstruction(instr, position_); + ASSERT(!FLAG_hydrogen_track_positions || + !position_.IsUnknown() || + !info_->IsOptimizing()); + current_block()->AddInstruction(instr, source_position()); if (graph()->IsInsideNoSideEffectsScope()) { instr->SetFlag(HValue::kHasNoObservableSideEffects); } @@ -1178,9 +1180,10 @@ HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) { - ASSERT(!FLAG_emit_opt_code_positions || !info_->IsOptimizing() || - position_ != RelocInfo::kNoPosition); - current_block()->Finish(last, position_); + ASSERT(!FLAG_hydrogen_track_positions || + !info_->IsOptimizing() || + !position_.IsUnknown()); + current_block()->Finish(last, source_position()); if (last->IsReturn() || last->IsAbnormalExit()) { set_current_block(NULL); } @@ -1188,9 +1191,9 @@ void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) { void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) { - ASSERT(!FLAG_emit_opt_code_positions || !info_->IsOptimizing() || - position_ != RelocInfo::kNoPosition); - current_block()->FinishExit(instruction, position_); + ASSERT(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() || + !position_.IsUnknown()); + current_block()->FinishExit(instruction, source_position()); if (instruction->IsReturn() || instruction->IsAbnormalExit()) { set_current_block(NULL); } @@ -1214,7 +1217,7 @@ void HGraphBuilder::AddSimulate(BailoutId id, RemovableSimulate removable) { ASSERT(current_block() != NULL); ASSERT(!graph()->IsInsideNoSideEffectsScope()); - current_block()->AddNewSimulate(id, position_, removable); + current_block()->AddNewSimulate(id, source_position(), removable); } @@ -2993,7 +2996,7 @@ HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin) { HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) : HGraphBuilder(info), function_state_(NULL), - initial_function_state_(this, info, NORMAL_RETURN), + initial_function_state_(this, info, NORMAL_RETURN, 0), ast_context_(NULL), break_scope_(NULL), inlined_count_(0), @@ -3005,7 +3008,7 @@ HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) // to know it's the initial state. function_state_= &initial_function_state_; InitializeAstVisitor(info->zone()); - if (FLAG_emit_opt_code_positions) { + if (FLAG_hydrogen_track_positions) { SetSourcePosition(info->shared_info()->start_position()); } } @@ -3074,7 +3077,8 @@ HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry( } -void HBasicBlock::FinishExit(HControlInstruction* instruction, int position) { +void HBasicBlock::FinishExit(HControlInstruction* instruction, + HSourcePosition position) { Finish(instruction, position); ClearEnvironment(); } @@ -3097,7 +3101,9 @@ HGraph::HGraph(CompilationInfo* info) type_change_checksum_(0), maximum_environment_size_(0), no_side_effects_scope_count_(0), - disallow_adding_new_values_(false) { + disallow_adding_new_values_(false), + next_inline_id_(0), + inlined_functions_(5, info->zone()) { if (info->IsStub()) { HydrogenCodeStub* stub = info->code_stub(); CodeStubInterfaceDescriptor* descriptor = @@ -3105,6 +3111,7 @@ HGraph::HGraph(CompilationInfo* info) start_environment_ = new(zone_) HEnvironment(zone_, descriptor->environment_length()); } else { + TraceInlinedFunction(info->shared_info(), HSourcePosition::Unknown()); start_environment_ = new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); } @@ -3132,6 +3139,81 @@ void HGraph::FinalizeUniqueness() { } +int HGraph::TraceInlinedFunction( + Handle<SharedFunctionInfo> shared, + HSourcePosition position) { + if (!FLAG_hydrogen_track_positions) { + return 0; + } + + int id = 0; + for (; id < inlined_functions_.length(); id++) { + if (inlined_functions_[id].shared().is_identical_to(shared)) { + break; + } + } + + if (id == inlined_functions_.length()) { + inlined_functions_.Add(InlinedFunctionInfo(shared), zone()); + + if (!shared->script()->IsUndefined()) { + Handle<Script> script(Script::cast(shared->script())); + if (!script->source()->IsUndefined()) { + CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); + PrintF(tracing_scope.file(), + "--- FUNCTION SOURCE (%s) id{%d,%d} ---\n", + shared->DebugName()->ToCString().get(), + info()->optimization_id(), + id); + + { + ConsStringIteratorOp op; + StringCharacterStream stream(String::cast(script->source()), + &op, + shared->start_position()); + // fun->end_position() points to the last character in the stream. We + // need to compensate by adding one to calculate the length. + int source_len = + shared->end_position() - shared->start_position() + 1; + for (int i = 0; i < source_len; i++) { + if (stream.HasMore()) { + PrintF(tracing_scope.file(), "%c", stream.GetNext()); + } + } + } + + PrintF(tracing_scope.file(), "\n--- END ---\n"); + } + } + } + + int inline_id = next_inline_id_++; + + if (inline_id != 0) { + CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); + PrintF(tracing_scope.file(), "INLINE (%s) id{%d,%d} AS %d AT ", + shared->DebugName()->ToCString().get(), + info()->optimization_id(), + id, + inline_id); + position.PrintTo(tracing_scope.file()); + PrintF(tracing_scope.file(), "\n"); + } + + return inline_id; +} + + +int HGraph::SourcePositionToScriptPosition(HSourcePosition pos) { + if (!FLAG_hydrogen_track_positions || pos.IsUnknown()) { + return pos.raw(); + } + + return inlined_functions_[pos.inlining_id()].start_position() + + pos.position(); +} + + // Block ordering was implemented with two mutually recursive methods, // HGraph::Postorder and HGraph::PostorderLoopBlocks. // The recursion could lead to stack overflow so the algorithm has been @@ -3510,7 +3592,8 @@ void HGraph::CollectPhis() { // a (possibly inlined) function. FunctionState::FunctionState(HOptimizedGraphBuilder* owner, CompilationInfo* info, - InliningKind inlining_kind) + InliningKind inlining_kind, + int inlining_id) : owner_(owner), compilation_info_(info), call_context_(NULL), @@ -3520,6 +3603,8 @@ FunctionState::FunctionState(HOptimizedGraphBuilder* owner, entry_(NULL), arguments_object_(NULL), arguments_elements_(NULL), + inlining_id_(inlining_id), + outer_source_position_(HSourcePosition::Unknown()), outer_(owner->function_state()) { if (outer_ != NULL) { // State for an inline function. @@ -3543,12 +3628,27 @@ FunctionState::FunctionState(HOptimizedGraphBuilder* owner, // Push on the state stack. owner->set_function_state(this); + + if (FLAG_hydrogen_track_positions) { + outer_source_position_ = owner->source_position(); + owner->EnterInlinedSource( + info->shared_info()->start_position(), + inlining_id); + owner->SetSourcePosition(info->shared_info()->start_position()); + } } FunctionState::~FunctionState() { delete test_context_; owner_->set_function_state(outer_); + + if (FLAG_hydrogen_track_positions) { + owner_->set_source_position(outer_source_position_); + owner_->EnterInlinedSource( + outer_->compilation_info()->shared_info()->start_position(), + outer_->inlining_id()); + } } @@ -4361,7 +4461,9 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { Type* combined_type = clause->compare_type(); HControlInstruction* compare = BuildCompareInstruction( Token::EQ_STRICT, tag_value, label_value, tag_type, label_type, - combined_type, stmt->tag()->position(), clause->label()->position(), + combined_type, + ScriptPositionToSourcePosition(stmt->tag()->position()), + ScriptPositionToSourcePosition(clause->label()->position()), clause->id()); HBasicBlock* next_test_block = graph()->CreateBasicBlock(); @@ -6128,7 +6230,7 @@ void HOptimizedGraphBuilder::VisitThrow(Throw* expr) { CHECK_ALIVE(VisitForValue(expr->exception())); HValue* value = environment()->Pop(); - if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); + if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); Add<HPushArgument>(value); Add<HCallRuntime>(isolate()->factory()->empty_string(), Runtime::FunctionForId(Runtime::kThrow), 1); @@ -7105,7 +7207,8 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target, HValue* implicit_return_value, BailoutId ast_id, BailoutId return_id, - InliningKind inlining_kind) { + InliningKind inlining_kind, + HSourcePosition position) { int nodes_added = InliningAstSize(target); if (nodes_added == kNotInlinable) return false; @@ -7237,11 +7340,13 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target, ASSERT(target_shared->has_deoptimization_support()); AstTyper::Run(&target_info); + int function_id = graph()->TraceInlinedFunction(target_shared, position); + // Save the pending call context. Set up new one for the inlined function. // The function state is new-allocated because we need to delete it // in two different places. FunctionState* target_state = new FunctionState( - this, &target_info, inlining_kind); + this, &target_info, inlining_kind, function_id); HConstant* undefined = graph()->GetConstantUndefined(); @@ -7388,7 +7493,8 @@ bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) { NULL, expr->id(), expr->ReturnId(), - NORMAL_RETURN); + NORMAL_RETURN, + ScriptPositionToSourcePosition(expr->position())); } @@ -7399,7 +7505,8 @@ bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr, implicit_return_value, expr->id(), expr->ReturnId(), - CONSTRUCT_CALL_RETURN); + CONSTRUCT_CALL_RETURN, + ScriptPositionToSourcePosition(expr->position())); } @@ -7413,7 +7520,8 @@ bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, NULL, ast_id, return_id, - GETTER_CALL_RETURN); + GETTER_CALL_RETURN, + source_position()); } @@ -7427,7 +7535,8 @@ bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, 1, implicit_return_value, id, assignment_id, - SETTER_CALL_RETURN); + SETTER_CALL_RETURN, + source_position()); } @@ -7439,7 +7548,8 @@ bool HOptimizedGraphBuilder::TryInlineApply(Handle<JSFunction> function, NULL, expr->id(), expr->ReturnId(), - NORMAL_RETURN); + NORMAL_RETURN, + ScriptPositionToSourcePosition(expr->position())); } @@ -7987,6 +8097,8 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) { CHECK_ALIVE(PushLoad(prop, receiver, key)); HValue* function = Pop(); + if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); + // Push the function under the receiver. environment()->SetExpressionStackAt(0, function); @@ -8259,7 +8371,7 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { ASSERT(!HasStackOverflow()); ASSERT(current_block() != NULL); ASSERT(current_block()->HasPredecessor()); - if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); + if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); int argument_count = expr->arguments()->length() + 1; // Plus constructor. Factory* factory = isolate()->factory(); @@ -8802,7 +8914,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { ASSERT(!HasStackOverflow()); ASSERT(current_block() != NULL); ASSERT(current_block()->HasPredecessor()); - if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); + if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); Expression* target = expr->expression(); VariableProxy* proxy = target->AsVariableProxy(); Property* prop = target->AsProperty(); @@ -9469,9 +9581,11 @@ void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { BuildBinaryOperation(expr, left, right, ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE : PUSH_BEFORE_SIMULATE); - if (FLAG_emit_opt_code_positions && result->IsBinaryOperation()) { + if (FLAG_hydrogen_track_positions && result->IsBinaryOperation()) { HBinaryOperation::cast(result)->SetOperandPositions( - zone(), expr->left()->position(), expr->right()->position()); + zone(), + ScriptPositionToSourcePosition(expr->left()->position()), + ScriptPositionToSourcePosition(expr->right()->position())); } return ast_context()->ReturnValue(result); } @@ -9505,7 +9619,7 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { ASSERT(current_block() != NULL); ASSERT(current_block()->HasPredecessor()); - if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); + if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); // Check for a few fast cases. The AST visiting behavior must be in sync // with the full codegen: We don't push both left and right values onto @@ -9540,7 +9654,7 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { CHECK_ALIVE(VisitForValue(expr->left())); CHECK_ALIVE(VisitForValue(expr->right())); - if (FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); + if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); HValue* right = Pop(); HValue* left = Pop(); @@ -9602,7 +9716,9 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { HControlInstruction* compare = BuildCompareInstruction( op, left, right, left_type, right_type, combined_type, - expr->left()->position(), expr->right()->position(), expr->id()); + ScriptPositionToSourcePosition(expr->left()->position()), + ScriptPositionToSourcePosition(expr->right()->position()), + expr->id()); if (compare == NULL) return; // Bailed out. return ast_context()->ReturnControl(compare, expr->id()); } @@ -9615,8 +9731,8 @@ HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction( Type* left_type, Type* right_type, Type* combined_type, - int left_position, - int right_position, + HSourcePosition left_position, + HSourcePosition right_position, BailoutId bailout_id) { // Cases handled below depend on collected type feedback. They should // soft deoptimize when there is no type feedback. @@ -9641,7 +9757,7 @@ HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction( AddCheckMap(operand_to_check, map); HCompareObjectEqAndBranch* result = New<HCompareObjectEqAndBranch>(left, right); - if (FLAG_emit_opt_code_positions) { + if (FLAG_hydrogen_track_positions) { result->set_operand_position(zone(), 0, left_position); result->set_operand_position(zone(), 1, right_position); } @@ -9692,7 +9808,7 @@ HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction( HCompareNumericAndBranch* result = New<HCompareNumericAndBranch>(left, right, op); result->set_observed_input_representation(left_rep, right_rep); - if (FLAG_emit_opt_code_positions) { + if (FLAG_hydrogen_track_positions) { result->SetOperandPositions(zone(), left_position, right_position); } return result; @@ -9708,7 +9824,7 @@ void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, ASSERT(current_block() != NULL); ASSERT(current_block()->HasPredecessor()); ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); - if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); + if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); CHECK_ALIVE(VisitForValue(sub_expr)); HValue* value = Pop(); if (expr->op() == Token::EQ_STRICT) { @@ -10936,7 +11052,10 @@ void HTracer::TraceCompilation(CompilationInfo* info) { if (info->IsOptimizing()) { Handle<String> name = info->function()->debug_name(); PrintStringProperty("name", name->ToCString().get()); - PrintStringProperty("method", name->ToCString().get()); + PrintIndent(); + trace_.Add("method \"%s:%d\"\n", + name->ToCString().get(), + info->optimization_id()); } else { CodeStub::Major major_key = info->code_stub()->MajorKey(); PrintStringProperty("name", CodeStub::MajorName(major_key, false)); @@ -11050,14 +11169,22 @@ void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) { Tag HIR_tag(this, "HIR"); for (HInstructionIterator it(current); !it.Done(); it.Advance()) { HInstruction* instruction = it.Current(); - int bci = FLAG_emit_opt_code_positions && instruction->has_position() ? - instruction->position() : 0; int uses = instruction->UseCount(); PrintIndent(); - trace_.Add("%d %d ", bci, uses); + trace_.Add("0 %d ", uses); instruction->PrintNameTo(&trace_); trace_.Add(" "); instruction->PrintTo(&trace_); + if (FLAG_hydrogen_track_positions && + instruction->has_position() && + instruction->position().raw() != 0) { + const HSourcePosition pos = instruction->position(); + trace_.Add(" pos:"); + if (pos.inlining_id() != 0) { + trace_.Add("%d_", pos.inlining_id()); + } + trace_.Add("%d", pos.position()); + } trace_.Add(" <|@\n"); } } diff --git a/deps/v8/src/hydrogen.h b/deps/v8/src/hydrogen.h index b8344ef9c..62cef4a07 100644 --- a/deps/v8/src/hydrogen.h +++ b/deps/v8/src/hydrogen.h @@ -110,7 +110,7 @@ class HBasicBlock V8_FINAL : public ZoneObject { bool IsFinished() const { return end_ != NULL; } void AddPhi(HPhi* phi); void RemovePhi(HPhi* phi); - void AddInstruction(HInstruction* instr, int position); + void AddInstruction(HInstruction* instr, HSourcePosition position); bool Dominates(HBasicBlock* other) const; bool EqualToOrDominates(HBasicBlock* other) const; int LoopNestingDepth() const; @@ -137,7 +137,7 @@ class HBasicBlock V8_FINAL : public ZoneObject { int PredecessorIndexOf(HBasicBlock* predecessor) const; HPhi* AddNewPhi(int merged_index); HSimulate* AddNewSimulate(BailoutId ast_id, - int position, + HSourcePosition position, RemovableSimulate removable = FIXED_SIMULATE) { HSimulate* instr = CreateSimulate(ast_id, removable); AddInstruction(instr, position); @@ -184,13 +184,13 @@ class HBasicBlock V8_FINAL : public ZoneObject { friend class HGraphBuilder; HSimulate* CreateSimulate(BailoutId ast_id, RemovableSimulate removable); - void Finish(HControlInstruction* last, int position); - void FinishExit(HControlInstruction* instruction, int position); + void Finish(HControlInstruction* last, HSourcePosition position); + void FinishExit(HControlInstruction* instruction, HSourcePosition position); void Goto(HBasicBlock* block, - int position, + HSourcePosition position, FunctionState* state = NULL, bool add_simulate = true); - void GotoNoSimulate(HBasicBlock* block, int position) { + void GotoNoSimulate(HBasicBlock* block, HSourcePosition position) { Goto(block, position, NULL, false); } @@ -198,7 +198,7 @@ class HBasicBlock V8_FINAL : public ZoneObject { // instruction and updating the bailout environment. void AddLeaveInlined(HValue* return_value, FunctionState* state, - int position); + HSourcePosition position); private: void RegisterPredecessor(HBasicBlock* pred); @@ -469,6 +469,16 @@ class HGraph V8_FINAL : public ZoneObject { void DecrementInNoSideEffectsScope() { no_side_effects_scope_count_--; } bool IsInsideNoSideEffectsScope() { return no_side_effects_scope_count_ > 0; } + // If we are tracking source positions then this function assigns a unique + // identifier to each inlining and dumps function source if it was inlined + // for the first time during the current optimization. + int TraceInlinedFunction(Handle<SharedFunctionInfo> shared, + HSourcePosition position); + + // Converts given HSourcePosition to the absolute offset from the start of + // the corresponding script. + int SourcePositionToScriptPosition(HSourcePosition position); + private: HConstant* ReinsertConstantIfNecessary(HConstant* constant); HConstant* GetConstant(SetOncePointer<HConstant>* pointer, @@ -514,6 +524,23 @@ class HGraph V8_FINAL : public ZoneObject { int no_side_effects_scope_count_; bool disallow_adding_new_values_; + class InlinedFunctionInfo { + public: + explicit InlinedFunctionInfo(Handle<SharedFunctionInfo> shared) + : shared_(shared), start_position_(shared->start_position()) { + } + + Handle<SharedFunctionInfo> shared() const { return shared_; } + int start_position() const { return start_position_; } + + private: + Handle<SharedFunctionInfo> shared_; + int start_position_; + }; + + int next_inline_id_; + ZoneList<InlinedFunctionInfo> inlined_functions_; + DISALLOW_COPY_AND_ASSIGN(HGraph); }; @@ -880,7 +907,8 @@ class FunctionState V8_FINAL { public: FunctionState(HOptimizedGraphBuilder* owner, CompilationInfo* info, - InliningKind inlining_kind); + InliningKind inlining_kind, + int inlining_id); ~FunctionState(); CompilationInfo* compilation_info() { return compilation_info_; } @@ -910,6 +938,8 @@ class FunctionState V8_FINAL { bool arguments_pushed() { return arguments_elements() != NULL; } + int inlining_id() const { return inlining_id_; } + private: HOptimizedGraphBuilder* owner_; @@ -939,6 +969,9 @@ class FunctionState V8_FINAL { HArgumentsObject* arguments_object_; HArgumentsElements* arguments_elements_; + int inlining_id_; + HSourcePosition outer_source_position_; + FunctionState* outer_; }; @@ -1022,7 +1055,8 @@ class HGraphBuilder { : info_(info), graph_(NULL), current_block_(NULL), - position_(RelocInfo::kNoPosition) {} + position_(HSourcePosition::Unknown()), + start_position_(0) {} virtual ~HGraphBuilder() {} HBasicBlock* current_block() const { return current_block_; } @@ -1052,7 +1086,7 @@ class HGraphBuilder { HBasicBlock* target, FunctionState* state = NULL, bool add_simulate = true) { - from->Goto(target, position_, state, add_simulate); + from->Goto(target, source_position(), state, add_simulate); } void Goto(HBasicBlock* target, FunctionState* state = NULL, @@ -1068,7 +1102,7 @@ class HGraphBuilder { void AddLeaveInlined(HBasicBlock* block, HValue* return_value, FunctionState* state) { - block->AddLeaveInlined(return_value, state, position_); + block->AddLeaveInlined(return_value, state, source_position()); } void AddLeaveInlined(HValue* return_value, FunctionState* state) { return AddLeaveInlined(current_block(), return_value, state); @@ -1274,8 +1308,6 @@ class HGraphBuilder { void AddSimulate(BailoutId id, RemovableSimulate removable = FIXED_SIMULATE); - int position() const { return position_; } - protected: virtual bool BuildGraph() = 0; @@ -1777,6 +1809,27 @@ class HGraphBuilder { protected: void SetSourcePosition(int position) { ASSERT(position != RelocInfo::kNoPosition); + position_.set_position(position - start_position_); + } + + void EnterInlinedSource(int start_position, int id) { + if (FLAG_hydrogen_track_positions) { + start_position_ = start_position; + position_.set_inlining_id(id); + } + } + + // Convert the given absolute offset from the start of the script to + // the HSourcePosition assuming that this position corresponds to the + // same function as current position_. + HSourcePosition ScriptPositionToSourcePosition(int position) { + HSourcePosition pos = position_; + pos.set_position(position - start_position_); + return pos; + } + + HSourcePosition source_position() { return position_; } + void set_source_position(HSourcePosition position) { position_ = position; } @@ -1807,7 +1860,8 @@ class HGraphBuilder { CompilationInfo* info_; HGraph* graph_; HBasicBlock* current_block_; - int position_; + HSourcePosition position_; + int start_position_; }; @@ -2213,7 +2267,8 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { HValue* implicit_return_value, BailoutId ast_id, BailoutId return_id, - InliningKind inlining_kind); + InliningKind inlining_kind, + HSourcePosition position); bool TryInlineCall(Call* expr); bool TryInlineConstruct(CallNew* expr, HValue* implicit_return_value); @@ -2422,8 +2477,8 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { Type* left_type, Type* right_type, Type* combined_type, - int left_position, - int right_position, + HSourcePosition left_position, + HSourcePosition right_position, BailoutId bailout_id); HInstruction* BuildStringCharCodeAt(HValue* string, diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.cc b/deps/v8/src/ia32/lithium-codegen-ia32.cc index 5a12ca969..524320dd8 100644 --- a/deps/v8/src/ia32/lithium-codegen-ia32.cc +++ b/deps/v8/src/ia32/lithium-codegen-ia32.cc @@ -479,7 +479,8 @@ bool LCodeGen::GenerateDeferredCode() { HValue* value = instructions_->at(code->instruction_index())->hydrogen_value(); - RecordAndWritePosition(value->position()); + RecordAndWritePosition( + chunk()->graph()->SourcePositionToScriptPosition(value->position())); Comment(";;; <@%d,#%d> " "-------------------- Deferred %s --------------------", @@ -1181,6 +1182,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { translations_.CreateByteArray(isolate()->factory()); data->SetTranslationByteArray(*translations); data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); + data->SetOptimizationId(Smi::FromInt(info_->optimization_id())); Handle<FixedArray> literals = factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); diff --git a/deps/v8/src/isolate.cc b/deps/v8/src/isolate.cc index 8a2f4219c..db7295855 100644 --- a/deps/v8/src/isolate.cc +++ b/deps/v8/src/isolate.cc @@ -1566,7 +1566,8 @@ Isolate::Isolate() sweeper_thread_(NULL), num_sweeper_threads_(0), max_available_threads_(0), - stress_deopt_count_(0) { + stress_deopt_count_(0), + next_optimization_id_(0) { id_ = NoBarrier_AtomicIncrement(&isolate_counter_, 1); TRACE_ISOLATE(constructor); diff --git a/deps/v8/src/isolate.h b/deps/v8/src/isolate.h index d93a86229..6c2626d8b 100644 --- a/deps/v8/src/isolate.h +++ b/deps/v8/src/isolate.h @@ -1153,6 +1153,14 @@ class Isolate { // Given an address occupied by a live code object, return that object. Object* FindCodeObject(Address a); + int NextOptimizationId() { + int id = next_optimization_id_++; + if (!Smi::IsValid(next_optimization_id_)) { + next_optimization_id_ = 0; + } + return id; + } + private: Isolate(); @@ -1384,6 +1392,8 @@ class Isolate { // Counts deopt points if deopt_every_n_times is enabled. unsigned int stress_deopt_count_; + int next_optimization_id_; + friend class ExecutionAccess; friend class HandleScopeImplementer; friend class IsolateInitializer; diff --git a/deps/v8/src/lithium-codegen.cc b/deps/v8/src/lithium-codegen.cc index 2d71d13c6..a057c2fd8 100644 --- a/deps/v8/src/lithium-codegen.cc +++ b/deps/v8/src/lithium-codegen.cc @@ -104,11 +104,9 @@ bool LCodeGenBase::GenerateBody() { GenerateBodyInstructionPre(instr); HValue* value = instr->hydrogen_value(); - if (value->position() != RelocInfo::kNoPosition) { - ASSERT(!graph()->info()->IsOptimizing() || - !FLAG_emit_opt_code_positions || - value->position() != RelocInfo::kNoPosition); - RecordAndWritePosition(value->position()); + if (!value->position().IsUnknown()) { + RecordAndWritePosition( + chunk()->graph()->SourcePositionToScriptPosition(value->position())); } instr->CompileToNative(codegen); diff --git a/deps/v8/src/mips/lithium-codegen-mips.cc b/deps/v8/src/mips/lithium-codegen-mips.cc index f033f6d34..ec3bb2f18 100644 --- a/deps/v8/src/mips/lithium-codegen-mips.cc +++ b/deps/v8/src/mips/lithium-codegen-mips.cc @@ -274,7 +274,8 @@ bool LCodeGen::GenerateDeferredCode() { HValue* value = instructions_->at(code->instruction_index())->hydrogen_value(); - RecordAndWritePosition(value->position()); + RecordAndWritePosition( + chunk()->graph()->SourcePositionToScriptPosition(value->position())); Comment(";;; <@%d,#%d> " "-------------------- Deferred %s --------------------", @@ -866,6 +867,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { translations_.CreateByteArray(isolate()->factory()); data->SetTranslationByteArray(*translations); data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); + data->SetOptimizationId(Smi::FromInt(info_->optimization_id())); Handle<FixedArray> literals = factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h index 1b4075250..bcad4d6d6 100644 --- a/deps/v8/src/objects.h +++ b/deps/v8/src/objects.h @@ -4951,7 +4951,8 @@ class DeoptimizationInputData: public FixedArray { static const int kLiteralArrayIndex = 2; static const int kOsrAstIdIndex = 3; static const int kOsrPcOffsetIndex = 4; - static const int kFirstDeoptEntryIndex = 5; + static const int kOptimizationIdIndex = 5; + static const int kFirstDeoptEntryIndex = 6; // Offsets of deopt entry elements relative to the start of the entry. static const int kAstIdRawOffset = 0; @@ -4974,6 +4975,7 @@ class DeoptimizationInputData: public FixedArray { DEFINE_ELEMENT_ACCESSORS(LiteralArray, FixedArray) DEFINE_ELEMENT_ACCESSORS(OsrAstId, Smi) DEFINE_ELEMENT_ACCESSORS(OsrPcOffset, Smi) + DEFINE_ELEMENT_ACCESSORS(OptimizationId, Smi) #undef DEFINE_ELEMENT_ACCESSORS diff --git a/deps/v8/src/x64/lithium-codegen-x64.cc b/deps/v8/src/x64/lithium-codegen-x64.cc index 2cb09325f..0ba2d6f33 100644 --- a/deps/v8/src/x64/lithium-codegen-x64.cc +++ b/deps/v8/src/x64/lithium-codegen-x64.cc @@ -335,7 +335,8 @@ bool LCodeGen::GenerateDeferredCode() { HValue* value = instructions_->at(code->instruction_index())->hydrogen_value(); - RecordAndWritePosition(value->position()); + RecordAndWritePosition( + chunk()->graph()->SourcePositionToScriptPosition(value->position())); Comment(";;; <@%d,#%d> " "-------------------- Deferred %s --------------------", @@ -798,6 +799,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { translations_.CreateByteArray(isolate()->factory()); data->SetTranslationByteArray(*translations); data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); + data->SetOptimizationId(Smi::FromInt(info_->optimization_id())); Handle<FixedArray> literals = factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); |