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:
parent
372d905d73
commit
c3a6ca68d0
5
BUILD.gn
5
BUILD.gn
@ -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",
|
||||
|
@ -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.
|
||||
//
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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()));
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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_
|
@ -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";
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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:
|
||||
|
@ -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) {}
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 --------------------",
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 --------------------",
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
|
@ -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_;
|
||||
};
|
||||
|
||||
|
@ -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 --------------------",
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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()) {}
|
||||
|
||||
|
@ -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_;
|
||||
};
|
||||
|
@ -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 --------------------",
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 --------------------",
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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> "
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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> "
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 --------------------",
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 --------------------",
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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_;
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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 =
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
214
src/objects.cc
214
src/objects.cc
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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());
|
||||
|
@ -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
137
src/source-position.cc
Normal 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
|
@ -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
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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],
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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";
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user