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

Side by Side Diff: test/cctest/interpreter/test-source-positions.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 2015 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 "src/v8.h"
6
7 #include "src/compiler/pipeline.h"
8 #include "src/handles.h"
9 #include "src/interpreter/bytecode-generator.h"
10 #include "src/interpreter/interpreter.h"
11 #include "src/isolate.h"
12 #include "src/parsing/parser.h"
13 #include "test/cctest/cctest.h"
14 #include "test/cctest/interpreter/source-position-matcher.h"
15
16 namespace v8 {
17 namespace internal {
18 namespace interpreter {
19
20 struct BytecodeFrameInfo {
21 explicit BytecodeFrameInfo(int locals_count = -1)
22 : number_of_locals(locals_count) {}
23
24 int number_of_locals;
25 };
26
27 class OptimizedBytecodeSourcePositionTester final {
28 public:
29 explicit OptimizedBytecodeSourcePositionTester(Isolate* isolate)
30 : isolate_(isolate) {
31 optimization_flags_ = {&FLAG_ignition_peephole, &FLAG_ignition_reo};
32 SaveFlags();
33 }
34 ~OptimizedBytecodeSourcePositionTester() { RestoreFlags(); }
35
36 bool SourcePositionsMatch(const char* function_body,
37 const char* function_decl_params = "",
38 const char* function_args = "");
39
40 private:
41 Handle<BytecodeArray> MakeBytecode(size_t optimization_flags,
42 const char* function_body,
43 const char* function_decl_params,
44 const char* function_args,
45 BytecodeFrameInfo* frame_info);
46 static std::string MakeFunctionName(size_t flags);
47 static std::string MakeScript(const char* function_name,
48 const char* function_body,
49 const char* function_decl_params,
50 const char* function_args);
51
52 void SetOptimizationFlags(size_t bitmask);
53 void SaveFlags();
54 void RestoreFlags();
55
56 Isolate* isolate() const { return isolate_; }
57
58 Isolate* isolate_;
59 std::vector<bool*> optimization_flags_;
60 std::vector<bool> saved_flags_;
61 };
62
63 // static
64 std::string OptimizedBytecodeSourcePositionTester::MakeFunctionName(
65 size_t flags) {
66 std::ostringstream os;
67 os << "test_function_" << flags;
68 return os.str();
69 }
70
71 // static
72 std::string OptimizedBytecodeSourcePositionTester::MakeScript(
73 const char* function_name, const char* function_body,
74 const char* function_decl_params, const char* function_args) {
75 std::ostringstream os;
76 os << "function " << function_name << "(" << function_decl_params << ") {";
77 os << function_body;
78 os << "}";
79 os << function_name << "(" << function_args << ");";
80 return os.str();
81 }
82
83 Handle<BytecodeArray> OptimizedBytecodeSourcePositionTester::MakeBytecode(
84 size_t flags, const char* function_body, const char* function_decl_params,
85 const char* function_args, BytecodeFrameInfo* frame_info) {
86 std::string function_name = MakeFunctionName(flags);
87 std::string script = MakeScript(function_name.c_str(), function_body,
88 function_decl_params, function_args);
89 SetOptimizationFlags(flags);
90 CompileRun(script.c_str());
91
92 // Get number of locals and store in frame_info.
93 Local<Function> api_function =
94 Local<Function>::Cast(CcTest::global()
95 ->Get(CcTest::isolate()->GetCurrentContext(),
96 v8_str(function_name.c_str()))
97 .ToLocalChecked());
98 Handle<JSFunction> function =
99 Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function));
100 frame_info->number_of_locals =
101 function->shared()->scope_info()->StackSlotCount();
102
103 return handle(function->shared()->bytecode_array());
104 }
105
106 void OptimizedBytecodeSourcePositionTester::SetOptimizationFlags(
107 size_t bitmask) {
rmcilroy 2016/06/07 09:46:11 Could we just have bools for each of the flags or
oth 2016/06/07 13:46:18 The intent was adding a new optimization stage wou
108 size_t bit = 1;
109 for (size_t i = 0; i < optimization_flags_.size(); ++i) {
110 *optimization_flags_[i] = bitmask & bit ? true : false;
111 bit <<= 1;
112 }
113 }
114
115 void OptimizedBytecodeSourcePositionTester::SaveFlags() {
116 saved_flags_.resize(optimization_flags_.size());
117 for (size_t i = 0; i < optimization_flags_.size(); ++i) {
118 saved_flags_[i] = *optimization_flags_[i];
119 }
120 }
121
122 void OptimizedBytecodeSourcePositionTester::RestoreFlags() {
123 for (size_t i = 0; i < optimization_flags_.size(); ++i) {
124 *optimization_flags_[i] = saved_flags_[i];
125 }
126 }
127
128 bool OptimizedBytecodeSourcePositionTester::SourcePositionsMatch(
129 const char* function_body, const char* function_decl_params,
130 const char* function_args) {
131 BytecodeFrameInfo unoptimized_frame_info;
132 Handle<BytecodeArray> unoptimized_bytecode =
133 MakeBytecode(0, function_body, function_decl_params, function_args,
134 &unoptimized_frame_info);
135 size_t count = static_cast<size_t>(1u) << optimization_flags_.size();
136 for (size_t i = 1; i < count; ++i) {
rmcilroy 2016/06/07 09:46:11 I'd prefer we had seperate tests for each optimiza
oth 2016/06/07 13:46:18 I'm not sure this scales. The code currently test
137 BytecodeFrameInfo optimized_frame_info;
138 Handle<BytecodeArray> optimized_bytecode =
139 MakeBytecode(i, function_body, function_decl_params, function_args,
140 &optimized_frame_info);
141 SourcePositionMatcher matcher(unoptimized_frame_info.number_of_locals);
142 if (!matcher.Match(unoptimized_bytecode, optimized_bytecode)) {
143 printf("Unoptimized:\n");
rmcilroy 2016/06/07 09:46:11 remove logging
oth 2016/06/07 13:46:18 Done.
144 unoptimized_bytecode->Print();
145 printf("Optimized:\n");
146 optimized_bytecode->Print();
147 return false;
148 }
149 }
150 return true;
151 }
152
153 class ScopedFlag {
154 public:
155 explicit ScopedFlag(bool* flag) : flag_(flag), saved_value_(flag) {}
156 ~ScopedFlag() { *flag_ = saved_value_; }
157
158 ScopedFlag& operator=(bool value) {
159 *flag_ = value;
160 return *this;
161 }
162
163 private:
164 bool* flag_;
165 bool saved_value_;
166
167 DISALLOW_COPY_AND_ASSIGN(ScopedFlag);
168 };
169
170 TEST(SourcePositionsEquivalent) {
171 HandleAndZoneScope handles;
172
173 ScopedFlag always_opt_flag(&FLAG_always_opt);
174 always_opt_flag = false;
175
176 ScopedFlag ignition_flag(&FLAG_ignition);
177 ignition_flag = true;
rmcilroy 2016/06/07 09:46:11 nit - You could set these flags (and initialize th
oth 2016/06/07 13:46:18 Done.
178
179 // Ensure handler table is generated.
180 handles.main_isolate()->interpreter()->Initialize();
181
182 const char* test_scripts[] = {
183 "var x = (y = 3) + (x = y); return x + y;",
184
185 "var x = 55;\n"
186 "var y = x + (x = 1) + (x = 2) + (x = 3);\n"
187 "return y;",
188
189 "var x = 10; return x >>> 3;",
190
191 "var x = 0; return x || (1, 2, 3);",
192
193 "return a || (a, b, a, b, c = 5, 3); ",
194
195 "var a = 3; var b = 4; a = b; b = a; a = b; return a;",
196
197 "var a = 1; return [[a, 2], [a + 2]];",
198
199 "var a = 1; if (a || a < 0) { return 1; }",
200
201 "var b;"
202 "b = a.name;"
203 "b = a.name;"
204 "a.name = a;"
205 "b = a.name;"
206 "a.name = a;"
207 "return b;",
208
209 "var sum = 0;\n"
210 "outer: {\n"
211 " for (var x = 0; x < 10; ++x) {\n"
212 " for (var y = 0; y < 3; ++y) {\n"
213 " ++sum;\n"
214 " if (x + y == 12) { break outer; }\n"
215 " }\n"
216 " }\n"
217 "}\n"
218 "return sum;\n",
219
220 "var a = 1;"
221 "switch (a) {"
222 " case 1: return a * a + 1;"
223 " case 1: break;"
224 " case 2: return (a = 3) * a + (a = 4);"
225 " case 3:"
226 "}"
227 "return a;",
228
229 "for (var p of [0, 1, 2]) {}",
230
231 "var x = { 'a': 1, 'b': 2 };"
232 "for (x['a'] of [1,2,3]) { return x['a']; }",
233
234 "while (x == 4) {\n"
235 " var y = x + 1;\n"
236 " if (y == 2) break;\n"
237 " for (z['a'] of [0]) {\n"
238 " x += (x *= 3) + y;"
239 " }\n"
240 "}\n",
241
242 "function g(a, b) { return a.func(b + b, b); }\n"
243 "g(new (function Obj() { this.func = function() { return; }})(), 1)\n"};
244
245 OptimizedBytecodeSourcePositionTester tester(handles.main_isolate());
246 for (size_t i = 0; i < arraysize(test_scripts); ++i) {
247 CHECK(tester.SourcePositionsMatch(test_scripts[i]));
248 }
249 }
250
251 } // namespace interpreter
252 } // namespace internal
253 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698