Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Side by Side Diff: test/cctest/interpreter/source-position-matcher.cc

Issue 2042633002: [interpreter] Ensure optimizations preserve source positions. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 #include "test/cctest/interpreter/source-position-matcher.h"
6
7 #include "src/interpreter/bytecode-array-iterator.h"
8 #include "src/objects-inl.h"
9 #include "src/objects.h"
10
11 namespace v8 {
12 namespace internal {
13 namespace interpreter {
14
15 // Comparer for PositionTableEntry instances.
16 struct PTECompare {
rmcilroy 2016/06/07 09:46:11 I don't think it's worth abbreviating this given y
oth 2016/06/07 13:46:17 Done.
17 bool operator()(const PositionTableEntry& lhs,
18 const PositionTableEntry& rhs) {
19 int lhs_type_score = type_score(lhs);
20 int rhs_type_score = type_score(rhs);
21 if (lhs_type_score == rhs_type_score) {
22 return lhs.source_position < rhs.source_position;
23 } else {
24 return lhs_type_score < rhs_type_score;
25 }
26 }
27
28 int type_score(const PositionTableEntry& entry) {
29 return entry.is_statement ? 1 : 0;
30 }
31 };
32
33 //
34 // The principles for comparing source positions in bytecode arrays
35 // are:
36 //
37 // 1. The number of statement positions must be the same in both.
38 //
39 // 2. Statement positions may be moved provide they do not affect the
40 // debuggers causal view of the v8 heap and local state. This means
41 // statement positions may be moved when their initial posiiton is
rmcilroy 2016/06/07 09:46:11 /s/posiiton/position
oth 2016/06/07 13:46:17 Done.
42 // on bytecodes that manipulate the accumulator and temporary
43 // registers.
44 //
45 // 3. When duplicate expression positions are present, either may
46 // be dropped.
47 //
48 // 4. Expression positions may be applied to later bytecodes in the
49 // bytecode array if the current bytecode does not throw.
50 //
51 // 5. Expression positions may be dropped when they are applied to
52 // bytecodes that manipulate local frame state and immediately
53 // proceeded by another source position.
54 //
55 // 6. The relative ordering of source positions must be preserved.
56 //
57 bool SourcePositionMatcher::Match(Handle<BytecodeArray> original_bytecode,
58 Handle<BytecodeArray> optimized_bytecode) {
59 SourcePositionTableIterator original(
60 original_bytecode->source_position_table());
61 SourcePositionTableIterator optimized(
62 optimized_bytecode->source_position_table());
63
64 int last_original_bytecode_offset = 0;
65 int last_optimized_bytecode_offset = 0;
66
67 // Order list of expression positions (terminated by a statement
68 // position to ease validation).
rmcilroy 2016/06/07 09:46:11 I think it's a bit confusing to terminate with the
oth 2016/06/07 13:46:17 Okay, done. The statement position is used as a ba
69 std::vector<PositionTableEntry> original_expression_entries;
70 std::vector<PositionTableEntry> optimized_expression_entries;
71
72 while (true) {
73 MoveToNextStatement(&original, &original_expression_entries);
74 MoveToNextStatement(&optimized, &optimized_expression_entries);
75
76 if (original.done() && optimized.done()) {
77 return true;
78 } else if (original.done()) {
79 printf("Source positions ended early on original bytecode.");
80 return false;
81 } else if (optimized.done()) {
82 printf("Source positions ended early on optimized bytecode.");
83 return false;
84 }
85
86 if (NewExpressionPositionsInOptimized(&original_expression_entries,
rmcilroy 2016/06/07 09:46:11 nit - HasNewExpressionPositionsInOptimized
oth 2016/06/07 13:46:17 Done.
87 &optimized_expression_entries)) {
88 printf("Optimized set has new expression positions.\n");
89 return false;
90 }
91
92 StripUnneededExpressionPositions(original_bytecode,
93 &original_expression_entries);
94 StripUnneededExpressionPositions(optimized_bytecode,
95 &optimized_expression_entries);
96 if (!CompareExpressionPositions(&original_expression_entries,
97 &optimized_expression_entries)) {
98 return false;
rmcilroy 2016/06/07 09:46:11 nit - comment that message is printed in CompareEx
oth 2016/06/07 13:46:17 Done.
99 }
100
101 // Check original and optimized have matching source positions.
102 if (original.source_position() != optimized.source_position()) {
103 printf("Statement source position mismatch %d != %d\n",
104 original.source_position(), optimized.source_position());
105 return false;
106 }
107
108 if (original.bytecode_offset() < last_original_bytecode_offset) {
109 printf("Original has bytecode offset running backwards %d < %d.\n",
110 original.bytecode_offset(), last_original_bytecode_offset);
111 return false;
112 }
113 last_original_bytecode_offset = original.bytecode_offset();
114
115 if (optimized.bytecode_offset() < last_optimized_bytecode_offset) {
116 printf("Optimized has bytecode offset running backwards %d < %d.\n",
117 optimized.bytecode_offset(), last_optimized_bytecode_offset);
118 return false;
119 }
120 last_optimized_bytecode_offset = optimized.bytecode_offset();
121
122 // TODO(oth): Can we compare statement positions are semantically
123 // equivalent? e.g. before a bytecode that has debugger observable
124 // effects. This is likely non-trivial.
125 }
126
127 return true;
128 }
129
130 bool SourcePositionMatcher::NewExpressionPositionsInOptimized(
131 const std::vector<PositionTableEntry>* const original_positions,
132 const std::vector<PositionTableEntry>* const optimized_positions) {
133 std::set<PositionTableEntry, PTECompare> original_set(
134 original_positions->begin(), original_positions->end());
135
136 bool retval = false;
137 for (auto optimized_position : *optimized_positions) {
138 if (original_set.find(optimized_position) == original_set.end()) {
139 printf("Optimized bytecode has new expression source position %d\n",
140 optimized_position.source_position);
141 retval = true;
142 }
143 }
144 return retval;
145 }
146
147 bool SourcePositionMatcher::CompareExpressionPositions(
148 const std::vector<PositionTableEntry>* const original_positions,
149 const std::vector<PositionTableEntry>* const optimized_positions) {
150 if (original_positions->size() < 1 ||
151 !original_positions->back().is_statement) {
152 printf(
153 "Original expression positions are not terminated by a statement.\n");
154 return false;
155 }
156
157 if (optimized_positions->size() < 1 ||
158 !optimized_positions->back().is_statement) {
159 printf(
160 "Optimized expression positions are not terminated by a statement.\n");
161 return false;
162 }
163
164 if (original_positions->size() != optimized_positions->size()) {
165 printf(
166 "Optimized bytecode has different number of expression positions "
167 "%zu != %zu\n",
168 optimized_positions->size() - 1, original_positions->size() - 1);
169 printf("Original expression source positions");
rmcilroy 2016/06/07 09:46:11 Is some of this logging printfs? Maybe you should
oth 2016/06/07 13:46:17 I can't see anything in v8 tests that attempts to
170 for (size_t i = 0; i < original_positions->size() - 1; ++i) {
171 printf(" %d", original_positions->at(i).source_position);
172 }
173 printf("\nOptimized expression source positions");
174 for (size_t i = 0; i < optimized_positions->size() - 1; ++i) {
175 printf(" %d", optimized_positions->at(i).source_position);
176 }
177 printf("\n");
178 return false;
179 }
180
181 for (size_t i = 0; i < original_positions->size() - 1; ++i) {
182 PositionTableEntry original = original_positions->at(i);
183 PositionTableEntry optimized = original_positions->at(i);
184 CHECK(original.source_position > 0);
185 if ((original.is_statement || optimized.is_statement) ||
186 (original.source_position != optimized.source_position) ||
187 (original.source_position < 0)) {
188 printf("Expression positions differ %d != %d\n", original.source_position,
189 optimized.source_position);
190 return false;
191 }
192 }
193 return true;
194 }
195
196 void SourcePositionMatcher::StripUnneededExpressionPositions(
197 Handle<BytecodeArray> bytecode_array,
198 std::vector<PositionTableEntry>* positions) {
199 size_t j = 0;
200 for (size_t i = 0; i < positions->size() - 1; ++i) {
201 CHECK(positions->at(i).source_position > 0 &&
202 !positions->at(i).is_statement);
203 if (ExpressionPositionIsNeeded(bytecode_array,
204 positions->at(i).bytecode_offset,
205 positions->at(i + 1).bytecode_offset)) {
206 positions->at(j++) = positions->at(i);
207 }
208 }
209 positions->at(j++) = positions->back();
210 positions->resize(j);
211 CHECK(positions->back().is_statement);
212 }
213
214 bool SourcePositionMatcher::ExpressionPositionIsNeeded(
215 Handle<BytecodeArray> bytecode_array, int start_offset, int end_offset) {
216 CHECK_GT(end_offset, start_offset);
217 BytecodeArrayIterator iterator(bytecode_array);
218 while (iterator.current_offset() != start_offset) {
219 iterator.Advance();
220 }
221
222 while (iterator.current_offset() != end_offset) {
223 if (Bytecodes::IsWithoutExternalSideEffects(iterator.current_bytecode())) {
224 iterator.Advance();
225 } else {
226 // Bytecode could throw so need an expression position.
227 CHECK(iterator.current_bytecode() != Bytecode::kStar);
rmcilroy 2016/06/07 09:46:11 Not sure why this CHECK is here. It couldn't be St
oth 2016/06/07 13:46:17 It's just left over cruft from an earlier revision
228 return true;
229 }
230 }
231 return false;
232 }
233
234 void SourcePositionMatcher::MoveToNextStatement(
235 SourcePositionTableIterator* iterator,
236 std::vector<PositionTableEntry>* positions) {
237 iterator->Advance();
238 positions->clear();
239 while (!iterator->done()) {
240 positions->push_back({iterator->bytecode_offset(),
241 iterator->source_position(),
242 iterator->is_statement()});
243 if (iterator->is_statement()) {
244 break;
245 }
246 iterator->Advance();
247 }
248 }
249
250 } // namespace interpreter
251 } // namespace internal
252 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698