// 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. #ifndef V8_CODEGEN_SOURCE_POSITION_TABLE_H_ #define V8_CODEGEN_SOURCE_POSITION_TABLE_H_ #include "src/base/export-template.h" #include "src/base/vector.h" #include "src/codegen/source-position.h" #include "src/common/assert-scope.h" #include "src/common/checks.h" #include "src/common/globals.h" #include "src/zone/zone-containers.h" namespace v8 { namespace internal { class ByteArray; template <typename T> class Handle; class Isolate; class Zone; struct PositionTableEntry { PositionTableEntry() : code_offset(kFunctionEntryBytecodeOffset), source_position(0), is_statement(false) {} PositionTableEntry(int offset, int64_t source, bool statement) : code_offset(offset), source_position(source), is_statement(statement) {} int code_offset; int64_t source_position; bool is_statement; }; class V8_EXPORT_PRIVATE SourcePositionTableBuilder { public: enum RecordingMode { // Indicates that source positions are never to be generated. (Resulting in // an empty table). OMIT_SOURCE_POSITIONS, // Indicates that source positions are not currently required, but may be // generated later. LAZY_SOURCE_POSITIONS, // Indicates that source positions should be immediately generated. RECORD_SOURCE_POSITIONS }; explicit SourcePositionTableBuilder( Zone* zone, RecordingMode mode = RECORD_SOURCE_POSITIONS); void AddPosition(size_t code_offset, SourcePosition source_position, bool is_statement); template <typename IsolateT> EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) Handle<ByteArray> ToSourcePositionTable(IsolateT* isolate); base::OwnedVector<byte> ToSourcePositionTableVector(); inline bool Omit() const { return mode_ != RECORD_SOURCE_POSITIONS; } inline bool Lazy() const { return mode_ == LAZY_SOURCE_POSITIONS; } private: void AddEntry(const PositionTableEntry& entry); RecordingMode mode_; ZoneVector<byte> bytes_; #ifdef ENABLE_SLOW_DCHECKS ZoneVector<PositionTableEntry> raw_entries_; #endif PositionTableEntry previous_; // Previously written entry, to compute delta. }; class V8_EXPORT_PRIVATE SourcePositionTableIterator { public: // Filter that applies when advancing the iterator. If the filter isn't // satisfied, we advance the iterator again. enum IterationFilter { kJavaScriptOnly = 0, kExternalOnly = 1, kAll = 2 }; // Filter that applies only to the first entry of the source position table. // If it is kSkipFunctionEntry, it will skip the FunctionEntry entry if it // exists. enum FunctionEntryFilter { kSkipFunctionEntry = 0, kDontSkipFunctionEntry = 1 }; // Used for saving/restoring the iterator. struct IndexAndPositionState { int index_; PositionTableEntry position_; IterationFilter iteration_filter_; FunctionEntryFilter function_entry_filter_; }; // We expose three flavours of the iterator, depending on the argument passed // to the constructor: // Handlified iterator allows allocation, but it needs a handle (and thus // a handle scope). This is the preferred version. explicit SourcePositionTableIterator( Handle<ByteArray> byte_array, IterationFilter iteration_filter = kJavaScriptOnly, FunctionEntryFilter function_entry_filter = kSkipFunctionEntry); // Non-handlified iterator does not need a handle scope, but it disallows // allocation during its lifetime. This is useful if there is no handle // scope around. explicit SourcePositionTableIterator( ByteArray byte_array, IterationFilter iteration_filter = kJavaScriptOnly, FunctionEntryFilter function_entry_filter = kSkipFunctionEntry); // Handle-safe iterator based on an a vector located outside the garbage // collected heap, allows allocation during its lifetime. explicit SourcePositionTableIterator( base::Vector<const byte> bytes, IterationFilter iteration_filter = kJavaScriptOnly, FunctionEntryFilter function_entry_filter = kSkipFunctionEntry); void Advance(); int code_offset() const { DCHECK(!done()); return current_.code_offset; } SourcePosition source_position() const { DCHECK(!done()); return SourcePosition::FromRaw(current_.source_position); } bool is_statement() const { DCHECK(!done()); return current_.is_statement; } bool done() const { return index_ == kDone; } IndexAndPositionState GetState() const { return {index_, current_, iteration_filter_, function_entry_filter_}; } void RestoreState(const IndexAndPositionState& saved_state) { index_ = saved_state.index_; current_ = saved_state.position_; iteration_filter_ = saved_state.iteration_filter_; function_entry_filter_ = saved_state.function_entry_filter_; } private: // Initializes the source position interator with the first valid bytecode. // Also sets the FunctionEntry SourcePosition if it exists. void Initialize(); static const int kDone = -1; base::Vector<const byte> raw_table_; Handle<ByteArray> table_; int index_ = 0; PositionTableEntry current_; IterationFilter iteration_filter_; FunctionEntryFilter function_entry_filter_; DISALLOW_GARBAGE_COLLECTION(no_gc) }; } // namespace internal } // namespace v8 #endif // V8_CODEGEN_SOURCE_POSITION_TABLE_H_