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/base/vector.h" 10#include "src/codegen/source-position.h" 11#include "src/common/assert-scope.h" 12#include "src/common/checks.h" 13#include "src/common/globals.h" 14#include "src/zone/zone-containers.h" 15 16namespace v8 { 17namespace internal { 18 19class ByteArray; 20template <typename T> 21class Handle; 22class Isolate; 23class Zone; 24 25struct PositionTableEntry { 26 PositionTableEntry() 27 : code_offset(kFunctionEntryBytecodeOffset), 28 source_position(0), 29 is_statement(false) {} 30 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 38class 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 IsolateT> 58 EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) 59 Handle<ByteArray> ToSourcePositionTable(IsolateT* isolate); 60 base::OwnedVector<byte> ToSourcePositionTableVector(); 61 62 inline bool Omit() const { return mode_ != RECORD_SOURCE_POSITIONS; } 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 76class 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 base::Vector<const byte> bytes, 118 IterationFilter iteration_filter = kJavaScriptOnly, 119 FunctionEntryFilter function_entry_filter = kSkipFunctionEntry); 120 121 void Advance(); 122 123 int code_offset() const { 124 DCHECK(!done()); 125 return current_.code_offset; 126 } 127 SourcePosition source_position() const { 128 DCHECK(!done()); 129 return SourcePosition::FromRaw(current_.source_position); 130 } 131 bool is_statement() const { 132 DCHECK(!done()); 133 return current_.is_statement; 134 } 135 bool done() const { return index_ == kDone; } 136 137 IndexAndPositionState GetState() const { 138 return {index_, current_, iteration_filter_, function_entry_filter_}; 139 } 140 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 base::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_GARBAGE_COLLECTION(no_gc) 162}; 163 164} // namespace internal 165} // namespace v8 166 167#endif // V8_CODEGEN_SOURCE_POSITION_TABLE_H_ 168