1 // Copyright 2016 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_CODEGEN_SOURCE_POSITION_TABLE_H_ 6 #define V8_CODEGEN_SOURCE_POSITION_TABLE_H_ 7 8 #include "src/base/export-template.h" 9 #include "src/codegen/source-position.h" 10 #include "src/common/assert-scope.h" 11 #include "src/common/checks.h" 12 #include "src/common/globals.h" 13 #include "src/utils/vector.h" 14 #include "src/zone/zone-containers.h" 15 16 namespace v8 { 17 namespace internal { 18 19 class ByteArray; 20 template <typename T> 21 class Handle; 22 class Isolate; 23 class Zone; 24 25 struct PositionTableEntry { PositionTableEntryPositionTableEntry26 PositionTableEntry() 27 : code_offset(kFunctionEntryBytecodeOffset), 28 source_position(0), 29 is_statement(false) {} PositionTableEntryPositionTableEntry30 PositionTableEntry(int offset, int64_t source, bool statement) 31 : code_offset(offset), source_position(source), is_statement(statement) {} 32 33 int code_offset; 34 int64_t source_position; 35 bool is_statement; 36 }; 37 38 class V8_EXPORT_PRIVATE SourcePositionTableBuilder { 39 public: 40 enum RecordingMode { 41 // Indicates that source positions are never to be generated. (Resulting in 42 // an empty table). 43 OMIT_SOURCE_POSITIONS, 44 // Indicates that source positions are not currently required, but may be 45 // generated later. 46 LAZY_SOURCE_POSITIONS, 47 // Indicates that source positions should be immediately generated. 48 RECORD_SOURCE_POSITIONS 49 }; 50 51 explicit SourcePositionTableBuilder( 52 Zone* zone, RecordingMode mode = RECORD_SOURCE_POSITIONS); 53 54 void AddPosition(size_t code_offset, SourcePosition source_position, 55 bool is_statement); 56 57 template <typename LocalIsolate> 58 EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) 59 Handle<ByteArray> ToSourcePositionTable(LocalIsolate* isolate); 60 OwnedVector<byte> ToSourcePositionTableVector(); 61 Omit()62 inline bool Omit() const { return mode_ != RECORD_SOURCE_POSITIONS; } Lazy()63 inline bool Lazy() const { return mode_ == LAZY_SOURCE_POSITIONS; } 64 65 private: 66 void AddEntry(const PositionTableEntry& entry); 67 68 RecordingMode mode_; 69 ZoneVector<byte> bytes_; 70 #ifdef ENABLE_SLOW_DCHECKS 71 ZoneVector<PositionTableEntry> raw_entries_; 72 #endif 73 PositionTableEntry previous_; // Previously written entry, to compute delta. 74 }; 75 76 class V8_EXPORT_PRIVATE SourcePositionTableIterator { 77 public: 78 // Filter that applies when advancing the iterator. If the filter isn't 79 // satisfied, we advance the iterator again. 80 enum IterationFilter { kJavaScriptOnly = 0, kExternalOnly = 1, kAll = 2 }; 81 // Filter that applies only to the first entry of the source position table. 82 // If it is kSkipFunctionEntry, it will skip the FunctionEntry entry if it 83 // exists. 84 enum FunctionEntryFilter { 85 kSkipFunctionEntry = 0, 86 kDontSkipFunctionEntry = 1 87 }; 88 89 // Used for saving/restoring the iterator. 90 struct IndexAndPositionState { 91 int index_; 92 PositionTableEntry position_; 93 IterationFilter iteration_filter_; 94 FunctionEntryFilter function_entry_filter_; 95 }; 96 97 // We expose three flavours of the iterator, depending on the argument passed 98 // to the constructor: 99 100 // Handlified iterator allows allocation, but it needs a handle (and thus 101 // a handle scope). This is the preferred version. 102 explicit SourcePositionTableIterator( 103 Handle<ByteArray> byte_array, 104 IterationFilter iteration_filter = kJavaScriptOnly, 105 FunctionEntryFilter function_entry_filter = kSkipFunctionEntry); 106 107 // Non-handlified iterator does not need a handle scope, but it disallows 108 // allocation during its lifetime. This is useful if there is no handle 109 // scope around. 110 explicit SourcePositionTableIterator( 111 ByteArray byte_array, IterationFilter iteration_filter = kJavaScriptOnly, 112 FunctionEntryFilter function_entry_filter = kSkipFunctionEntry); 113 114 // Handle-safe iterator based on an a vector located outside the garbage 115 // collected heap, allows allocation during its lifetime. 116 explicit SourcePositionTableIterator( 117 Vector<const byte> bytes, 118 IterationFilter iteration_filter = kJavaScriptOnly, 119 FunctionEntryFilter function_entry_filter = kSkipFunctionEntry); 120 121 void Advance(); 122 code_offset()123 int code_offset() const { 124 DCHECK(!done()); 125 return current_.code_offset; 126 } source_position()127 SourcePosition source_position() const { 128 DCHECK(!done()); 129 return SourcePosition::FromRaw(current_.source_position); 130 } is_statement()131 bool is_statement() const { 132 DCHECK(!done()); 133 return current_.is_statement; 134 } done()135 bool done() const { return index_ == kDone; } 136 GetState()137 IndexAndPositionState GetState() const { 138 return {index_, current_, iteration_filter_, function_entry_filter_}; 139 } 140 RestoreState(const IndexAndPositionState & saved_state)141 void RestoreState(const IndexAndPositionState& saved_state) { 142 index_ = saved_state.index_; 143 current_ = saved_state.position_; 144 iteration_filter_ = saved_state.iteration_filter_; 145 function_entry_filter_ = saved_state.function_entry_filter_; 146 } 147 148 private: 149 // Initializes the source position interator with the first valid bytecode. 150 // Also sets the FunctionEntry SourcePosition if it exists. 151 void Initialize(); 152 153 static const int kDone = -1; 154 155 Vector<const byte> raw_table_; 156 Handle<ByteArray> table_; 157 int index_ = 0; 158 PositionTableEntry current_; 159 IterationFilter iteration_filter_; 160 FunctionEntryFilter function_entry_filter_; 161 DISALLOW_HEAP_ALLOCATION(no_gc) 162 }; 163 164 } // namespace internal 165 } // namespace v8 166 167 #endif // V8_CODEGEN_SOURCE_POSITION_TABLE_H_ 168