This CL enables precise source positions for all V8 compilers. It merges compiler::SourcePosition and internal::SourcePosition to a single class used throughout the codebase. The new internal::SourcePosition instances store an id identifying an inlined function in addition to a script offset.

SourcePosition::InliningId() refers to a the new table DeoptimizationInputData::InliningPositions(), which provides the following data for every inlining id:
 - The inlined SharedFunctionInfo as an offset into DeoptimizationInfo::LiteralArray
 - The SourcePosition of the inlining. Recursively, this yields the full inlining stack.
Before the Code object is created, the same information can be found in CompilationInfo::inlined_functions().

If SourcePosition::InliningId() is SourcePosition::kNotInlined, it refers to the outer (non-inlined) function.
So every SourcePosition has full information about its inlining stack, as long as the corresponding Code object is known. The internal represenation of a source position is a positive 64bit integer.

All compilers create now appropriate source positions for inlined functions. In the case of Turbofan, this required using AstGraphBuilderWithPositions for inlined functions too. So this class is now moved to a header file.

At the moment, the additional information in source positions is only used in --trace-deopt and --code-comments. The profiler needs to be updated, at the moment it gets the correct script offsets from the deopt info, but the wrong script id from the reconstructed deopt stack, which can lead to wrong outputs. This should be resolved by making the profiler use the new inlining information for deopts.

I activated the inlined deoptimization tests in test-cpu-profiler.cc for Turbofan, changing them to a case where the deopt stack and the inlining position agree. It is currently still broken for other cases.

The following additional changes were necessary:
 - The source position table (internal::SourcePositionTableBuilder etc.) supports now 64bit source positions. Encoding source positions in a single 64bit int together with the difference encoding in the source position table results in very little overhead for the inlining id, since only 12% of the source positions in Octane have a changed inlining id.
 - The class HPositionInfo was effectively dead code and is now removed.
 - SourcePosition has new printing and information facilities, including computing a full inlining stack.
 - I had to rename compiler/source-position.{h,cc} to compiler/compiler-source-position-table.{h,cc} to avoid clashes with the new src/source-position.cc file.
 - I wrote the new wrapper PodArray for ByteArray. It is a template working with any POD-type. This is used in DeoptimizationInputData::InliningPositions().
 - I removed HInlinedFunctionInfo and HGraph::inlined_function_infos, because they were only used for the now obsolete Crankshaft inlining ids.
 - Crankshaft managed a list of inlined functions in Lithium: LChunk::inlined_functions. This is an analog structure to CompilationInfo::inlined_functions. So I removed LChunk::inlined_functions and made Crankshaft use CompilationInfo::inlined_functions instead, because this was necessary to register the offsets into the literal array in a uniform way. This is a safe change because LChunk::inlined_functions has no other uses and the functions in CompilationInfo::inlined_functions have a strictly longer lifespan, being created earlier (in Hydrogen already).

BUG=v8:5432

Review-Url: https://codereview.chromium.org/2451853002
Cr-Commit-Position: refs/heads/master@{#40975}
This commit is contained in:
tebbi 2016-11-14 09:21:37 -08:00 committed by Commit bot
parent 372d905d73
commit c3a6ca68d0
103 changed files with 905 additions and 764 deletions

View File

@ -1030,6 +1030,8 @@ v8_source_set("v8_base") {
"src/compiler/common-operator-reducer.h",
"src/compiler/common-operator.cc",
"src/compiler/common-operator.h",
"src/compiler/compiler-source-position-table.cc",
"src/compiler/compiler-source-position-table.h",
"src/compiler/control-builders.cc",
"src/compiler/control-builders.h",
"src/compiler/control-equivalence.cc",
@ -1176,8 +1178,6 @@ v8_source_set("v8_base") {
"src/compiler/simplified-operator-reducer.h",
"src/compiler/simplified-operator.cc",
"src/compiler/simplified-operator.h",
"src/compiler/source-position.cc",
"src/compiler/source-position.h",
"src/compiler/state-values-utils.cc",
"src/compiler/state-values-utils.h",
"src/compiler/store-store-elimination.cc",
@ -1661,6 +1661,7 @@ v8_source_set("v8_base") {
"src/snapshot/startup-serializer.h",
"src/source-position-table.cc",
"src/source-position-table.h",
"src/source-position.cc",
"src/source-position.h",
"src/splay-tree-inl.h",
"src/splay-tree.h",

View File

@ -1421,7 +1421,8 @@ class Assembler : public AssemblerBase {
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(DeoptimizeReason reason, int raw_position, int id);
void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
int id);
// Record the emission of a constant pool.
//

View File

@ -306,8 +306,9 @@ void ConstPool::RecordEntry(intptr_t data,
DCHECK(mode != RelocInfo::COMMENT && mode != RelocInfo::CONST_POOL &&
mode != RelocInfo::VENEER_POOL &&
mode != RelocInfo::CODE_AGE_SEQUENCE &&
mode != RelocInfo::DEOPT_POSITION && mode != RelocInfo::DEOPT_REASON &&
mode != RelocInfo::DEOPT_ID);
mode != RelocInfo::DEOPT_SCRIPT_OFFSET &&
mode != RelocInfo::DEOPT_INLINING_ID &&
mode != RelocInfo::DEOPT_REASON && mode != RelocInfo::DEOPT_ID);
uint64_t raw_data = static_cast<uint64_t>(data);
int offset = assm_->pc_offset();
if (IsEmpty()) {
@ -2947,7 +2948,8 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
(rmode <= RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL)) ||
(rmode == RelocInfo::INTERNAL_REFERENCE) ||
(rmode == RelocInfo::CONST_POOL) || (rmode == RelocInfo::VENEER_POOL) ||
(rmode == RelocInfo::DEOPT_POSITION) ||
(rmode == RelocInfo::DEOPT_SCRIPT_OFFSET) ||
(rmode == RelocInfo::DEOPT_INLINING_ID) ||
(rmode == RelocInfo::DEOPT_REASON) || (rmode == RelocInfo::DEOPT_ID) ||
(rmode == RelocInfo::GENERATOR_CONTINUATION)) {
// Adjust code for new modes.

View File

@ -933,7 +933,8 @@ class Assembler : public AssemblerBase {
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(DeoptimizeReason reason, int raw_position, int id);
void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
int id);
int buffer_space() const;

View File

@ -760,8 +760,10 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
return "internal reference";
case INTERNAL_REFERENCE_ENCODED:
return "encoded internal reference";
case DEOPT_POSITION:
return "deopt position";
case DEOPT_SCRIPT_OFFSET:
return "deopt script offset";
case DEOPT_INLINING_ID:
return "deopt inlining id";
case DEOPT_REASON:
return "deopt reason";
case DEOPT_ID:
@ -801,7 +803,7 @@ void RelocInfo::Print(Isolate* isolate, std::ostream& os) { // NOLINT
os << static_cast<const void*>(pc_) << " " << RelocModeName(rmode_);
if (IsComment(rmode_)) {
os << " (" << reinterpret_cast<char*>(data_) << ")";
} else if (rmode_ == DEOPT_POSITION) {
} else if (rmode_ == DEOPT_SCRIPT_OFFSET || rmode_ == DEOPT_INLINING_ID) {
os << " (" << data() << ")";
} else if (rmode_ == DEOPT_REASON) {
os << " ("
@ -872,7 +874,8 @@ void RelocInfo::Verify(Isolate* isolate) {
case RUNTIME_ENTRY:
case COMMENT:
case EXTERNAL_REFERENCE:
case DEOPT_POSITION:
case DEOPT_SCRIPT_OFFSET:
case DEOPT_INLINING_ID:
case DEOPT_REASON:
case DEOPT_ID:
case CONST_POOL:
@ -1891,11 +1894,12 @@ int ConstantPoolBuilder::Emit(Assembler* assm) {
// Platform specific but identical code for all the platforms.
void Assembler::RecordDeoptReason(DeoptimizeReason reason, int raw_position,
int id) {
void Assembler::RecordDeoptReason(DeoptimizeReason reason,
SourcePosition position, int id) {
if (FLAG_trace_deopt || isolate()->is_profiling()) {
EnsureSpace ensure_space(this);
RecordRelocInfo(RelocInfo::DEOPT_POSITION, raw_position);
RecordRelocInfo(RelocInfo::DEOPT_SCRIPT_OFFSET, position.ScriptOffset());
RecordRelocInfo(RelocInfo::DEOPT_INLINING_ID, position.InliningId());
RecordRelocInfo(RelocInfo::DEOPT_REASON, static_cast<int>(reason));
RecordRelocInfo(RelocInfo::DEOPT_ID, id);
}

View File

@ -52,6 +52,7 @@ class ApiFunction;
namespace internal {
// Forward declarations.
class SourcePosition;
class StatsCounter;
// -----------------------------------------------------------------------------
@ -420,9 +421,10 @@ class RelocInfo {
CONST_POOL,
VENEER_POOL,
DEOPT_POSITION, // Deoptimization source position.
DEOPT_REASON, // Deoptimization reason index.
DEOPT_ID, // Deoptimization inlining id.
DEOPT_SCRIPT_OFFSET,
DEOPT_INLINING_ID, // Deoptimization source position.
DEOPT_REASON, // Deoptimization reason index.
DEOPT_ID, // Deoptimization inlining id.
// This is not an actual reloc mode, but used to encode a long pc jump that
// cannot be encoded as part of another record.
@ -480,7 +482,7 @@ class RelocInfo {
return mode == VENEER_POOL;
}
static inline bool IsDeoptPosition(Mode mode) {
return mode == DEOPT_POSITION;
return mode == DEOPT_SCRIPT_OFFSET || mode == DEOPT_INLINING_ID;
}
static inline bool IsDeoptReason(Mode mode) {
return mode == DEOPT_REASON;

View File

@ -9,6 +9,7 @@
#include "src/ast/scopes.h"
#include "src/isolate.h"
#include "src/parsing/parse-info.h"
#include "src/source-position.h"
namespace v8 {
namespace internal {
@ -218,10 +219,12 @@ void CompilationInfo::SetOptimizing() {
code_flags_ = Code::KindField::update(code_flags_, Code::OPTIMIZED_FUNCTION);
}
void CompilationInfo::AddInlinedFunction(
Handle<SharedFunctionInfo> inlined_function) {
int CompilationInfo::AddInlinedFunction(
Handle<SharedFunctionInfo> inlined_function, SourcePosition pos) {
int id = static_cast<int>(inlined_functions_.size());
inlined_functions_.push_back(InlinedFunctionHolder(
inlined_function, handle(inlined_function->code())));
inlined_function, handle(inlined_function->code()), pos));
return id;
}
Code::Kind CompilationInfo::output_code_kind() const {

View File

@ -283,18 +283,29 @@ class CompilationInfo final {
// Do not remove.
Handle<Code> inlined_code_object_root;
InliningPosition position;
InlinedFunctionHolder(Handle<SharedFunctionInfo> inlined_shared_info,
Handle<Code> inlined_code_object_root)
Handle<Code> inlined_code_object_root,
SourcePosition pos)
: shared_info(inlined_shared_info),
inlined_code_object_root(inlined_code_object_root) {}
inlined_code_object_root(inlined_code_object_root) {
position.position = pos;
// initialized when generating the deoptimization literals
position.inlined_function_id = -1;
}
void RegisterInlinedFunctionId(size_t inlined_function_id) {
position.inlined_function_id = static_cast<int>(inlined_function_id);
}
};
typedef std::vector<InlinedFunctionHolder> InlinedFunctionList;
InlinedFunctionList const& inlined_functions() const {
return inlined_functions_;
}
InlinedFunctionList& inlined_functions() { return inlined_functions_; }
void AddInlinedFunction(Handle<SharedFunctionInfo> inlined_function);
// Returns the inlining id for source position tracking.
int AddInlinedFunction(Handle<SharedFunctionInfo> inlined_function,
SourcePosition pos);
std::unique_ptr<char[]> GetDebugName() const;

View File

@ -1276,6 +1276,7 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
Handle<Script> script;
if (!maybe_shared_info.ToHandle(&shared_info)) {
script = isolate->factory()->NewScript(source);
if (FLAG_trace_deopt) Script::InitLineEnds(script);
if (!script_name.is_null()) {
script->set_name(*script_name);
script->set_line_offset(line_offset);
@ -1435,6 +1436,7 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
// Create a script object describing the script to be compiled.
Handle<Script> script = isolate->factory()->NewScript(source);
if (FLAG_trace_deopt) Script::InitLineEnds(script);
if (natives == NATIVES_CODE) {
script->set_type(Script::TYPE_NATIVE);
script->set_hide_source(true);

View File

@ -1643,7 +1643,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
DeoptimizeReason deoptimization_reason =
GetDeoptimizationReason(deoptimization_id);
__ RecordDeoptReason(deoptimization_reason, pos.raw(), deoptimization_id);
__ RecordDeoptReason(deoptimization_reason, pos, deoptimization_id);
__ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
__ CheckConstPool(false, false);
return kSuccess;

View File

@ -1756,7 +1756,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
DeoptimizeReason deoptimization_reason =
GetDeoptimizationReason(deoptimization_id);
__ RecordDeoptReason(deoptimization_reason, pos.raw(), deoptimization_id);
__ RecordDeoptReason(deoptimization_reason, pos, deoptimization_id);
__ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
return kSuccess;
}

View File

@ -4367,6 +4367,16 @@ Node* AstGraphBuilder::MergeValue(Node* value, Node* other, Node* control) {
return value;
}
AstGraphBuilderWithPositions::AstGraphBuilderWithPositions(
Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph,
float invocation_frequency, LoopAssignmentAnalysis* loop_assignment,
TypeHintAnalysis* type_hint_analysis, SourcePositionTable* source_positions,
int inlining_id)
: AstGraphBuilder(local_zone, info, jsgraph, invocation_frequency,
loop_assignment, type_hint_analysis),
source_positions_(source_positions),
start_position_(info->shared_info()->start_position(), inlining_id) {}
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -6,6 +6,7 @@
#define V8_COMPILER_AST_GRAPH_BUILDER_H_
#include "src/ast/ast.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/liveness-analyzer.h"
#include "src/compiler/state-values-utils.h"
@ -617,6 +618,35 @@ class AstGraphBuilder::Environment : public ZoneObject {
void PrepareForOsrEntry();
};
class AstGraphBuilderWithPositions final : public AstGraphBuilder {
public:
AstGraphBuilderWithPositions(Zone* local_zone, CompilationInfo* info,
JSGraph* jsgraph, float invocation_frequency,
LoopAssignmentAnalysis* loop_assignment,
TypeHintAnalysis* type_hint_analysis,
SourcePositionTable* source_positions,
int inlining_id = SourcePosition::kNotInlined);
bool CreateGraph(bool stack_check = true) {
SourcePositionTable::Scope pos_scope(source_positions_, start_position_);
return AstGraphBuilder::CreateGraph(stack_check);
}
#define DEF_VISIT(type) \
void Visit##type(type* node) override { \
SourcePositionTable::Scope pos( \
source_positions_, \
SourcePosition(node->position(), start_position_.InliningId())); \
AstGraphBuilder::Visit##type(node); \
}
AST_NODE_LIST(DEF_VISIT)
#undef DEF_VISIT
private:
SourcePositionTable* const source_positions_;
SourcePosition const start_position_;
};
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -8,6 +8,7 @@
#include "src/ast/scopes.h"
#include "src/compilation-info.h"
#include "src/compiler/bytecode-branch-analysis.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/linkage.h"
#include "src/compiler/operator-properties.h"
#include "src/interpreter/bytecodes.h"
@ -491,7 +492,8 @@ Node* BytecodeGraphBuilder::Environment::Checkpoint(
BytecodeGraphBuilder::BytecodeGraphBuilder(
Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph,
float invocation_frequency, SourcePositionTable* source_positions)
float invocation_frequency, SourcePositionTable* source_positions,
int inlining_id)
: local_zone_(local_zone),
jsgraph_(jsgraph),
invocation_frequency_(invocation_frequency),
@ -516,7 +518,8 @@ BytecodeGraphBuilder::BytecodeGraphBuilder(
liveness_analyzer_(
static_cast<size_t>(bytecode_array()->register_count()), true,
local_zone),
source_positions_(source_positions) {}
source_positions_(source_positions),
start_position_(info->shared_info()->start_position(), inlining_id) {}
Node* BytecodeGraphBuilder::GetNewTarget() {
if (!new_target_.is_set()) {
@ -570,6 +573,8 @@ VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) {
}
bool BytecodeGraphBuilder::CreateGraph(bool stack_check) {
SourcePositionTable::Scope pos_scope(source_positions_, start_position_);
// Set up the basic structure of the graph. Outputs for {Start} are the formal
// parameters (including the receiver) plus new target, number of arguments,
// context and closure.
@ -2197,13 +2202,11 @@ Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other,
void BytecodeGraphBuilder::UpdateCurrentSourcePosition(
SourcePositionTableIterator* it, int offset) {
// TODO(neis): Remove this once inlining supports source positions.
if (source_positions_ == nullptr) return;
if (it->done()) return;
if (it->code_offset() == offset) {
source_positions_->set_current_position(it->source_position());
source_positions_->SetCurrentPosition(SourcePosition(
it->source_position().ScriptOffset(), start_position_.InliningId()));
it->Advance();
} else {
DCHECK_GT(it->code_offset(), offset);

View File

@ -9,7 +9,6 @@
#include "src/compiler/bytecode-loop-analysis.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/liveness-analyzer.h"
#include "src/compiler/source-position.h"
#include "src/compiler/state-values-utils.h"
#include "src/compiler/type-hint-analyzer.h"
#include "src/interpreter/bytecode-array-iterator.h"
@ -24,13 +23,16 @@ class CompilationInfo;
namespace compiler {
class SourcePositionTable;
// The BytecodeGraphBuilder produces a high-level IR graph based on
// interpreter bytecodes.
class BytecodeGraphBuilder {
public:
BytecodeGraphBuilder(Zone* local_zone, CompilationInfo* info,
JSGraph* jsgraph, float invocation_frequency,
SourcePositionTable* source_positions);
SourcePositionTable* source_positions,
int inlining_id = SourcePosition::kNotInlined);
// Creates a graph by visiting bytecodes.
bool CreateGraph(bool stack_check = true);
@ -313,6 +315,8 @@ class BytecodeGraphBuilder {
// The Turbofan source position table, to be populated.
SourcePositionTable* source_positions_;
SourcePosition const start_position_;
// Update [source_positions_]'s current position to that of the bytecode at
// [offset], if any.
void UpdateCurrentSourcePosition(SourcePositionTableIterator* it, int offset);

View File

@ -88,9 +88,10 @@ Handle<Code> CodeGenerator::GenerateCode() {
// Define deoptimization literals for all inlined functions.
DCHECK_EQ(0u, deoptimization_literals_.size());
for (const CompilationInfo::InlinedFunctionHolder& inlined :
for (CompilationInfo::InlinedFunctionHolder& inlined :
info->inlined_functions()) {
if (!inlined.shared_info.is_identical_to(info->shared_info())) {
inlined.RegisterInlinedFunctionId(deoptimization_literals_.size());
DefineDeoptimizationLiteral(inlined.shared_info);
}
}
@ -469,29 +470,19 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleInstruction(
void CodeGenerator::AssembleSourcePosition(Instruction* instr) {
SourcePosition source_position;
SourcePosition source_position = SourcePosition::Unknown();
if (!code()->GetSourcePosition(instr, &source_position)) return;
if (source_position == current_source_position_) return;
current_source_position_ = source_position;
if (source_position.IsUnknown()) return;
int code_pos = source_position.raw();
source_position_table_builder_.AddPosition(masm()->pc_offset(), code_pos,
false);
if (!source_position.IsKnown()) return;
source_position_table_builder_.AddPosition(masm()->pc_offset(),
source_position, false);
if (FLAG_code_comments) {
CompilationInfo* info = this->info();
if (!info->parse_info()) return;
Vector<char> buffer = Vector<char>::New(256);
int ln = Script::GetLineNumber(info->script(), code_pos);
int cn = Script::GetColumnNumber(info->script(), code_pos);
if (info->script()->name()->IsString()) {
Handle<String> file(String::cast(info->script()->name()));
base::OS::SNPrintF(buffer.start(), buffer.length(), "-- %s:%d:%d --",
file->ToCString().get(), ln, cn);
} else {
base::OS::SNPrintF(buffer.start(), buffer.length(),
"-- <unknown>:%d:%d --", ln, cn);
}
masm()->RecordComment(buffer.start());
std::ostringstream buffer;
buffer << "-- " << source_position.InliningStack(info) << " --";
masm()->RecordComment(StrDup(buffer.str().c_str()));
}
}
@ -516,6 +507,26 @@ void CodeGenerator::AssembleGaps(Instruction* instr) {
}
}
namespace {
Handle<PodArray<InliningPosition>> CreateInliningPositions(
CompilationInfo* info) {
const CompilationInfo::InlinedFunctionList& inlined_functions =
info->inlined_functions();
if (inlined_functions.size() == 0) {
return Handle<PodArray<InliningPosition>>::cast(
info->isolate()->factory()->empty_byte_array());
}
Handle<PodArray<InliningPosition>> inl_positions =
PodArray<InliningPosition>::New(
info->isolate(), static_cast<int>(inlined_functions.size()), TENURED);
for (size_t i = 0; i < inlined_functions.size(); ++i) {
inl_positions->set(static_cast<int>(i), inlined_functions[i].position);
}
return inl_positions;
}
} // namespace
void CodeGenerator::PopulateDeoptimizationData(Handle<Code> code_object) {
CompilationInfo* info = this->info();
@ -548,6 +559,9 @@ void CodeGenerator::PopulateDeoptimizationData(Handle<Code> code_object) {
data->SetLiteralArray(*literals);
}
Handle<PodArray<InliningPosition>> inl_pos = CreateInliningPositions(info);
data->SetInliningPositions(*inl_pos);
if (info->is_osr()) {
DCHECK(osr_pc_offset_ >= 0);
data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id().ToInt()));

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/compiler/source-position.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/graph.h"
#include "src/compiler/node-aux-data.h"
@ -24,28 +24,24 @@ class SourcePositionTable::Decorator final : public GraphDecorator {
SourcePositionTable* source_positions_;
};
SourcePositionTable::SourcePositionTable(Graph* graph)
: graph_(graph),
decorator_(nullptr),
current_position_(SourcePosition::Unknown()),
table_(graph->zone()) {}
void SourcePositionTable::AddDecorator() {
DCHECK_NULL(decorator_);
decorator_ = new (graph_->zone()) Decorator(this);
graph_->AddDecorator(decorator_);
}
void SourcePositionTable::RemoveDecorator() {
DCHECK_NOT_NULL(decorator_);
graph_->RemoveDecorator(decorator_);
decorator_ = nullptr;
}
SourcePosition SourcePositionTable::GetSourcePosition(Node* node) const {
return table_.Get(node);
}
@ -65,7 +61,7 @@ void SourcePositionTable::Print(std::ostream& os) const {
os << ",";
}
os << "\"" << i.first << "\""
<< ":" << pos.raw();
<< ":" << pos.ScriptOffset();
needs_comma = true;
}
}

View File

@ -2,43 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_COMPILER_SOURCE_POSITION_H_
#define V8_COMPILER_SOURCE_POSITION_H_
#ifndef V8_COMPILER_COMPILER_SOURCE_POSITION_TABLE_H_
#define V8_COMPILER_COMPILER_SOURCE_POSITION_TABLE_H_
#include "src/base/compiler-specific.h"
#include "src/compiler/node-aux-data.h"
#include "src/globals.h"
#include "src/source-position.h"
namespace v8 {
namespace internal {
namespace compiler {
// Encapsulates encoding and decoding of sources positions from which Nodes
// originated.
class SourcePosition final {
public:
explicit SourcePosition(int raw = kUnknownPosition) : raw_(raw) {}
static SourcePosition Unknown() { return SourcePosition(kUnknownPosition); }
bool IsUnknown() const { return raw() == kUnknownPosition; }
bool IsKnown() const { return raw() != kUnknownPosition; }
int raw() const { return raw_; }
private:
static const int kUnknownPosition = kNoSourcePosition;
int raw_;
};
inline bool operator==(const SourcePosition& lhs, const SourcePosition& rhs) {
return lhs.raw() == rhs.raw();
}
inline bool operator!=(const SourcePosition& lhs, const SourcePosition& rhs) {
return !(lhs == rhs);
}
class V8_EXPORT_PRIVATE SourcePositionTable final
: public NON_EXPORTED_BASE(ZoneObject) {
public:
@ -74,8 +49,8 @@ class V8_EXPORT_PRIVATE SourcePositionTable final
SourcePosition GetSourcePosition(Node* node) const;
void SetSourcePosition(Node* node, SourcePosition position);
void set_current_position(int position) {
current_position_ = SourcePosition(position);
void SetCurrentPosition(const SourcePosition& pos) {
current_position_ = pos;
}
void Print(std::ostream& os) const;
@ -86,7 +61,7 @@ class V8_EXPORT_PRIVATE SourcePositionTable final
Graph* const graph_;
Decorator* decorator_;
SourcePosition current_position_;
NodeAuxData<SourcePosition> table_;
NodeAuxData<SourcePosition, SourcePosition::Unknown> table_;
DISALLOW_COPY_AND_ASSIGN(SourcePositionTable);
};
@ -95,4 +70,4 @@ class V8_EXPORT_PRIVATE SourcePositionTable final
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_SOURCE_POSITION_H_
#endif // V8_COMPILER_COMPILER_SOURCE_POSITION_TABLE_H_

View File

@ -11,6 +11,7 @@
#include "src/code-stubs.h"
#include "src/compilation-info.h"
#include "src/compiler/all-nodes.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/graph.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/node.h"
@ -151,7 +152,7 @@ class JSONGraphNodeWriter {
}
SourcePosition position = positions_->GetSourcePosition(node);
if (position.IsKnown()) {
os_ << ",\"pos\":" << position.raw();
os_ << ",\"pos\":" << position.ScriptOffset();
}
os_ << ",\"opcode\":\"" << IrOpcode::Mnemonic(node->opcode()) << "\"";
os_ << ",\"control\":" << (NodeProperties::IsControl(node) ? "true"
@ -496,7 +497,7 @@ void GraphC1Visualizer::PrintSchedule(const char* phase,
if (positions != nullptr) {
SourcePosition position = positions->GetSourcePosition(node);
if (position.IsKnown()) {
os_ << " pos:" << position.raw();
os_ << " pos:" << position.ScriptOffset();
}
}
os_ << " <|@\n";

View File

@ -1790,7 +1790,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
DeoptimizeReason deoptimization_reason =
GetDeoptimizationReason(deoptimization_id);
__ RecordDeoptReason(deoptimization_reason, pos.raw(), deoptimization_id);
__ RecordDeoptReason(deoptimization_reason, pos, deoptimization_id);
__ call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
return kSuccess;
}

View File

@ -7,6 +7,7 @@
#include <limits>
#include "src/base/adapters.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/instruction-selector-impl.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/pipeline.h"

View File

@ -15,7 +15,6 @@
#include "src/compiler/frame.h"
#include "src/compiler/instruction-codes.h"
#include "src/compiler/opcodes.h"
#include "src/compiler/source-position.h"
#include "src/globals.h"
#include "src/macro-assembler.h"
#include "src/register-configuration.h"
@ -23,10 +22,13 @@
namespace v8 {
namespace internal {
class SourcePosition;
namespace compiler {
// Forward declarations.
class Schedule;
class SourcePositionTable;
class V8_EXPORT_PRIVATE InstructionOperand {
public:

View File

@ -15,10 +15,11 @@ class JSInliningHeuristic final : public AdvancedReducer {
public:
enum Mode { kGeneralInlining, kRestrictedInlining, kStressInlining };
JSInliningHeuristic(Editor* editor, Mode mode, Zone* local_zone,
CompilationInfo* info, JSGraph* jsgraph)
CompilationInfo* info, JSGraph* jsgraph,
SourcePositionTable* source_positions)
: AdvancedReducer(editor),
mode_(mode),
inliner_(editor, local_zone, info, jsgraph),
inliner_(editor, local_zone, info, jsgraph, source_positions),
candidates_(local_zone),
seen_(local_zone),
jsgraph_(jsgraph) {}

View File

@ -523,7 +523,8 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
// Remember that we inlined this function. This needs to be called right
// after we ensure deoptimization support so that the code flusher
// does not remove the code with the deoptimization support.
info_->AddInlinedFunction(shared_info);
int inlining_id = info_->AddInlinedFunction(
shared_info, source_positions_->GetSourcePosition(node));
// ----------------------------------------------------------------
// After this point, we've made a decision to inline this function.
@ -543,7 +544,8 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
// Run the BytecodeGraphBuilder to create the subgraph.
Graph::SubgraphScope scope(graph());
BytecodeGraphBuilder graph_builder(&zone, &info, jsgraph(),
call.frequency(), nullptr);
call.frequency(), source_positions_,
inlining_id);
graph_builder.CreateGraph(false);
// Extract the inlinee start/end nodes.
@ -562,8 +564,9 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
// Run the AstGraphBuilder to create the subgraph.
Graph::SubgraphScope scope(graph());
AstGraphBuilder graph_builder(&zone, &info, jsgraph(), call.frequency(),
loop_assignment, type_hint_analysis);
AstGraphBuilderWithPositions graph_builder(
&zone, &info, jsgraph(), call.frequency(), loop_assignment,
type_hint_analysis, source_positions_, inlining_id);
graph_builder.CreateGraph(false);
// Extract the inlinee start/end nodes.

View File

@ -5,8 +5,8 @@
#ifndef V8_COMPILER_JS_INLINING_H_
#define V8_COMPILER_JS_INLINING_H_
#include "src/compiler/js-graph.h"
#include "src/compiler/graph-reducer.h"
#include "src/compiler/js-graph.h"
namespace v8 {
namespace internal {
@ -16,17 +16,20 @@ class CompilationInfo;
namespace compiler {
class SourcePositionTable;
// The JSInliner provides the core graph inlining machinery. Note that this
// class only deals with the mechanics of how to inline one graph into another,
// heuristics that decide what and how much to inline are beyond its scope.
class JSInliner final : public AdvancedReducer {
public:
JSInliner(Editor* editor, Zone* local_zone, CompilationInfo* info,
JSGraph* jsgraph)
JSGraph* jsgraph, SourcePositionTable* source_positions)
: AdvancedReducer(editor),
local_zone_(local_zone),
info_(info),
jsgraph_(jsgraph) {}
jsgraph_(jsgraph),
source_positions_(source_positions) {}
// Reducer interface, eagerly inlines everything.
Reduction Reduce(Node* node) final;
@ -45,6 +48,7 @@ class JSInliner final : public AdvancedReducer {
Zone* const local_zone_;
CompilationInfo* info_;
JSGraph* const jsgraph_;
SourcePositionTable* const source_positions_;
Node* CreateArtificialFrameState(Node* node, Node* outer_frame_state,
int parameter_count,

View File

@ -1886,7 +1886,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
DeoptimizeReason deoptimization_reason =
GetDeoptimizationReason(deoptimization_id);
__ RecordDeoptReason(deoptimization_reason, pos.raw(), deoptimization_id);
__ RecordDeoptReason(deoptimization_reason, pos, deoptimization_id);
__ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
return kSuccess;
}

View File

@ -2207,7 +2207,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
DeoptimizeReason deoptimization_reason =
GetDeoptimizationReason(deoptimization_id);
__ RecordDeoptReason(deoptimization_reason, pos.raw(), deoptimization_id);
__ RecordDeoptReason(deoptimization_reason, pos, deoptimization_id);
__ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
return kSuccess;
}

View File

@ -15,20 +15,20 @@ namespace compiler {
// Forward declarations.
class Node;
template <class T>
template <class T, T def()>
class NodeAuxData {
public:
explicit NodeAuxData(Zone* zone) : aux_data_(zone) {}
void Set(Node* node, T const& data) {
size_t const id = node->id();
if (id >= aux_data_.size()) aux_data_.resize(id + 1);
if (id >= aux_data_.size()) aux_data_.resize(id + 1, def());
aux_data_[id] = data;
}
T Get(Node* node) const {
size_t const id = node->id();
return (id < aux_data_.size()) ? aux_data_[id] : T();
return (id < aux_data_.size()) ? aux_data_[id] : def();
}
class const_iterator;
@ -41,9 +41,8 @@ class NodeAuxData {
ZoneVector<T> aux_data_;
};
template <class T>
class NodeAuxData<T>::const_iterator {
template <class T, T def()>
class NodeAuxData<T, def>::const_iterator {
public:
typedef std::forward_iterator_tag iterator_category;
typedef int difference_type;
@ -76,14 +75,16 @@ class NodeAuxData<T>::const_iterator {
size_t current_;
};
template <class T>
typename NodeAuxData<T>::const_iterator NodeAuxData<T>::begin() const {
return typename NodeAuxData<T>::const_iterator(&aux_data_, 0);
template <class T, T def()>
typename NodeAuxData<T, def>::const_iterator NodeAuxData<T, def>::begin()
const {
return typename NodeAuxData<T, def>::const_iterator(&aux_data_, 0);
}
template <class T>
typename NodeAuxData<T>::const_iterator NodeAuxData<T>::end() const {
return typename NodeAuxData<T>::const_iterator(&aux_data_, aux_data_.size());
template <class T, T def()>
typename NodeAuxData<T, def>::const_iterator NodeAuxData<T, def>::end() const {
return typename NodeAuxData<T, def>::const_iterator(&aux_data_,
aux_data_.size());
}
} // namespace compiler

View File

@ -427,38 +427,6 @@ void TraceSchedule(CompilationInfo* info, Schedule* schedule) {
}
class AstGraphBuilderWithPositions final : public AstGraphBuilder {
public:
AstGraphBuilderWithPositions(Zone* local_zone, CompilationInfo* info,
JSGraph* jsgraph,
LoopAssignmentAnalysis* loop_assignment,
TypeHintAnalysis* type_hint_analysis,
SourcePositionTable* source_positions)
: AstGraphBuilder(local_zone, info, jsgraph, 1.0f, loop_assignment,
type_hint_analysis),
source_positions_(source_positions),
start_position_(info->shared_info()->start_position()) {}
bool CreateGraph() {
SourcePositionTable::Scope pos_scope(source_positions_, start_position_);
return AstGraphBuilder::CreateGraph();
}
#define DEF_VISIT(type) \
void Visit##type(type* node) override { \
SourcePositionTable::Scope pos(source_positions_, \
SourcePosition(node->position())); \
AstGraphBuilder::Visit##type(node); \
}
AST_NODE_LIST(DEF_VISIT)
#undef DEF_VISIT
private:
SourcePositionTable* const source_positions_;
SourcePosition const start_position_;
};
class SourcePositionWrapper final : public Reducer {
public:
SourcePositionWrapper(Reducer* reducer, SourcePositionTable* table)
@ -753,8 +721,9 @@ struct GraphBuilderPhase {
succeeded = graph_builder.CreateGraph();
} else {
AstGraphBuilderWithPositions graph_builder(
temp_zone, data->info(), data->jsgraph(), data->loop_assignment(),
data->type_hint_analysis(), data->source_positions());
temp_zone, data->info(), data->jsgraph(), 1.0f,
data->loop_assignment(), data->type_hint_analysis(),
data->source_positions());
succeeded = graph_builder.CreateGraph();
}
@ -807,11 +776,11 @@ struct InliningPhase {
JSNativeContextSpecialization native_context_specialization(
&graph_reducer, data->jsgraph(), flags, data->native_context(),
data->info()->dependencies(), temp_zone);
JSInliningHeuristic inlining(&graph_reducer,
data->info()->is_inlining_enabled()
? JSInliningHeuristic::kGeneralInlining
: JSInliningHeuristic::kRestrictedInlining,
temp_zone, data->info(), data->jsgraph());
JSInliningHeuristic inlining(
&graph_reducer, data->info()->is_inlining_enabled()
? JSInliningHeuristic::kGeneralInlining
: JSInliningHeuristic::kRestrictedInlining,
temp_zone, data->info(), data->jsgraph(), data->source_positions());
JSIntrinsicLowering intrinsic_lowering(
&graph_reducer, data->jsgraph(),
data->info()->is_deoptimization_enabled()

View File

@ -2082,7 +2082,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
DeoptimizeReason deoptimization_reason =
GetDeoptimizationReason(deoptimization_id);
__ RecordDeoptReason(deoptimization_reason, pos.raw(), deoptimization_id);
__ RecordDeoptReason(deoptimization_reason, pos, deoptimization_id);
__ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
return kSuccess;
}

View File

@ -2220,7 +2220,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
DeoptimizeReason deoptimization_reason =
GetDeoptimizationReason(deoptimization_id);
__ RecordDeoptReason(deoptimization_reason, pos.raw(), deoptimization_id);
__ RecordDeoptReason(deoptimization_reason, pos, deoptimization_id);
__ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
return kSuccess;
}

View File

@ -11,6 +11,7 @@
#include "src/code-factory.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/diamond.h"
#include "src/compiler/linkage.h"
#include "src/compiler/node-matchers.h"
@ -19,7 +20,6 @@
#include "src/compiler/operator-properties.h"
#include "src/compiler/representation-change.h"
#include "src/compiler/simplified-operator.h"
#include "src/compiler/source-position.h"
#include "src/compiler/type-cache.h"
#include "src/conversions-inl.h"
#include "src/objects.h"

View File

@ -13,6 +13,7 @@
#include "src/compiler/access-builder.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/diamond.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/graph.h"
@ -25,7 +26,6 @@
#include "src/compiler/node-matchers.h"
#include "src/compiler/pipeline.h"
#include "src/compiler/simd-scalar-lowering.h"
#include "src/compiler/source-position.h"
#include "src/compiler/zone-stats.h"
#include "src/code-factory.h"
@ -3086,9 +3086,8 @@ void WasmGraphBuilder::SimdScalarLoweringForTesting() {
void WasmGraphBuilder::SetSourcePosition(Node* node,
wasm::WasmCodePosition position) {
DCHECK_NE(position, wasm::kNoCodePosition);
compiler::SourcePosition pos(position);
if (source_position_table_)
source_position_table_->SetSourcePosition(node, pos);
source_position_table_->SetSourcePosition(node, SourcePosition(position));
}
Node* WasmGraphBuilder::CreateS128Value(int32_t value) {

View File

@ -2351,7 +2351,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
DeoptimizeReason deoptimization_reason =
GetDeoptimizationReason(deoptimization_id);
__ RecordDeoptReason(deoptimization_reason, pos.raw(), deoptimization_id);
__ RecordDeoptReason(deoptimization_reason, pos, deoptimization_id);
__ call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
return kSuccess;
}

View File

@ -2245,7 +2245,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
DeoptimizeReason deoptimization_reason =
GetDeoptimizationReason(deoptimization_id);
__ RecordDeoptReason(deoptimization_reason, pos.raw(), deoptimization_id);
__ RecordDeoptReason(deoptimization_reason, pos, deoptimization_id);
__ call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
return kSuccess;
}

View File

@ -2344,7 +2344,6 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
inner->BindContext(instr->closure_context());
inner->set_entry(instr);
current_block_->UpdateEnvironment(inner);
chunk_->AddInlinedFunction(instr->shared());
return NULL;
}

View File

@ -253,8 +253,7 @@ bool LCodeGen::GenerateDeferredCode() {
HValue* value =
instructions_->at(code->instruction_index())->hydrogen_value();
RecordAndWritePosition(
chunk()->graph()->SourcePositionToScriptPosition(value->position()));
RecordAndWritePosition(value->position());
Comment(";;; <@%d,#%d> "
"-------------------- Deferred %s --------------------",

View File

@ -1402,7 +1402,6 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
inner->BindContext(instr->closure_context());
inner->set_entry(instr);
current_block_->UpdateEnvironment(inner);
chunk_->AddInlinedFunction(instr->shared());
return NULL;
}

View File

@ -704,8 +704,7 @@ bool LCodeGen::GenerateDeferredCode() {
HValue* value =
instructions_->at(code->instruction_index())->hydrogen_value();
RecordAndWritePosition(
chunk()->graph()->SourcePositionToScriptPosition(value->position()));
RecordAndWritePosition(value->position());
Comment(";;; <@%d,#%d> "
"-------------------- Deferred %s --------------------",

View File

@ -486,9 +486,6 @@ class HValue : public ZoneObject {
virtual ~HValue() {}
virtual SourcePosition position() const { return SourcePosition::Unknown(); }
virtual SourcePosition operand_position(int index) const {
return position();
}
HBasicBlock* block() const { return block_; }
void SetBlock(HBasicBlock* block);
@ -948,99 +945,6 @@ std::ostream& operator<<(std::ostream& os, const ChangesOf& v);
return new (zone) I(context, p1, p2, p3, p4, p5, p6); \
}
// A helper class to represent per-operand position information attached to
// the HInstruction in the compact form. Uses tagging to distinguish between
// case when only instruction's position is available and case when operands'
// positions are also available.
// 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.
class HPositionInfo {
public:
explicit HPositionInfo(int pos) : data_(TagPosition(pos)) { }
SourcePosition position() const {
if (has_operand_positions()) {
return operand_positions()[kInstructionPosIndex];
}
return SourcePosition::FromRaw(static_cast<int>(UntagPosition(data_)));
}
void set_position(SourcePosition pos) {
if (has_operand_positions()) {
operand_positions()[kInstructionPosIndex] = pos;
} else {
data_ = TagPosition(pos.raw());
}
}
void ensure_storage_for_operand_positions(Zone* zone, int operand_count) {
if (has_operand_positions()) {
return;
}
const int length = kFirstOperandPosIndex + operand_count;
SourcePosition* positions = zone->NewArray<SourcePosition>(length);
for (int i = 0; i < length; i++) {
positions[i] = SourcePosition::Unknown();
}
const SourcePosition pos = position();
data_ = reinterpret_cast<intptr_t>(positions);
set_position(pos);
DCHECK(has_operand_positions());
}
SourcePosition operand_position(int idx) const {
if (!has_operand_positions()) {
return position();
}
return *operand_position_slot(idx);
}
void set_operand_position(int idx, SourcePosition pos) {
*operand_position_slot(idx) = pos;
}
private:
static const intptr_t kInstructionPosIndex = 0;
static const intptr_t kFirstOperandPosIndex = 1;
SourcePosition* operand_position_slot(int idx) const {
DCHECK(has_operand_positions());
return &(operand_positions()[kFirstOperandPosIndex + idx]);
}
bool has_operand_positions() const {
return !IsTaggedPosition(data_);
}
SourcePosition* operand_positions() const {
DCHECK(has_operand_positions());
return reinterpret_cast<SourcePosition*>(data_);
}
static const intptr_t kPositionTag = 1;
static const intptr_t kPositionShift = 1;
static bool IsTaggedPosition(intptr_t val) {
return (val & kPositionTag) != 0;
}
static intptr_t UntagPosition(intptr_t val) {
DCHECK(IsTaggedPosition(val));
return val >> kPositionShift;
}
static intptr_t TagPosition(intptr_t val) {
const intptr_t result = (val << kPositionShift) | kPositionTag;
DCHECK(UntagPosition(result) == val);
return result;
}
intptr_t data_;
};
class HInstruction : public HValue {
public:
HInstruction* next() const { return next_; }
@ -1067,26 +971,11 @@ class HInstruction : public HValue {
}
// The position is a write-once variable.
SourcePosition position() const override {
return SourcePosition(position_.position());
}
bool has_position() const {
return !position().IsUnknown();
}
SourcePosition position() const override { return position_; }
bool has_position() const { return position_.IsKnown(); }
void set_position(SourcePosition position) {
DCHECK(!has_position());
DCHECK(!position.IsUnknown());
position_.set_position(position);
}
SourcePosition operand_position(int index) const override {
const SourcePosition pos = position_.operand_position(index);
return pos.IsUnknown() ? position() : pos;
}
void set_operand_position(Zone* zone, int index, SourcePosition pos) {
DCHECK(0 <= index && index < OperandCount());
position_.ensure_storage_for_operand_positions(zone, OperandCount());
position_.set_operand_position(index, pos);
DCHECK(position.IsKnown());
position_ = position;
}
bool Dominates(HInstruction* other);
@ -1111,7 +1000,7 @@ class HInstruction : public HValue {
: HValue(type),
next_(NULL),
previous_(NULL),
position_(kNoSourcePosition) {
position_(SourcePosition::Unknown()) {
SetDependsOnFlag(kOsrEntries);
}
@ -1125,7 +1014,7 @@ class HInstruction : public HValue {
HInstruction* next_;
HInstruction* previous_;
HPositionInfo position_;
SourcePosition position_;
friend class HBasicBlock;
};
@ -1920,7 +1809,7 @@ class HEnterInlined final : public HTemplateInstruction<0> {
function_(function),
inlining_kind_(inlining_kind),
syntactic_tail_call_mode_(syntactic_tail_call_mode),
inlining_id_(0),
inlining_id_(-1),
arguments_var_(arguments_var),
arguments_object_(arguments_object),
return_targets_(2, zone) {}
@ -3474,12 +3363,6 @@ class HBinaryOperation : public HTemplateInstruction<3> {
return representation();
}
void SetOperandPositions(Zone* zone, SourcePosition left_pos,
SourcePosition right_pos) {
set_operand_position(zone, 1, left_pos);
set_operand_position(zone, 2, right_pos);
}
bool RightIsPowerOf2() {
if (!right()->IsInteger32Constant()) return false;
int32_t value = right()->GetInteger32Constant();
@ -3892,12 +3775,6 @@ class HCompareNumericAndBranch : public HTemplateControlInstruction<2, 2> {
std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
void SetOperandPositions(Zone* zone, SourcePosition left_pos,
SourcePosition right_pos) {
set_operand_position(zone, 0, left_pos);
set_operand_position(zone, 1, right_pos);
}
DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
private:

View File

@ -41,12 +41,6 @@ void HRepresentationChangesPhase::InsertRepresentationChangeForUse(
new_value = new (graph()->zone())
HChange(value, to, is_truncating_to_smi, is_truncating_to_int,
is_truncating_to_number);
if (!use_value->operand_position(use_index).IsUnknown()) {
new_value->set_position(use_value->operand_position(use_index));
} else {
DCHECK(!FLAG_hydrogen_track_positions ||
!graph()->info()->IsOptimizing());
}
}
new_value->InsertBefore(next);

View File

@ -86,7 +86,7 @@ class HOptimizedGraphBuilderWithPositions : public HOptimizedGraphBuilder {
SetSourcePosition(node->position()); \
} \
HOptimizedGraphBuilder::Visit##type(node); \
if (!old_position.IsUnknown()) { \
if (old_position.IsKnown()) { \
set_source_position(old_position); \
} \
}
@ -101,7 +101,7 @@ class HOptimizedGraphBuilderWithPositions : public HOptimizedGraphBuilder {
SetSourcePosition(node->position()); \
} \
HOptimizedGraphBuilder::Visit##type(node); \
if (!old_position.IsUnknown()) { \
if (old_position.IsKnown()) { \
set_source_position(old_position); \
} \
}
@ -312,7 +312,7 @@ void HBasicBlock::AddInstruction(HInstruction* instr, SourcePosition position) {
DCHECK(!instr->IsLinked());
DCHECK(!IsFinished());
if (!position.IsUnknown()) {
if (position.IsKnown()) {
instr->set_position(position);
}
if (first_ == NULL) {
@ -320,7 +320,7 @@ void HBasicBlock::AddInstruction(HInstruction* instr, SourcePosition position) {
DCHECK(!last_environment()->ast_id().IsNone());
HBlockEntry* entry = new(zone()) HBlockEntry();
entry->InitializeAsFirst(this);
if (!position.IsUnknown()) {
if (position.IsKnown()) {
entry->set_position(position);
} else {
DCHECK(!FLAG_hydrogen_track_positions ||
@ -1364,7 +1364,8 @@ HGraph* HGraphBuilder::CreateGraph() {
graph_ = new (zone()) HGraph(info_, descriptor_);
if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_);
if (!info_->IsStub() && is_tracking_positions()) {
TraceInlinedFunction(info_->shared_info(), SourcePosition::Unknown());
TraceInlinedFunction(info_->shared_info(), SourcePosition::Unknown(),
SourcePosition::kNotInlined);
}
CompilationPhase phase("H_Block building", info_);
set_current_block(graph()->entry_block());
@ -1373,12 +1374,11 @@ HGraph* HGraphBuilder::CreateGraph() {
return graph_;
}
int HGraphBuilder::TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
SourcePosition position) {
void HGraphBuilder::TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
SourcePosition position,
int inlining_id) {
DCHECK(is_tracking_positions());
int inline_id = static_cast<int>(graph()->inlined_function_infos().size());
HInlinedFunctionInfo info(shared->start_position());
if (!shared->script()->IsUndefined(isolate())) {
Handle<Script> script(Script::cast(shared->script()), isolate());
@ -1392,7 +1392,7 @@ int HGraphBuilder::TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
os << String::cast(source_name)->ToCString().get() << ":";
}
os << shared->DebugName()->ToCString().get() << ") id{";
os << info_->optimization_id() << "," << inline_id << "} ---\n";
os << info_->optimization_id() << "," << inlining_id << "} ---\n";
{
DisallowHeapAllocation no_allocation;
int start = shared->start_position();
@ -1408,23 +1408,19 @@ int HGraphBuilder::TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
}
}
graph()->inlined_function_infos().push_back(info);
if (FLAG_hydrogen_track_positions && inline_id != 0) {
if (FLAG_hydrogen_track_positions &&
inlining_id != SourcePosition::kNotInlined) {
CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
OFStream os(tracing_scope.file());
os << "INLINE (" << shared->DebugName()->ToCString().get() << ") id{"
<< info_->optimization_id() << "," << inline_id << "} AS " << inline_id
<< " AT " << position << std::endl;
<< info_->optimization_id() << "," << inlining_id << "} AS "
<< inlining_id << " AT " << position.ScriptOffset() << std::endl;
}
return inline_id;
}
HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
DCHECK(current_block() != NULL);
DCHECK(!FLAG_hydrogen_track_positions ||
!position_.IsUnknown() ||
DCHECK(!FLAG_hydrogen_track_positions || position_.IsKnown() ||
!info_->IsOptimizing());
current_block()->AddInstruction(instr, source_position());
if (graph()->IsInsideNoSideEffectsScope()) {
@ -1435,9 +1431,8 @@ HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) {
DCHECK(!FLAG_hydrogen_track_positions ||
!info_->IsOptimizing() ||
!position_.IsUnknown());
DCHECK(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() ||
position_.IsKnown());
current_block()->Finish(last, source_position());
if (last->IsReturn() || last->IsAbnormalExit()) {
set_current_block(NULL);
@ -1447,7 +1442,7 @@ void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) {
void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) {
DCHECK(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() ||
!position_.IsUnknown());
position_.IsKnown());
current_block()->FinishExit(instruction, source_position());
if (instruction->IsReturn() || instruction->IsAbnormalExit()) {
set_current_block(NULL);
@ -3126,7 +3121,7 @@ HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info,
bool track_positions)
: HGraphBuilder(info, CallInterfaceDescriptor(), track_positions),
function_state_(NULL),
initial_function_state_(this, info, NORMAL_RETURN, 0,
initial_function_state_(this, info, NORMAL_RETURN, -1,
TailCallMode::kAllow),
ast_context_(NULL),
break_scope_(NULL),
@ -3242,8 +3237,7 @@ HGraph::HGraph(CompilationInfo* info, CallInterfaceDescriptor descriptor)
type_change_checksum_(0),
maximum_environment_size_(0),
no_side_effects_scope_count_(0),
disallow_adding_new_values_(false),
inlined_function_infos_(info->zone()) {
disallow_adding_new_values_(false) {
if (info->IsStub()) {
// For stubs, explicitly add the context to the environment.
start_environment_ =
@ -3275,14 +3269,6 @@ void HGraph::FinalizeUniqueness() {
}
int HGraph::SourcePositionToScriptPosition(SourcePosition pos) {
return (FLAG_hydrogen_track_positions && !pos.IsUnknown())
? inlined_function_infos_.at(pos.inlining_id()).start_position +
pos.position()
: pos.raw();
}
// 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
@ -3707,9 +3693,7 @@ FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
if (owner->is_tracking_positions()) {
outer_source_position_ = owner->source_position();
owner->EnterInlinedSource(
info->shared_info()->start_position(),
inlining_id);
owner->EnterInlinedSource(inlining_id);
owner->SetSourcePosition(info->shared_info()->start_position());
}
}
@ -3721,9 +3705,7 @@ FunctionState::~FunctionState() {
if (owner_->is_tracking_positions()) {
owner_->set_source_position(outer_source_position_);
owner_->EnterInlinedSource(
outer_->compilation_info()->shared_info()->start_position(),
outer_->inlining_id());
owner_->EnterInlinedSource(outer_->inlining_id());
}
}
@ -8162,7 +8144,8 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
// Remember that we inlined this function. This needs to be called right
// after the EnsureDeoptimizationSupport call so that the code flusher
// does not remove the code with the deoptimization support.
top_info()->AddInlinedFunction(target_info.shared_info());
int inlining_id = top_info()->AddInlinedFunction(target_info.shared_info(),
source_position());
// ----------------------------------------------------------------
// After this point, we've made a decision to inline this function (so
@ -8178,9 +8161,8 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
&bounds_)
.Run();
int inlining_id = 0;
if (is_tracking_positions()) {
inlining_id = TraceInlinedFunction(target_shared, source_position());
TraceInlinedFunction(target_shared, source_position(), inlining_id);
}
// Save the pending call context. Set up new one for the inlined function.
@ -8231,6 +8213,7 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
if (is_tracking_positions()) {
enter_inlined->set_inlining_id(inlining_id);
}
function_state()->set_entry(enter_inlined);
VisitDeclarations(target_info.scope()->declarations());
@ -11136,12 +11119,6 @@ void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
BuildBinaryOperation(expr, left, right,
ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
: PUSH_BEFORE_SIMULATE);
if (is_tracking_positions() && result->IsBinaryOperation()) {
HBinaryOperation::cast(result)->SetOperandPositions(
zone(),
ScriptPositionToSourcePosition(expr->left()->position()),
ScriptPositionToSourcePosition(expr->right()->position()));
}
return ast_context()->ReturnValue(result);
}
@ -11321,10 +11298,6 @@ HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
AddCheckMap(operand_to_check, map);
HCompareObjectEqAndBranch* result =
New<HCompareObjectEqAndBranch>(left, right);
if (is_tracking_positions()) {
result->set_operand_position(zone(), 0, left_position);
result->set_operand_position(zone(), 1, right_position);
}
return result;
} else {
BuildCheckHeapObject(operand_to_check);
@ -11464,9 +11437,6 @@ HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
HCompareNumericAndBranch* result =
New<HCompareNumericAndBranch>(left, right, op);
result->set_observed_input_representation(left_rep, right_rep);
if (is_tracking_positions()) {
result->SetOperandPositions(zone(), left_position, right_position);
}
return result;
}
}
@ -12835,11 +12805,11 @@ void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
PrintIndent();
std::ostringstream os;
os << "0 " << uses << " " << NameOf(instruction) << " " << *instruction;
if (instruction->has_position() && instruction->position().raw() != 0) {
if (instruction->has_position()) {
const SourcePosition pos = instruction->position();
os << " pos:";
if (pos.inlining_id() != 0) os << pos.inlining_id() << "_";
os << pos.position();
if (pos.isInlined()) os << "inlining(" << pos.InliningId() << "),";
os << pos.ScriptOffset();
}
os << " <|@\n";
trace_.Add(os.str().c_str());

View File

@ -318,12 +318,6 @@ class HLoopInformation final : public ZoneObject {
HStackCheck* stack_check_;
};
struct HInlinedFunctionInfo {
explicit HInlinedFunctionInfo(int start_position)
: start_position(start_position) {}
int start_position;
};
class HGraph final : public ZoneObject {
public:
explicit HGraph(CompilationInfo* info, CallInterfaceDescriptor descriptor);
@ -475,14 +469,6 @@ class HGraph final : public ZoneObject {
int TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
SourcePosition position);
// Converts given SourcePosition to the absolute offset from the start of
// the corresponding script.
int SourcePositionToScriptPosition(SourcePosition position);
ZoneVector<HInlinedFunctionInfo>& inlined_function_infos() {
return inlined_function_infos_;
}
private:
HConstant* ReinsertConstantIfNecessary(HConstant* constant);
HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
@ -528,8 +514,6 @@ class HGraph final : public ZoneObject {
int no_side_effects_scope_count_;
bool disallow_adding_new_values_;
ZoneVector<HInlinedFunctionInfo> inlined_function_infos_;
DISALLOW_COPY_AND_ASSIGN(HGraph);
};
@ -1073,7 +1057,6 @@ class HGraphBuilder {
current_block_(NULL),
scope_(info->scope()),
position_(SourcePosition::Unknown()),
start_position_(0),
track_positions_(track_positions) {}
virtual ~HGraphBuilder() {}
@ -1844,28 +1827,25 @@ class HGraphBuilder {
protected:
void SetSourcePosition(int position) {
if (position != kNoSourcePosition) {
position_.set_position(position - start_position_);
position_.SetScriptOffset(position);
}
// Otherwise position remains unknown.
}
void EnterInlinedSource(int start_position, int id) {
void EnterInlinedSource(int inlining_id) {
if (is_tracking_positions()) {
start_position_ = start_position;
position_.set_inlining_id(id);
position_.SetInliningId(inlining_id);
}
}
// Convert the given absolute offset from the start of the script to
// the SourcePosition assuming that this position corresponds to the
// same function as current position_.
// same function as position_.
SourcePosition ScriptPositionToSourcePosition(int position) {
if (position == kNoSourcePosition) {
return SourcePosition::Unknown();
}
SourcePosition pos = position_;
pos.set_position(position - start_position_);
return pos;
return SourcePosition(position, position_.InliningId());
}
SourcePosition source_position() { return position_; }
@ -1873,8 +1853,8 @@ class HGraphBuilder {
bool is_tracking_positions() { return track_positions_; }
int TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
SourcePosition position);
void TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
SourcePosition position, int inlining_id);
HValue* BuildAllocateEmptyArrayBuffer(HValue* byte_length);
template <typename ViewClass>
@ -1897,7 +1877,6 @@ class HGraphBuilder {
HBasicBlock* current_block_;
Scope* scope_;
SourcePosition position_;
int start_position_;
bool track_positions_;
};

View File

@ -327,8 +327,7 @@ bool LCodeGen::GenerateDeferredCode() {
HValue* value =
instructions_->at(code->instruction_index())->hydrogen_value();
RecordAndWritePosition(
chunk()->graph()->SourcePositionToScriptPosition(value->position()));
RecordAndWritePosition(value->position());
Comment(";;; <@%d,#%d> "
"-------------------- Deferred %s --------------------",

View File

@ -2414,7 +2414,6 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
inner->BindContext(instr->closure_context());
inner->set_entry(instr);
current_block_->UpdateEnvironment(inner);
chunk_->AddInlinedFunction(instr->shared());
return NULL;
}

View File

@ -103,9 +103,8 @@ bool LCodeGenBase::GenerateBody() {
GenerateBodyInstructionPre(instr);
HValue* value = instr->hydrogen_value();
if (!value->position().IsUnknown()) {
RecordAndWritePosition(
chunk()->graph()->SourcePositionToScriptPosition(value->position()));
if (value->position().IsKnown()) {
RecordAndWritePosition(value->position());
}
instr->CompileToNative(codegen);
@ -141,8 +140,8 @@ void LCodeGenBase::CheckEnvironmentUsage() {
#endif
}
void LCodeGenBase::RecordAndWritePosition(int pos) {
if (pos == kNoSourcePosition) return;
void LCodeGenBase::RecordAndWritePosition(SourcePosition pos) {
if (!pos.IsKnown()) return;
source_position_table_builder_.AddPosition(masm_->pc_offset(), pos, false);
}
@ -167,8 +166,7 @@ void LCodeGenBase::Comment(const char* format, ...) {
void LCodeGenBase::DeoptComment(const Deoptimizer::DeoptInfo& deopt_info) {
SourcePosition position = deopt_info.position;
int deopt_id = deopt_info.deopt_id;
int raw_position = position.IsUnknown() ? 0 : position.raw();
masm()->RecordDeoptReason(deopt_info.deopt_reason, raw_position, deopt_id);
masm()->RecordDeoptReason(deopt_info.deopt_reason, position, deopt_id);
}
@ -311,6 +309,26 @@ void LCodeGenBase::WriteTranslationFrame(LEnvironment* environment,
}
}
namespace {
Handle<PodArray<InliningPosition>> CreateInliningPositions(
CompilationInfo* info) {
const CompilationInfo::InlinedFunctionList& inlined_functions =
info->inlined_functions();
if (inlined_functions.size() == 0) {
return Handle<PodArray<InliningPosition>>::cast(
info->isolate()->factory()->empty_byte_array());
}
Handle<PodArray<InliningPosition>> inl_positions =
PodArray<InliningPosition>::New(
info->isolate(), static_cast<int>(inlined_functions.size()), TENURED);
for (size_t i = 0; i < inlined_functions.size(); ++i) {
inl_positions->set(static_cast<int>(i), inlined_functions[i].position);
}
return inl_positions;
}
} // namespace
void LCodeGenBase::PopulateDeoptimizationData(Handle<Code> code) {
int length = deoptimizations_.length();
@ -342,6 +360,9 @@ void LCodeGenBase::PopulateDeoptimizationData(Handle<Code> code) {
data->SetLiteralArray(*literals);
}
Handle<PodArray<InliningPosition>> inl_pos = CreateInliningPositions(info_);
data->SetInliningPositions(*inl_pos);
data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id().ToInt()));
data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_));
@ -360,16 +381,22 @@ void LCodeGenBase::PopulateDeoptimizationData(Handle<Code> code) {
void LCodeGenBase::PopulateDeoptimizationLiteralsWithInlinedFunctions() {
DCHECK_EQ(0, deoptimization_literals_.length());
for (Handle<SharedFunctionInfo> function : chunk()->inlined_functions()) {
DefineDeoptimizationLiteral(function);
for (CompilationInfo::InlinedFunctionHolder& inlined :
info()->inlined_functions()) {
if (!inlined.shared_info.is_identical_to(info()->shared_info())) {
inlined.RegisterInlinedFunctionId(deoptimization_literals_.length());
DefineDeoptimizationLiteral(inlined.shared_info);
}
}
inlined_function_count_ = deoptimization_literals_.length();
// Define deoptimization literals for all unoptimized code objects of inlined
// functions. This ensures unoptimized code is kept alive by optimized code.
AllowDeferredHandleDereference allow_shared_function_info_dereference;
for (Handle<SharedFunctionInfo> function : chunk()->inlined_functions()) {
DefineDeoptimizationLiteral(handle(function->code()));
for (const CompilationInfo::InlinedFunctionHolder& inlined :
info()->inlined_functions()) {
if (!inlined.shared_info.is_identical_to(info()->shared_info())) {
DefineDeoptimizationLiteral(inlined.inlined_code_object_root);
}
}
}

View File

@ -50,7 +50,7 @@ class LCodeGenBase BASE_EMBEDDED {
virtual void GenerateBodyInstructionPost(LInstruction* instr) {}
virtual void EnsureSpaceForLazyDeopt(int space_needed) = 0;
void RecordAndWritePosition(int position);
void RecordAndWritePosition(SourcePosition position);
int GetNextEmittedBlock() const;

View File

@ -261,7 +261,6 @@ LChunk::LChunk(CompilationInfo* info, HGraph* graph)
graph_(graph),
instructions_(32, info->zone()),
pointer_maps_(8, info->zone()),
inlined_functions_(1, info->zone()),
deprecation_dependencies_(32, info->zone()),
stability_dependencies_(8, info->zone()) {}

View File

@ -660,14 +660,6 @@ class LChunk : public ZoneObject {
int LookupDestination(int block_id) const;
Label* GetAssemblyLabel(int block_id) const;
const ZoneList<Handle<SharedFunctionInfo>>& inlined_functions() const {
return inlined_functions_;
}
void AddInlinedFunction(Handle<SharedFunctionInfo> closure) {
inlined_functions_.Add(closure, zone());
}
void AddDeprecationDependency(Handle<Map> map) {
DCHECK(!map->is_deprecated());
if (!map->CanBeDeprecated()) return;
@ -705,7 +697,6 @@ class LChunk : public ZoneObject {
BitVector* allocated_double_registers_;
ZoneList<LInstruction*> instructions_;
ZoneList<LPointerMap*> pointer_maps_;
ZoneList<Handle<SharedFunctionInfo>> inlined_functions_;
ZoneList<Handle<Map>> deprecation_dependencies_;
ZoneList<Handle<Map>> stability_dependencies_;
};

View File

@ -286,8 +286,7 @@ bool LCodeGen::GenerateDeferredCode() {
HValue* value =
instructions_->at(code->instruction_index())->hydrogen_value();
RecordAndWritePosition(
chunk()->graph()->SourcePositionToScriptPosition(value->position()));
RecordAndWritePosition(value->position());
Comment(";;; <@%d,#%d> "
"-------------------- Deferred %s --------------------",

View File

@ -2291,7 +2291,6 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
inner->BindContext(instr->closure_context());
inner->set_entry(instr);
current_block_->UpdateEnvironment(inner);
chunk_->AddInlinedFunction(instr->shared());
return NULL;
}

View File

@ -262,8 +262,7 @@ bool LCodeGen::GenerateDeferredCode() {
HValue* value =
instructions_->at(code->instruction_index())->hydrogen_value();
RecordAndWritePosition(
chunk()->graph()->SourcePositionToScriptPosition(value->position()));
RecordAndWritePosition(value->position());
Comment(";;; <@%d,#%d> "
"-------------------- Deferred %s --------------------",

View File

@ -2296,7 +2296,6 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
inner->BindContext(instr->closure_context());
inner->set_entry(instr);
current_block_->UpdateEnvironment(inner);
chunk_->AddInlinedFunction(instr->shared());
return NULL;
}

View File

@ -270,8 +270,7 @@ bool LCodeGen::GenerateDeferredCode() {
HValue* value =
instructions_->at(code->instruction_index())->hydrogen_value();
RecordAndWritePosition(
chunk()->graph()->SourcePositionToScriptPosition(value->position()));
RecordAndWritePosition(value->position());
Comment(
";;; <@%d,#%d> "

View File

@ -2313,7 +2313,6 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
inner->BindContext(instr->closure_context());
inner->set_entry(instr);
current_block_->UpdateEnvironment(inner);
chunk_->AddInlinedFunction(instr->shared());
return NULL;
}

View File

@ -258,8 +258,7 @@ bool LCodeGen::GenerateDeferredCode() {
HValue* value =
instructions_->at(code->instruction_index())->hydrogen_value();
RecordAndWritePosition(
chunk()->graph()->SourcePositionToScriptPosition(value->position()));
RecordAndWritePosition(value->position());
Comment(
";;; <@%d,#%d> "

View File

@ -2123,7 +2123,6 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
inner->BindContext(instr->closure_context());
inner->set_entry(instr);
current_block_->UpdateEnvironment(inner);
chunk_->AddInlinedFunction(instr->shared());
return NULL;
}

View File

@ -356,8 +356,7 @@ bool LCodeGen::GenerateDeferredCode() {
HValue* value =
instructions_->at(code->instruction_index())->hydrogen_value();
RecordAndWritePosition(
chunk()->graph()->SourcePositionToScriptPosition(value->position()));
RecordAndWritePosition(value->position());
Comment(";;; <@%d,#%d> "
"-------------------- Deferred %s --------------------",

View File

@ -2416,7 +2416,6 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
inner->BindContext(instr->closure_context());
inner->set_entry(instr);
current_block_->UpdateEnvironment(inner);
chunk_->AddInlinedFunction(instr->shared());
return NULL;
}

View File

@ -330,8 +330,7 @@ bool LCodeGen::GenerateDeferredCode() {
HValue* value =
instructions_->at(code->instruction_index())->hydrogen_value();
RecordAndWritePosition(
chunk()->graph()->SourcePositionToScriptPosition(value->position()));
RecordAndWritePosition(value->position());
Comment(";;; <@%d,#%d> "
"-------------------- Deferred %s --------------------",

View File

@ -2416,7 +2416,6 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
inner->BindContext(instr->closure_context());
inner->set_entry(instr);
current_block_->UpdateEnvironment(inner);
chunk_->AddInlinedFunction(instr->shared());
return NULL;
}

View File

@ -211,7 +211,7 @@ void CodeBreakIterator::Next() {
int offset = code_offset();
while (!source_position_iterator_.done() &&
source_position_iterator_.code_offset() <= offset) {
position_ = source_position_iterator_.source_position();
position_ = source_position_iterator_.source_position().ScriptOffset();
if (source_position_iterator_.is_statement()) {
statement_position_ = position_;
}
@ -295,7 +295,7 @@ void BytecodeArrayBreakIterator::Next() {
if (!first) source_position_iterator_.Advance();
first = false;
if (Done()) return;
position_ = source_position_iterator_.source_position();
position_ = source_position_iterator_.source_position().ScriptOffset();
if (source_position_iterator_.is_statement()) {
statement_position_ = position_;
}

View File

@ -1111,9 +1111,10 @@ void TranslateSourcePositionTable(Handle<AbstractCode> code,
Handle<ByteArray> source_position_table(code->source_position_table());
for (SourcePositionTableIterator iterator(*source_position_table);
!iterator.done(); iterator.Advance()) {
int position = iterator.source_position();
int new_position = TranslatePosition(position, position_change_array);
builder.AddPosition(iterator.code_offset(), new_position,
SourcePosition position = iterator.source_position();
position.SetScriptOffset(
TranslatePosition(position.ScriptOffset(), position_change_array));
builder.AddPosition(iterator.code_offset(), position,
iterator.is_statement());
}

View File

@ -2727,16 +2727,19 @@ Deoptimizer::DeoptInfo Deoptimizer::GetDeoptInfo(Code* code, Address pc) {
int last_deopt_id = kNoDeoptimizationId;
int mask = RelocInfo::ModeMask(RelocInfo::DEOPT_REASON) |
RelocInfo::ModeMask(RelocInfo::DEOPT_ID) |
RelocInfo::ModeMask(RelocInfo::DEOPT_POSITION);
RelocInfo::ModeMask(RelocInfo::DEOPT_SCRIPT_OFFSET) |
RelocInfo::ModeMask(RelocInfo::DEOPT_INLINING_ID);
for (RelocIterator it(code, mask); !it.done(); it.next()) {
RelocInfo* info = it.rinfo();
if (info->pc() >= pc) {
return DeoptInfo(last_position, last_reason, last_deopt_id);
}
if (info->rmode() == RelocInfo::DEOPT_POSITION) {
int raw_position = static_cast<int>(info->data());
last_position = raw_position ? SourcePosition::FromRaw(raw_position)
: SourcePosition::Unknown();
if (info->rmode() == RelocInfo::DEOPT_SCRIPT_OFFSET) {
int script_offset = static_cast<int>(info->data());
it.next();
DCHECK(it.rinfo()->rmode() == RelocInfo::DEOPT_INLINING_ID);
int inlining_id = static_cast<int>(it.rinfo()->data());
last_position = SourcePosition(script_offset, inlining_id);
} else if (info->rmode() == RelocInfo::DEOPT_ID) {
last_deopt_id = static_cast<int>(info->data());
} else if (info->rmode() == RelocInfo::DEOPT_REASON) {

View File

@ -172,8 +172,11 @@ static int DecodeIt(Isolate* isolate, std::ostream* os,
}
RelocInfo::Mode rmode = relocinfo.rmode();
if (rmode == RelocInfo::DEOPT_POSITION) {
out.AddFormatted(" ;; debug: deopt position '%d'",
if (rmode == RelocInfo::DEOPT_SCRIPT_OFFSET) {
out.AddFormatted(" ;; debug: deopt position, script offset '%d'",
static_cast<int>(relocinfo.data()));
} else if (rmode == RelocInfo::DEOPT_INLINING_ID) {
out.AddFormatted(" ;; debug: deopt position, inlining id '%d'",
static_cast<int>(relocinfo.data()));
} else if (rmode == RelocInfo::DEOPT_REASON) {
DeoptimizeReason reason =

View File

@ -665,12 +665,14 @@ void FullCodeGenerator::EmitHasProperty() {
void FullCodeGenerator::RecordStatementPosition(int pos) {
DCHECK_NE(kNoSourcePosition, pos);
source_position_table_builder_.AddPosition(masm_->pc_offset(), pos, true);
source_position_table_builder_.AddPosition(masm_->pc_offset(),
SourcePosition(pos), true);
}
void FullCodeGenerator::RecordPosition(int pos) {
DCHECK_NE(kNoSourcePosition, pos);
source_position_table_builder_.AddPosition(masm_->pc_offset(), pos, false);
source_position_table_builder_.AddPosition(masm_->pc_offset(),
SourcePosition(pos), false);
}

View File

@ -1446,7 +1446,8 @@ class Assembler : public AssemblerBase {
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(DeoptimizeReason reason, int raw_position, int id);
void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
int id);
// Writes a single byte or word of data in the code stream. Used for
// inline tables, e.g., jump-tables.

View File

@ -94,9 +94,9 @@ void BytecodeArrayWriter::UpdateSourcePositionTable(
int bytecode_offset = static_cast<int>(bytecodes()->size());
const BytecodeSourceInfo& source_info = node->source_info();
if (source_info.is_valid()) {
source_position_table_builder()->AddPosition(bytecode_offset,
source_info.source_position(),
source_info.is_statement());
source_position_table_builder()->AddPosition(
bytecode_offset, SourcePosition(source_info.source_position()),
source_info.is_statement());
}
}

View File

@ -634,7 +634,7 @@ class CaptureStackTraceHelper {
if (!line_key_.is_null()) {
Script::PositionInfo info;
bool valid_pos =
script->GetPositionInfo(position, &info, Script::WITH_OFFSET);
Script::GetPositionInfo(script, position, &info, Script::WITH_OFFSET);
if (!column_key_.is_null() && valid_pos) {
JSObject::AddProperty(stack_frame, column_key_,
@ -2270,7 +2270,6 @@ void Isolate::Deinit() {
delete interpreter_;
interpreter_ = NULL;
delete compiler_dispatcher_tracer_;
compiler_dispatcher_tracer_ = nullptr;

View File

@ -1149,12 +1149,13 @@ void Logger::CodeLinePosInfoRecordEvent(AbstractCode* code,
iter.Advance()) {
if (iter.is_statement()) {
jit_logger_->AddCodeLinePosInfoEvent(
jit_handler_data, iter.code_offset(), iter.source_position(),
jit_handler_data, iter.code_offset(),
iter.source_position().ScriptOffset(),
JitCodeEvent::STATEMENT_POSITION);
}
jit_logger_->AddCodeLinePosInfoEvent(jit_handler_data, iter.code_offset(),
iter.source_position(),
JitCodeEvent::POSITION);
jit_logger_->AddCodeLinePosInfoEvent(
jit_handler_data, iter.code_offset(),
iter.source_position().ScriptOffset(), JitCodeEvent::POSITION);
}
jit_logger_->EndCodePosInfoEvent(code, jit_handler_data);
}

View File

@ -367,8 +367,8 @@ MaybeHandle<String> FormatEvalOrigin(Isolate* isolate, Handle<Script> script) {
builder.AppendString(Handle<String>::cast(name_obj));
Script::PositionInfo info;
if (eval_from_script->GetPositionInfo(script->GetEvalPosition(), &info,
Script::NO_OFFSET)) {
if (Script::GetPositionInfo(eval_from_script, script->GetEvalPosition(),
&info, Script::NO_OFFSET)) {
builder.AppendCString(":");
Handle<String> str = isolate->factory()->NumberToString(

View File

@ -1055,7 +1055,8 @@ class Assembler : public AssemblerBase {
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(DeoptimizeReason reason, int raw_position, int id);
void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
int id);
static int RelocateInternalReference(RelocInfo::Mode rmode, byte* pc,
intptr_t pc_delta);

View File

@ -1117,7 +1117,8 @@ class Assembler : public AssemblerBase {
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(DeoptimizeReason reason, int raw_position, int id);
void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
int id);
static int RelocateInternalReference(RelocInfo::Mode rmode, byte* pc,
intptr_t pc_delta);

View File

@ -3371,6 +3371,24 @@ CAST_ACCESSOR(WeakCell)
CAST_ACCESSOR(WeakFixedArray)
CAST_ACCESSOR(WeakHashTable)
template <class T>
PodArray<T>* PodArray<T>::cast(Object* object) {
SLOW_DCHECK(object->IsByteArray());
return reinterpret_cast<PodArray<T>*>(object);
}
template <class T>
const PodArray<T>* PodArray<T>::cast(const Object* object) {
SLOW_DCHECK(object->IsByteArray());
return reinterpret_cast<const PodArray<T>*>(object);
}
// static
template <class T>
Handle<PodArray<T>> PodArray<T>::New(Isolate* isolate, int length,
PretenureFlag pretenure) {
return Handle<PodArray<T>>::cast(
isolate->factory()->NewByteArray(length * sizeof(T), pretenure));
}
// static
template <class Traits>
@ -3413,6 +3431,7 @@ DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrPcOffset, Smi)
DEFINE_DEOPT_ELEMENT_ACCESSORS(OptimizationId, Smi)
DEFINE_DEOPT_ELEMENT_ACCESSORS(SharedFunctionInfo, Object)
DEFINE_DEOPT_ELEMENT_ACCESSORS(WeakCellCache, Object)
DEFINE_DEOPT_ELEMENT_ACCESSORS(InliningPositions, PodArray<InliningPosition>)
#undef DEFINE_DEOPT_ELEMENT_ACCESSORS

View File

@ -13418,72 +13418,107 @@ void Script::InitLineEnds(Handle<Script> script) {
DCHECK(script->line_ends()->IsFixedArray());
}
bool Script::GetPositionInfo(Handle<Script> script, int position,
PositionInfo* info, OffsetFlag offset_flag) {
InitLineEnds(script);
return script->GetPositionInfo(position, info, offset_flag);
}
namespace {
bool GetPositionInfoSlow(const Script* script, int position,
Script::PositionInfo* info) {
if (!script->source()->IsString()) return false;
if (position < 0) position = 0;
String* source_string = String::cast(script->source());
int line = 0;
int line_start = 0;
int len = source_string->length();
for (int pos = 0; pos <= len; ++pos) {
if (pos == len || source_string->Get(pos) == '\n') {
if (position <= pos) {
info->line = line;
info->column = position - line_start;
info->line_start = line_start;
info->line_end = pos;
return true;
}
line++;
line_start = pos + 1;
}
}
return false;
}
} // namespace
#define SMI_VALUE(x) (Smi::cast(x)->value())
bool Script::GetPositionInfo(int position, PositionInfo* info,
OffsetFlag offset_flag) {
Handle<Script> script(this);
InitLineEnds(script);
OffsetFlag offset_flag) const {
DisallowHeapAllocation no_allocation;
DCHECK(script->line_ends()->IsFixedArray());
FixedArray* ends = FixedArray::cast(script->line_ends());
const int ends_len = ends->length();
if (ends_len == 0) return false;
// Return early on invalid positions. Negative positions behave as if 0 was
// passed, and positions beyond the end of the script return as failure.
if (position < 0) {
position = 0;
} else if (position > SMI_VALUE(ends->get(ends_len - 1))) {
return false;
}
// Determine line number by doing a binary search on the line ends array.
if (SMI_VALUE(ends->get(0)) >= position) {
info->line = 0;
info->line_start = 0;
info->column = position;
if (line_ends()->IsUndefined(GetIsolate())) {
// Slow mode: we do not have line_ends. We have to iterate through source.
if (!GetPositionInfoSlow(this, position, info)) return false;
} else {
int left = 0;
int right = ends_len - 1;
DCHECK(line_ends()->IsFixedArray());
FixedArray* ends = FixedArray::cast(line_ends());
while (right > 0) {
DCHECK_LE(left, right);
const int mid = (left + right) / 2;
if (position > SMI_VALUE(ends->get(mid))) {
left = mid + 1;
} else if (position <= SMI_VALUE(ends->get(mid - 1))) {
right = mid - 1;
} else {
info->line = mid;
break;
}
const int ends_len = ends->length();
if (ends_len == 0) return false;
// Return early on invalid positions. Negative positions behave as if 0 was
// passed, and positions beyond the end of the script return as failure.
if (position < 0) {
position = 0;
} else if (position > SMI_VALUE(ends->get(ends_len - 1))) {
return false;
}
DCHECK(SMI_VALUE(ends->get(info->line)) >= position &&
SMI_VALUE(ends->get(info->line - 1)) < position);
info->line_start = SMI_VALUE(ends->get(info->line - 1)) + 1;
info->column = position - info->line_start;
}
// Line end is position of the linebreak character.
info->line_end = SMI_VALUE(ends->get(info->line));
if (info->line_end > 0) {
DCHECK(script->source()->IsString());
Handle<String> src(String::cast(script->source()));
if (src->length() >= info->line_end &&
src->Get(info->line_end - 1) == '\r') {
info->line_end--;
// Determine line number by doing a binary search on the line ends array.
if (SMI_VALUE(ends->get(0)) >= position) {
info->line = 0;
info->line_start = 0;
info->column = position;
} else {
int left = 0;
int right = ends_len - 1;
while (right > 0) {
DCHECK_LE(left, right);
const int mid = (left + right) / 2;
if (position > SMI_VALUE(ends->get(mid))) {
left = mid + 1;
} else if (position <= SMI_VALUE(ends->get(mid - 1))) {
right = mid - 1;
} else {
info->line = mid;
break;
}
}
DCHECK(SMI_VALUE(ends->get(info->line)) >= position &&
SMI_VALUE(ends->get(info->line - 1)) < position);
info->line_start = SMI_VALUE(ends->get(info->line - 1)) + 1;
info->column = position - info->line_start;
}
// Line end is position of the linebreak character.
info->line_end = SMI_VALUE(ends->get(info->line));
if (info->line_end > 0) {
DCHECK(source()->IsString());
String* src = String::cast(source());
if (src->length() >= info->line_end &&
src->Get(info->line_end - 1) == '\r') {
info->line_end--;
}
}
}
// Add offsets if requested.
if (offset_flag == WITH_OFFSET) {
if (info->line == 0) {
info->column += script->column_offset();
info->column += column_offset();
}
info->line += script->line_offset();
info->line += line_offset();
}
return true;
@ -13492,49 +13527,28 @@ bool Script::GetPositionInfo(int position, PositionInfo* info,
int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
PositionInfo info;
if (!script->GetPositionInfo(code_pos, &info, WITH_OFFSET)) {
return -1;
}
GetPositionInfo(script, code_pos, &info, WITH_OFFSET);
return info.column;
}
int Script::GetLineNumberWithArray(int code_pos) {
int Script::GetColumnNumber(int code_pos) const {
PositionInfo info;
if (!GetPositionInfo(code_pos, &info, WITH_OFFSET)) {
return -1;
}
GetPositionInfo(code_pos, &info, WITH_OFFSET);
return info.column;
}
int Script::GetLineNumber(Handle<Script> script, int code_pos) {
PositionInfo info;
GetPositionInfo(script, code_pos, &info, WITH_OFFSET);
return info.line;
}
int Script::GetLineNumber(Handle<Script> script, int code_pos) {
InitLineEnds(script);
return script->GetLineNumberWithArray(code_pos);
int Script::GetLineNumber(int code_pos) const {
PositionInfo info;
GetPositionInfo(code_pos, &info, WITH_OFFSET);
return info.line;
}
int Script::GetLineNumber(int code_pos) {
DisallowHeapAllocation no_allocation;
if (!line_ends()->IsUndefined(GetIsolate())) {
return GetLineNumberWithArray(code_pos);
}
// Slow mode: we do not have line_ends. We have to iterate through source.
if (!source()->IsString()) return -1;
String* source_string = String::cast(source());
int line = 0;
int len = source_string->length();
for (int pos = 0; pos < len; pos++) {
if (pos == code_pos) break;
if (source_string->Get(pos) == '\n') line++;
}
return line;
}
Handle<Object> Script::GetNameOrSourceURL(Handle<Script> script) {
Isolate* isolate = script->GetIsolate();
@ -14290,7 +14304,7 @@ int AbstractCode::SourcePosition(int offset) {
for (SourcePositionTableIterator iterator(source_position_table());
!iterator.done() && iterator.code_offset() <= offset;
iterator.Advance()) {
position = iterator.source_position();
position = iterator.source_position().ScriptOffset();
}
return position;
}
@ -14303,7 +14317,7 @@ int AbstractCode::SourceStatementPosition(int offset) {
for (SourcePositionTableIterator it(source_position_table()); !it.done();
it.Advance()) {
if (it.is_statement()) {
int p = it.source_position();
int p = it.source_position().ScriptOffset();
if (statement_position < p && p <= position) {
statement_position = p;
}
@ -14521,14 +14535,15 @@ Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) {
void Code::PrintDeoptLocation(FILE* out, Address pc) {
Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(this, pc);
class SourcePosition pos = info.position;
if (info.deopt_reason != DeoptimizeReason::kNoReason || !pos.IsUnknown()) {
if (info.deopt_reason != DeoptimizeReason::kNoReason || pos.IsKnown()) {
if (FLAG_hydrogen_track_positions) {
PrintF(out, " ;;; deoptimize at %d_%d: %s\n",
pos.inlining_id(), pos.position(),
DeoptimizeReasonToString(info.deopt_reason));
PrintF(out, " ;;; deoptimize at %d_%d: %s\n", pos.InliningId(),
pos.ScriptOffset(), DeoptimizeReasonToString(info.deopt_reason));
} else {
PrintF(out, " ;;; deoptimize at %d: %s\n", pos.raw(),
DeoptimizeReasonToString(info.deopt_reason));
PrintF(out, " ;;; deoptimize at ");
OFStream outstr(out);
pos.Print(outstr, this);
PrintF(out, ", %s\n", DeoptimizeReasonToString(info.deopt_reason));
}
}
}
@ -14967,8 +14982,8 @@ void Code::Disassemble(const char* name, std::ostream& os) { // NOLINT
os << "Source positions:\n pc offset position\n";
for (; !it.done(); it.Advance()) {
os << std::setw(10) << it.code_offset() << std::setw(10)
<< it.source_position() << (it.is_statement() ? " statement" : "")
<< "\n";
<< it.source_position().ScriptOffset()
<< (it.is_statement() ? " statement" : "") << "\n";
}
os << "\n";
}
@ -15070,7 +15085,7 @@ void BytecodeArray::Disassemble(std::ostream& os) {
while (!iterator.done()) {
if (!source_positions.done() &&
iterator.current_offset() == source_positions.code_offset()) {
os << std::setw(5) << source_positions.source_position();
os << std::setw(5) << source_positions.source_position().ScriptOffset();
os << (source_positions.is_statement() ? " S> " : " E> ");
source_positions.Advance();
} else {
@ -19411,7 +19426,8 @@ int JSMessageObject::GetLineNumber() const {
Script::PositionInfo info;
const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
if (!the_script->GetPositionInfo(start_position(), &info, offset_flag)) {
if (!Script::GetPositionInfo(the_script, start_position(), &info,
offset_flag)) {
return Message::kNoLineNumberInfo;
}
@ -19425,7 +19441,8 @@ int JSMessageObject::GetColumnNumber() const {
Script::PositionInfo info;
const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
if (!the_script->GetPositionInfo(start_position(), &info, offset_flag)) {
if (!Script::GetPositionInfo(the_script, start_position(), &info,
offset_flag)) {
return -1;
}
@ -19442,7 +19459,8 @@ Handle<String> JSMessageObject::GetSourceLine() const {
Script::PositionInfo info;
const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
if (!the_script->GetPositionInfo(start_position(), &info, offset_flag)) {
if (!Script::GetPositionInfo(the_script, start_position(), &info,
offset_flag)) {
return isolate->factory()->empty_string();
}

View File

@ -168,6 +168,8 @@
namespace v8 {
namespace internal {
struct InliningPosition;
enum KeyedAccessStoreMode {
STANDARD_STORE,
STORE_TRANSITION_TO_OBJECT,
@ -4901,6 +4903,32 @@ class ByteArray: public FixedArrayBase {
DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray);
};
// Wrapper class for ByteArray which can store arbitrary C++ classes, as long
// as they can be copied with memcpy.
template <class T>
class PodArray : public ByteArray {
public:
static Handle<PodArray<T>> New(Isolate* isolate, int length,
PretenureFlag pretenure = NOT_TENURED);
void copy_out(int index, T* result) {
ByteArray::copy_out(index * sizeof(T), reinterpret_cast<byte*>(result),
sizeof(T));
}
T get(int index) {
T result;
copy_out(index, &result);
return result;
}
void set(int index, const T& value) {
copy_in(index * sizeof(T), reinterpret_cast<const byte*>(&value),
sizeof(T));
}
int length() { return ByteArray::length() / sizeof(T); }
DECLARE_CAST(PodArray<T>)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PodArray<T>);
};
// BytecodeArray represents a sequence of interpreter bytecodes.
class BytecodeArray : public FixedArrayBase {
@ -5133,7 +5161,6 @@ TYPED_ARRAYS(FIXED_TYPED_ARRAY_TRAITS)
#undef FIXED_TYPED_ARRAY_TRAITS
// DeoptimizationInputData is a fixed array used to hold the deoptimization
// data for code generated by the Hydrogen/Lithium compiler. It also
// contains information about functions that were inlined. If N different
@ -5152,7 +5179,8 @@ class DeoptimizationInputData: public FixedArray {
static const int kOptimizationIdIndex = 5;
static const int kSharedFunctionInfoIndex = 6;
static const int kWeakCellCacheIndex = 7;
static const int kFirstDeoptEntryIndex = 8;
static const int kInliningPositionsIndex = 8;
static const int kFirstDeoptEntryIndex = 9;
// Offsets of deopt entry elements relative to the start of the entry.
static const int kAstIdRawOffset = 0;
@ -5174,6 +5202,7 @@ class DeoptimizationInputData: public FixedArray {
DECLARE_ELEMENT_ACCESSORS(OptimizationId, Smi)
DECLARE_ELEMENT_ACCESSORS(SharedFunctionInfo, Object)
DECLARE_ELEMENT_ACCESSORS(WeakCellCache, Object)
DECLARE_ELEMENT_ACCESSORS(InliningPositions, PodArray<InliningPosition>)
#undef DECLARE_ELEMENT_ACCESSORS
@ -5215,7 +5244,6 @@ class DeoptimizationInputData: public FixedArray {
static int LengthFor(int entry_count) { return IndexForEntry(entry_count); }
};
// DeoptimizationOutputData is a fixed array used to hold the deoptimization
// data for code generated by the full compiler.
// The format of the these objects is
@ -7103,14 +7131,6 @@ class Script: public Struct {
// Init line_ends array with source code positions of line ends.
static void InitLineEnds(Handle<Script> script);
// Convert code offset into column number.
static int GetColumnNumber(Handle<Script> script, int code_offset);
// Convert code offset into (zero-based) line number.
// The non-handlified version does not allocate, but may be much slower.
static int GetLineNumber(Handle<Script> script, int code_offset);
int GetLineNumber(int code_pos);
// Carries information about a source position.
struct PositionInfo {
PositionInfo() : line(-1), column(-1), line_start(-1), line_end(-1) {}
@ -7118,7 +7138,7 @@ class Script: public Struct {
int line; // Zero-based line number.
int column; // Zero-based column number.
int line_start; // Position of first character in line.
int line_end; // Position of last (non-linebreak) character in line.
int line_end; // Position of final linebreak character in line.
};
// Specifies whether to add offsets to position infos.
@ -7127,8 +7147,20 @@ class Script: public Struct {
// Retrieves information about the given position, optionally with an offset.
// Returns false on failure, and otherwise writes into the given info object
// on success.
// The static method should is preferable for handlified callsites because it
// initializes the line ends array, avoiding expensive recomputations.
// The non-static version is not allocating and safe for unhandlified
// callsites.
static bool GetPositionInfo(Handle<Script> script, int position,
PositionInfo* info, OffsetFlag offset_flag);
bool GetPositionInfo(int position, PositionInfo* info,
OffsetFlag offset_flag);
OffsetFlag offset_flag) const;
// Wrappers for GetPositionInfo
static int GetColumnNumber(Handle<Script> script, int code_offset);
int GetColumnNumber(int code_pos) const;
static int GetLineNumber(Handle<Script> script, int code_offset);
int GetLineNumber(int code_pos) const;
// Get the JS object wrapping the given script; create it if none exists.
static Handle<JSObject> GetWrapper(Handle<Script> script);
@ -7172,8 +7204,6 @@ class Script: public Struct {
static const int kSize = kSourceMappingUrlOffset + kPointerSize;
private:
int GetLineNumberWithArray(int code_pos);
// Bit positions in the flags field.
static const int kCompilationTypeBit = 0;
static const int kCompilationStateBit = 1;

View File

@ -299,7 +299,7 @@ void PerfJitLogger::LogWriteDebugInfo(Code* code, SharedFunctionInfo* shared) {
for (SourcePositionTableIterator iterator(code->source_position_table());
!iterator.done(); iterator.Advance()) {
int position = iterator.source_position();
int position = iterator.source_position().ScriptOffset();
int line_number = Script::GetLineNumber(script, position);
// Compute column.
int relative_line_number = line_number - script_line_offset;

View File

@ -1216,7 +1216,8 @@ class Assembler : public AssemblerBase {
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(DeoptimizeReason reason, int raw_position, int id);
void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
int id);
// Writes a single byte or word of data in the code stream. Used
// for inline tables, e.g., jump-tables.

View File

@ -123,7 +123,7 @@ class CodeEventsContainer {
CodeEventRecord generic;
#define DECLARE_CLASS(ignore, type) type type##_;
CODE_EVENTS_TYPE_LIST(DECLARE_CLASS)
#undef DECLARE_TYPE
#undef DECLARE_CLASS
};
};

View File

@ -181,17 +181,18 @@ CpuProfileDeoptInfo CodeEntry::GetDeoptInfo() {
CpuProfileDeoptInfo info;
info.deopt_reason = deopt_reason_;
DCHECK_NE(kNoDeoptimizationId, deopt_id_);
size_t position = static_cast<size_t>(deopt_position_.ScriptOffset());
if (deopt_inlined_frames_.find(deopt_id_) == deopt_inlined_frames_.end()) {
info.stack.push_back(CpuProfileDeoptFrame(
{script_id_, position_ + deopt_position_.position()}));
info.stack.push_back(CpuProfileDeoptFrame({script_id_, position}));
} else {
size_t deopt_position = deopt_position_.raw();
// Copy stack of inlined frames where the deopt happened.
std::vector<DeoptInlinedFrame>& frames = deopt_inlined_frames_[deopt_id_];
bool first = true;
for (DeoptInlinedFrame& inlined_frame : base::Reversed(frames)) {
info.stack.push_back(CpuProfileDeoptFrame(
{inlined_frame.script_id, deopt_position + inlined_frame.position}));
deopt_position = 0; // Done with innermost frame.
info.stack.push_back(
CpuProfileDeoptFrame({inlined_frame.script_id,
first ? position : inlined_frame.position}));
first = false; // Done with innermost frame.
}
}
return info;

View File

@ -94,7 +94,7 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
int end_position = shared->end_position();
for (SourcePositionTableIterator it(abstract_code->source_position_table());
!it.done(); it.Advance()) {
int position = it.source_position();
int position = it.source_position().ScriptOffset();
// TODO(alph): in case of inlining the position may correspond to an
// inlined function source code. Do not collect positions that fall
// beyond the function source code. There's however a chance the

View File

@ -1638,7 +1638,7 @@ static Handle<Object> GetJSPositionInfo(Handle<Script> script, int position,
Script::OffsetFlag offset_flag,
Isolate* isolate) {
Script::PositionInfo info;
if (!script->GetPositionInfo(position, &info, offset_flag)) {
if (!Script::GetPositionInfo(script, position, &info, offset_flag)) {
return isolate->factory()->null_value();
}
@ -1705,7 +1705,7 @@ Handle<Object> ScriptLocationFromLine(Isolate* isolate, Handle<Script> script,
position = offset + column;
} else {
Script::PositionInfo info;
if (!script->GetPositionInfo(offset, &info, Script::NO_OFFSET) ||
if (!Script::GetPositionInfo(script, offset, &info, Script::NO_OFFSET) ||
info.line + line >= line_count) {
return isolate->factory()->null_value();
}

View File

@ -1254,7 +1254,8 @@ class Assembler : public AssemblerBase {
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(DeoptimizeReason reason, int raw_position, int id);
void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
int id);
// Writes a single byte or word of data in the code stream. Used
// for inline tables, e.g., jump-tables.

View File

@ -47,17 +47,19 @@ void SubtractFromEntry(PositionTableEntry& value,
}
// Helper: Encode an integer.
void EncodeInt(ZoneVector<byte>& bytes, int value) {
template <typename T>
void EncodeInt(ZoneVector<byte>& bytes, T value) {
// Zig-zag encoding.
static const int kShift = kIntSize * kBitsPerByte - 1;
static const int kShift = sizeof(T) * kBitsPerByte - 1;
value = ((value << 1) ^ (value >> kShift));
DCHECK_GE(value, 0);
unsigned int encoded = static_cast<unsigned int>(value);
auto encoded = static_cast<typename std::make_unsigned<T>::type>(value);
bool more;
do {
more = encoded > ValueBits::kMax;
bytes.push_back(MoreBit::encode(more) |
ValueBits::encode(encoded & ValueBits::kMask));
byte current =
MoreBit::encode(more) | ValueBits::encode(encoded & ValueBits::kMask);
bytes.push_back(current);
encoded >>= ValueBits::kSize;
} while (more);
}
@ -73,25 +75,27 @@ void EncodeEntry(ZoneVector<byte>& bytes, const PositionTableEntry& entry) {
}
// Helper: Decode an integer.
void DecodeInt(ByteArray* bytes, int* index, int* v) {
template <typename T>
T DecodeInt(ByteArray* bytes, int* index) {
byte current;
int shift = 0;
int decoded = 0;
T decoded = 0;
bool more;
do {
current = bytes->get((*index)++);
decoded |= ValueBits::decode(current) << shift;
decoded |= static_cast<typename std::make_unsigned<T>::type>(
ValueBits::decode(current))
<< shift;
more = MoreBit::decode(current);
shift += ValueBits::kSize;
} while (more);
DCHECK_GE(decoded, 0);
decoded = (decoded >> 1) ^ (-(decoded & 1));
*v = decoded;
return decoded;
}
void DecodeEntry(ByteArray* bytes, int* index, PositionTableEntry* entry) {
int tmp;
DecodeInt(bytes, index, &tmp);
int tmp = DecodeInt<int>(bytes, index);
if (tmp >= 0) {
entry->is_statement = true;
entry->code_offset = tmp;
@ -99,7 +103,7 @@ void DecodeEntry(ByteArray* bytes, int* index, PositionTableEntry* entry) {
entry->is_statement = false;
entry->code_offset = -(tmp + 1);
}
DecodeInt(bytes, index, &entry->source_position);
entry->source_position = DecodeInt<int64_t>(bytes, index);
}
} // namespace
@ -115,11 +119,12 @@ SourcePositionTableBuilder::SourcePositionTableBuilder(
}
void SourcePositionTableBuilder::AddPosition(size_t code_offset,
int source_position,
SourcePosition source_position,
bool is_statement) {
if (Omit()) return;
DCHECK(source_position.IsKnown());
int offset = static_cast<int>(code_offset);
AddEntry({offset, source_position, is_statement});
AddEntry({offset, source_position.raw(), is_statement});
}
void SourcePositionTableBuilder::AddEntry(const PositionTableEntry& entry) {
@ -152,7 +157,7 @@ Handle<ByteArray> SourcePositionTableBuilder::ToSourcePositionTable(
encoded.Advance(), raw++) {
DCHECK(raw != raw_entries_.end());
DCHECK_EQ(encoded.code_offset(), raw->code_offset);
DCHECK_EQ(encoded.source_position(), raw->source_position);
DCHECK_EQ(encoded.source_position().raw(), raw->source_position);
DCHECK_EQ(encoded.is_statement(), raw->is_statement);
}
DCHECK(raw == raw_entries_.end());

View File

@ -9,6 +9,7 @@
#include "src/checks.h"
#include "src/globals.h"
#include "src/handles.h"
#include "src/source-position.h"
#include "src/zone/zone-containers.h"
namespace v8 {
@ -23,11 +24,11 @@ class Zone;
struct PositionTableEntry {
PositionTableEntry()
: code_offset(0), source_position(0), is_statement(false) {}
PositionTableEntry(int offset, int source, bool statement)
PositionTableEntry(int offset, int64_t source, bool statement)
: code_offset(offset), source_position(source), is_statement(statement) {}
int code_offset;
int source_position;
int64_t source_position;
bool is_statement;
};
@ -38,7 +39,8 @@ class V8_EXPORT_PRIVATE SourcePositionTableBuilder {
SourcePositionTableBuilder(Zone* zone,
RecordingMode mode = RECORD_SOURCE_POSITIONS);
void AddPosition(size_t code_offset, int source_position, bool is_statement);
void AddPosition(size_t code_offset, SourcePosition source_position,
bool is_statement);
Handle<ByteArray> ToSourcePositionTable(Isolate* isolate,
Handle<AbstractCode> code);
@ -66,9 +68,9 @@ class V8_EXPORT_PRIVATE SourcePositionTableIterator {
DCHECK(!done());
return current_.code_offset;
}
int source_position() const {
SourcePosition source_position() const {
DCHECK(!done());
return current_.source_position;
return SourcePosition::FromRaw(current_.source_position);
}
bool is_statement() const {
DCHECK(!done());

137
src/source-position.cc Normal file
View File

@ -0,0 +1,137 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/source-position.h"
#include "src/compilation-info.h"
#include "src/objects-inl.h"
namespace v8 {
namespace internal {
std::ostream& operator<<(std::ostream& out, const SourcePositionInfo& pos) {
Handle<SharedFunctionInfo> function;
if (pos.function.ToHandle(&function)) {
Handle<Script> script(Script::cast(function->script()));
out << "<";
if (script->name()->IsString()) {
out << String::cast(script->name())->ToCString(DISALLOW_NULLS).get();
} else {
out << "unknown";
}
out << ":" << pos.line + 1 << ":" << pos.column + 1 << ">";
} else {
out << "<unknown:" << pos.position.ScriptOffset() << ">";
}
return out;
}
std::ostream& operator<<(std::ostream& out,
const std::vector<SourcePositionInfo>& stack) {
out << stack.back();
for (int i = static_cast<int>(stack.size()) - 2; i >= 0; --i) {
out << " inlined at ";
out << stack[i];
}
return out;
}
std::ostream& operator<<(std::ostream& out, const SourcePosition& pos) {
if (pos.isInlined()) {
out << "<inlined(" << pos.InliningId() << "):";
} else {
out << "<not inlined:";
}
out << pos.ScriptOffset() << ">";
return out;
}
SourcePositionInfo SourcePosition::Info(
Handle<SharedFunctionInfo> function) const {
Handle<Script> script(Script::cast(function->script()));
SourcePositionInfo result(*this);
Script::PositionInfo pos;
if (Script::GetPositionInfo(script, ScriptOffset(), &pos,
Script::WITH_OFFSET)) {
result.line = pos.line;
result.column = pos.column;
}
result.function = function;
return result;
}
std::vector<SourcePositionInfo> SourcePosition::InliningStack(
CompilationInfo* cinfo) const {
if (!isInlined()) {
return std::vector<SourcePositionInfo>{Info(cinfo->shared_info())};
} else {
InliningPosition inl = cinfo->inlined_functions()[InliningId()].position;
std::vector<SourcePositionInfo> stack = inl.position.InliningStack(cinfo);
stack.push_back(Info(cinfo->inlined_functions()[InliningId()].shared_info));
return stack;
}
}
std::vector<SourcePositionInfo> SourcePosition::InliningStack(
Handle<Code> code) const {
Handle<DeoptimizationInputData> deopt_data(
DeoptimizationInputData::cast(code->deoptimization_data()));
if (!isInlined()) {
Handle<SharedFunctionInfo> function(
SharedFunctionInfo::cast(deopt_data->SharedFunctionInfo()));
return std::vector<SourcePositionInfo>{Info(function)};
} else {
InliningPosition inl = deopt_data->InliningPositions()->get(InliningId());
std::vector<SourcePositionInfo> stack = inl.position.InliningStack(code);
if (inl.inlined_function_id == -1) {
stack.push_back(SourcePositionInfo(*this));
} else {
Handle<SharedFunctionInfo> function(SharedFunctionInfo::cast(
deopt_data->LiteralArray()->get(inl.inlined_function_id)));
stack.push_back(Info(function));
}
return stack;
}
}
void SourcePosition::Print(std::ostream& out,
SharedFunctionInfo* function) const {
Script* script = Script::cast(function->script());
Object* source_name = script->name();
Script::PositionInfo pos;
script->GetPositionInfo(ScriptOffset(), &pos, Script::WITH_OFFSET);
out << "<";
if (source_name->IsString()) {
out << String::cast(source_name)
->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)
.get();
} else {
out << "unknown";
}
out << ":" << pos.line + 1 << ":" << pos.column + 1 << ">";
}
void SourcePosition::Print(std::ostream& out, Code* code) const {
DeoptimizationInputData* deopt_data =
DeoptimizationInputData::cast(code->deoptimization_data());
if (!isInlined()) {
SharedFunctionInfo* function(
SharedFunctionInfo::cast(deopt_data->SharedFunctionInfo()));
Print(out, function);
} else {
InliningPosition inl = deopt_data->InliningPositions()->get(InliningId());
if (inl.inlined_function_id == -1) {
out << *this;
} else {
SharedFunctionInfo* function = SharedFunctionInfo::cast(
deopt_data->LiteralArray()->get(inl.inlined_function_id));
Print(out, function);
}
out << " inlined at ";
inl.position.Print(out, code);
}
}
} // namespace internal
} // namespace v8

View File

@ -9,77 +9,117 @@
#include "src/flags.h"
#include "src/globals.h"
#include "src/handles.h"
#include "src/utils.h"
namespace v8 {
namespace internal {
// 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 SourcePosition {
class Code;
class CompilationInfo;
class Script;
class SharedFunctionInfo;
struct SourcePositionInfo;
// SourcePosition stores
// - script_offset (31 bit non-negative int or kNoSourcePosition)
// - inlining_id (16 bit non-negative int or kNotInlined).
//
// A defined inlining_id refers to positions in
// CompilationInfo::inlined_functions or
// DeoptimizationInputData::InliningPositions, depending on the compilation
// stage.
class SourcePosition final {
public:
static SourcePosition Unknown() {
return SourcePosition::FromRaw(kNoPosition);
explicit SourcePosition(int script_offset, int inlining_id = kNotInlined)
: value_(0) {
SetScriptOffset(script_offset);
SetInliningId(inlining_id);
}
bool IsUnknown() const { return value_ == kNoPosition; }
static SourcePosition Unknown() { return SourcePosition(kNoSourcePosition); }
bool IsKnown() const {
return ScriptOffset() != kNoSourcePosition || InliningId() != kNotInlined;
}
bool isInlined() const { return InliningId() != kNotInlined; }
uint32_t position() const { return PositionField::decode(value_); }
void set_position(uint32_t position) {
if (FLAG_hydrogen_track_positions) {
value_ = static_cast<uint32_t>(PositionField::update(value_, position));
} else {
value_ = position;
}
std::vector<SourcePositionInfo> InliningStack(Handle<Code> code) const;
std::vector<SourcePositionInfo> InliningStack(CompilationInfo* code) const;
void Print(std::ostream& out, Code* function) const;
int ScriptOffset() const { return ScriptOffsetField::decode(value_) - 1; }
int InliningId() const { return InliningIdField::decode(value_) - 1; }
void SetScriptOffset(int script_offset) {
DCHECK(script_offset <= ScriptOffsetField::kMax - 2);
DCHECK(script_offset >= kNoSourcePosition);
value_ = ScriptOffsetField::update(value_, script_offset + 1);
}
void SetInliningId(int inlining_id) {
DCHECK(inlining_id <= InliningIdField::kMax - 2);
DCHECK(inlining_id >= kNotInlined);
value_ = InliningIdField::update(value_, inlining_id + 1);
}
uint32_t inlining_id() const { return InliningIdField::decode(value_); }
void set_inlining_id(uint32_t inlining_id) {
if (FLAG_hydrogen_track_positions) {
value_ =
static_cast<uint32_t>(InliningIdField::update(value_, inlining_id));
}
}
static const int kNotInlined = -1;
STATIC_ASSERT(kNoSourcePosition == -1);
uint32_t raw() const { return value_; }
private:
static const uint32_t kNoPosition = static_cast<uint32_t>(kNoSourcePosition);
typedef BitField<uint32_t, 0, 9> InliningIdField;
// Offset from the start of the inlined function.
typedef BitField<uint32_t, 9, 23> PositionField;
friend class HPositionInfo;
friend class Deoptimizer;
static SourcePosition FromRaw(uint32_t raw_position) {
int64_t raw() const { return static_cast<int64_t>(value_); }
static SourcePosition FromRaw(int64_t raw) {
SourcePosition position;
position.value_ = raw_position;
DCHECK_GE(raw, 0);
position.value_ = static_cast<uint64_t>(raw);
return position;
}
// If FLAG_hydrogen_track_positions is set contains bitfields InliningIdField
// and PositionField.
// Otherwise contains absolute offset from the script start.
uint32_t value_;
private:
// SourcePosition is used in a union in CodeEventsContainer, which requires a
// trivial constructor.
SourcePosition() = default;
void Print(std::ostream& out, SharedFunctionInfo* function) const;
SourcePositionInfo Info(Handle<SharedFunctionInfo> script) const;
// InliningId is in the high bits for better compression in
// SourcePositionTable.
typedef BitField64<int, 0, 31> ScriptOffsetField;
typedef BitField64<int, 31, 16> InliningIdField;
// Leaving the highest bit untouched to allow for signed conversion.
uint64_t value_;
};
inline std::ostream& operator<<(std::ostream& os, const SourcePosition& p) {
if (p.IsUnknown()) {
return os << "<?>";
} else if (FLAG_hydrogen_track_positions) {
return os << "<" << p.inlining_id() << ":" << p.position() << ">";
} else {
return os << "<0:" << p.raw() << ">";
}
inline bool operator==(const SourcePosition& lhs, const SourcePosition& rhs) {
return lhs.raw() == rhs.raw();
}
inline bool operator!=(const SourcePosition& lhs, const SourcePosition& rhs) {
return !(lhs == rhs);
}
struct InliningPosition {
// position of the inlined call
SourcePosition position = SourcePosition::Unknown();
// references position in DeoptimizationInputData::literals()
int inlined_function_id;
};
struct SourcePositionInfo {
explicit SourcePositionInfo(SourcePosition pos) : position(pos) {}
SourcePosition position;
MaybeHandle<SharedFunctionInfo> function;
int line = -1;
int column = -1;
};
std::ostream& operator<<(std::ostream& out, const SourcePosition& pos);
std::ostream& operator<<(std::ostream& out, const SourcePositionInfo& pos);
std::ostream& operator<<(std::ostream& out,
const std::vector<SourcePositionInfo>& stack);
} // namespace internal
} // namespace v8

View File

@ -710,8 +710,8 @@
'compiler/simplified-operator-reducer.h',
'compiler/simplified-operator.cc',
'compiler/simplified-operator.h',
'compiler/source-position.cc',
'compiler/source-position.h',
'compiler/compiler-source-position-table.cc',
'compiler/compiler-source-position-table.h',
'compiler/state-values-utils.cc',
'compiler/state-values-utils.h',
'compiler/store-store-elimination.cc',
@ -1201,6 +1201,7 @@
'snapshot/startup-serializer.h',
'source-position-table.cc',
'source-position-table.h',
'source-position.cc',
'source-position.h',
'splay-tree.h',
'splay-tree-inl.h',

View File

@ -1993,7 +1993,8 @@ class Assembler : public AssemblerBase {
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(DeoptimizeReason reason, int raw_position, int id);
void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
int id);
void PatchConstantPoolAccessInstruction(int pc_offset, int offset,
ConstantPoolEntry::Access access,

View File

@ -969,7 +969,8 @@ class Assembler : public AssemblerBase {
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(DeoptimizeReason reason, int raw_position, int id);
void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
int id);
// Writes a single byte or word of data in the code stream. Used for
// inline tables, e.g., jump-tables.

View File

@ -383,10 +383,6 @@
# BUG(4751). Flaky with Ignition.
'test-cpu-profiler/JsNativeJsSample': [SKIP],
# TurboFan cpu profiler result is different.
'test-cpu-profiler/DeoptAtFirstLevelInlinedSource': [FAIL],
'test-cpu-profiler/DeoptAtSecondLevelInlinedSource': [FAIL],
# TODO(vogelheim,5548): Turbofan does support cached accessors.
'test-api-accessors/CachedAccessorCrankshaft': [FAIL],

View File

@ -3,15 +3,15 @@
// found in the LICENSE file.
#include "src/compiler/common-operator.h"
#include "src/compiler/graph.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/graph.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node.h"
#include "src/compiler/operator.h"
#include "src/compiler/schedule.h"
#include "src/compiler/scheduler.h"
#include "src/compiler/source-position.h"
#include "src/compiler/verifier.h"
#include "test/cctest/cctest.h"

View File

@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/js-context-specialization.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/source-position.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/function-tester.h"
#include "test/cctest/compiler/graph-builder-tester.h"

View File

@ -219,7 +219,7 @@ void BytecodeExpectationsPrinter::PrintSourcePosition(
if (!source_iterator.done() &&
source_iterator.code_offset() == bytecode_offset) {
stream << "/* " << std::setw(kPositionWidth)
<< source_iterator.source_position();
<< source_iterator.source_position().ScriptOffset();
if (source_iterator.is_statement()) {
stream << " S> */ ";
} else {

View File

@ -213,7 +213,8 @@ void SourcePositionMatcher::MoveToNextStatement(
if (iterator->is_statement()) {
break;
}
positions->push_back({iterator->code_offset(), iterator->source_position(),
positions->push_back({iterator->code_offset(),
iterator->source_position().raw(),
iterator->is_statement()});
iterator->Advance();
}

View File

@ -24123,65 +24123,69 @@ TEST(ScriptPositionInfo) {
v8::internal::Script::PositionInfo info;
// With offset.
for (int i = 0; i < 2; ++i) {
// With offset.
// Behave as if 0 was passed if position is negative.
CHECK(script1->GetPositionInfo(-1, &info, script1->WITH_OFFSET));
CHECK_EQ(13, info.line);
CHECK_EQ(0, info.column);
CHECK_EQ(0, info.line_start);
CHECK_EQ(8, info.line_end);
// Behave as if 0 was passed if position is negative.
CHECK(script1->GetPositionInfo(-1, &info, script1->WITH_OFFSET));
CHECK_EQ(13, info.line);
CHECK_EQ(0, info.column);
CHECK_EQ(0, info.line_start);
CHECK_EQ(8, info.line_end);
CHECK(script1->GetPositionInfo(0, &info, script1->WITH_OFFSET));
CHECK_EQ(13, info.line);
CHECK_EQ(0, info.column);
CHECK_EQ(0, info.line_start);
CHECK_EQ(8, info.line_end);
CHECK(script1->GetPositionInfo(0, &info, script1->WITH_OFFSET));
CHECK_EQ(13, info.line);
CHECK_EQ(0, info.column);
CHECK_EQ(0, info.line_start);
CHECK_EQ(8, info.line_end);
CHECK(script1->GetPositionInfo(8, &info, script1->WITH_OFFSET));
CHECK_EQ(13, info.line);
CHECK_EQ(8, info.column);
CHECK_EQ(0, info.line_start);
CHECK_EQ(8, info.line_end);
CHECK(script1->GetPositionInfo(8, &info, script1->WITH_OFFSET));
CHECK_EQ(13, info.line);
CHECK_EQ(8, info.column);
CHECK_EQ(0, info.line_start);
CHECK_EQ(8, info.line_end);
CHECK(script1->GetPositionInfo(9, &info, script1->WITH_OFFSET));
CHECK_EQ(14, info.line);
CHECK_EQ(0, info.column);
CHECK_EQ(9, info.line_start);
CHECK_EQ(17, info.line_end);
CHECK(script1->GetPositionInfo(9, &info, script1->WITH_OFFSET));
CHECK_EQ(14, info.line);
CHECK_EQ(0, info.column);
CHECK_EQ(9, info.line_start);
CHECK_EQ(17, info.line_end);
// Fail when position is larger than script size.
CHECK(!script1->GetPositionInfo(220384, &info, script1->WITH_OFFSET));
// Fail when position is larger than script size.
CHECK(!script1->GetPositionInfo(220384, &info, script1->WITH_OFFSET));
// Without offset.
// Without offset.
// Behave as if 0 was passed if position is negative.
CHECK(script1->GetPositionInfo(-1, &info, script1->NO_OFFSET));
CHECK_EQ(0, info.line);
CHECK_EQ(0, info.column);
CHECK_EQ(0, info.line_start);
CHECK_EQ(8, info.line_end);
// Behave as if 0 was passed if position is negative.
CHECK(script1->GetPositionInfo(-1, &info, script1->NO_OFFSET));
CHECK_EQ(0, info.line);
CHECK_EQ(0, info.column);
CHECK_EQ(0, info.line_start);
CHECK_EQ(8, info.line_end);
CHECK(script1->GetPositionInfo(0, &info, script1->NO_OFFSET));
CHECK_EQ(0, info.line);
CHECK_EQ(0, info.column);
CHECK_EQ(0, info.line_start);
CHECK_EQ(8, info.line_end);
CHECK(script1->GetPositionInfo(0, &info, script1->NO_OFFSET));
CHECK_EQ(0, info.line);
CHECK_EQ(0, info.column);
CHECK_EQ(0, info.line_start);
CHECK_EQ(8, info.line_end);
CHECK(script1->GetPositionInfo(8, &info, script1->NO_OFFSET));
CHECK_EQ(0, info.line);
CHECK_EQ(8, info.column);
CHECK_EQ(0, info.line_start);
CHECK_EQ(8, info.line_end);
CHECK(script1->GetPositionInfo(8, &info, script1->NO_OFFSET));
CHECK_EQ(0, info.line);
CHECK_EQ(8, info.column);
CHECK_EQ(0, info.line_start);
CHECK_EQ(8, info.line_end);
CHECK(script1->GetPositionInfo(9, &info, script1->NO_OFFSET));
CHECK_EQ(1, info.line);
CHECK_EQ(0, info.column);
CHECK_EQ(9, info.line_start);
CHECK_EQ(17, info.line_end);
CHECK(script1->GetPositionInfo(9, &info, script1->NO_OFFSET));
CHECK_EQ(1, info.line);
CHECK_EQ(0, info.column);
CHECK_EQ(9, info.line_start);
CHECK_EQ(17, info.line_end);
// Fail when position is larger than script size.
CHECK(!script1->GetPositionInfo(220384, &info, script1->NO_OFFSET));
// Fail when position is larger than script size.
CHECK(!script1->GetPositionInfo(220384, &info, script1->NO_OFFSET));
i::Script::InitLineEnds(script1);
}
}
void CheckMagicComments(Local<Script> script, const char* expected_source_url,

View File

@ -1905,10 +1905,8 @@ TEST(SourceLocation) {
.ToLocalChecked();
}
static const char* inlined_source =
"function opt_function(left, right) { var k = left / 10; var r = 10 / "
"right; return k + r; }\n";
"function opt_function(f) { return f()*f(); }\n";
// 0.........1.........2.........3.........4....*....5.........6......*..7
@ -1925,17 +1923,16 @@ TEST(DeoptAtFirstLevelInlinedSource) {
// 0.........1.........2.........3.........4.........5.........6.........7
const char* source =
"function test(left, right) { return opt_function(left, right); }\n"
"function test(f) { return opt_function(f); }\n"
"\n"
"startProfiling();\n"
"\n"
"test(10, 10);\n"
"test(function(){return 10});test(function(){return 12});\n"
"\n"
"%SetForceInlineFlag(opt_function);\n"
"%OptimizeFunctionOnNextCall(test)\n"
"\n"
"test(10, 10);\n"
"\n"
"test(undefined, 10);\n"
"test(function(){return 100000000000});\n"
"\n"
"stopProfiling();\n"
"\n";
@ -1970,12 +1967,13 @@ TEST(DeoptAtFirstLevelInlinedSource) {
CHECK_EQ(1U, deopt_infos.size());
const v8::CpuProfileDeoptInfo& info = deopt_infos[0];
CHECK_EQ(reason(i::DeoptimizeReason::kNotAHeapNumber), info.deopt_reason);
CHECK_EQ(reason(i::DeoptimizeReason::kNotASmi), info.deopt_reason);
CHECK_EQ(2U, info.stack.size());
CHECK_EQ(inlined_script_id, info.stack[0].script_id);
CHECK_EQ(offset(inlined_source, "left /"), info.stack[0].position);
CHECK(abs(static_cast<int>(offset(inlined_source, "*f()")) -
static_cast<int>(info.stack[0].position)) <= 1);
CHECK_EQ(script_id, info.stack[1].script_id);
CHECK_EQ(offset(source, "opt_function(left,"), info.stack[1].position);
CHECK_EQ(offset(source, "opt_function(f)"), info.stack[1].position);
iprofiler->DeleteProfile(iprofile);
}
@ -1994,18 +1992,21 @@ TEST(DeoptAtSecondLevelInlinedSource) {
// 0.........1.........2.........3.........4.........5.........6.........7
const char* source =
"function test2(left, right) { return opt_function(left, right); }\n"
"function test1(left, right) { return test2(left, right); }\n"
"function test2(f) { return opt_function(f); }\n"
"function test1(f) { return test2(f); }\n"
"\n"
"startProfiling();\n"
"\n"
"test1(10, 10);\n"
"test1(function(){return 10});\n"
"test1(function(){return 11});\n"
"\n"
"%SetForceInlineFlag(test2);\n"
"%SetForceInlineFlag(opt_function);\n"
"%OptimizeFunctionOnNextCall(test1)\n"
"\n"
"test1(10, 10);\n"
"test1(function(){return 12});\n"
"\n"
"test1(undefined, 10);\n"
"test1(function(){return 100000000000});\n"
"\n"
"stopProfiling();\n"
"\n";
@ -2043,13 +2044,14 @@ TEST(DeoptAtSecondLevelInlinedSource) {
CHECK_EQ(1U, deopt_infos.size());
const v8::CpuProfileDeoptInfo info = deopt_infos[0];
CHECK_EQ(reason(i::DeoptimizeReason::kNotAHeapNumber), info.deopt_reason);
CHECK_EQ(reason(i::DeoptimizeReason::kNotASmi), info.deopt_reason);
CHECK_EQ(3U, info.stack.size());
CHECK_EQ(inlined_script_id, info.stack[0].script_id);
CHECK_EQ(offset(inlined_source, "left /"), info.stack[0].position);
CHECK(abs(static_cast<int>(offset(inlined_source, "*f()")) -
static_cast<int>(info.stack[0].position)) <= 1);
CHECK_EQ(script_id, info.stack[1].script_id);
CHECK_EQ(offset(source, "opt_function(left,"), info.stack[1].position);
CHECK_EQ(offset(source, "test2(left, right);"), info.stack[2].position);
CHECK_EQ(offset(source, "opt_function(f)"), info.stack[1].position);
CHECK_EQ(offset(source, "test2(f);"), info.stack[2].position);
iprofiler->DeleteProfile(iprofile);
}
@ -2070,15 +2072,17 @@ TEST(DeoptUntrackedFunction) {
const char* source =
"function test(left, right) { return opt_function(left, right); }\n"
"\n"
"test(10, 10);\n"
"test(function(){return 10});\n"
"test(function(){return 11});\n"
"\n"
"%SetForceInlineFlag(opt_function);\n"
"%OptimizeFunctionOnNextCall(test)\n"
"\n"
"test(10, 10);\n"
"test(function(){return 10});\n"
"\n"
"startProfiling();\n" // profiler started after compilation.
"\n"
"test(undefined, 10);\n"
"test(function(){return 100000000000});\n"
"\n"
"stopProfiling();\n"
"\n";

View File

@ -13,6 +13,7 @@
#include "src/base/utils/random-number-generator.h"
#include "src/zone/accounting-allocator.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/int64-lowering.h"
#include "src/compiler/js-graph.h"

View File

@ -4,9 +4,9 @@
#include "src/compiler/control-equivalence.h"
#include "src/bit-vector.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/source-position.h"
#include "src/zone/zone-containers.h"
#include "test/unittests/compiler/graph-unittest.h"

View File

@ -5,6 +5,7 @@
#include "test/unittests/compiler/instruction-selector-unittest.h"
#include "src/code-factory.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/graph.h"
#include "src/compiler/schedule.h"
#include "src/flags.h"

Some files were not shown because too many files have changed in this diff Show More