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

Side by Side Diff: test/cctest/interpreter/generate-bytecode-expectations.cc

Issue 1698403002: [Interpreter] generate-bytecode-expectations improvements. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 10 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
1 // Copyright 2016 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <cstring> 5 #include <cstring>
6 #include <fstream> 6 #include <fstream>
7 7
8 #include "test/cctest/interpreter/bytecode-expectations-printer.h" 8 #include "test/cctest/interpreter/bytecode-expectations-printer.h"
9 9
10 #include "include/libplatform/libplatform.h" 10 #include "include/libplatform/libplatform.h"
(...skipping 10 matching lines...) Expand all
21 21
22 class ProgramOptions { 22 class ProgramOptions {
23 public: 23 public:
24 static ProgramOptions FromCommandLine(int argc, char** argv); 24 static ProgramOptions FromCommandLine(int argc, char** argv);
25 25
26 ProgramOptions() 26 ProgramOptions()
27 : parsing_failed_(false), 27 : parsing_failed_(false),
28 print_help_(false), 28 print_help_(false),
29 read_raw_js_snippet_(false), 29 read_raw_js_snippet_(false),
30 read_from_stdin_(false), 30 read_from_stdin_(false),
31 fix_(false),
32 print_banner_(true),
33 wrap_(true),
34 execute_(true),
31 const_pool_type_( 35 const_pool_type_(
32 BytecodeExpectationsPrinter::ConstantPoolType::kMixed) {} 36 BytecodeExpectationsPrinter::ConstantPoolType::kMixed) {}
33 37
34 bool Validate() const; 38 bool Validate() const;
35 39
36 bool parsing_failed() const { return parsing_failed_; } 40 bool parsing_failed() const { return parsing_failed_; }
37 bool print_help() const { return print_help_; } 41 bool print_help() const { return print_help_; }
38 bool read_raw_js_snippet() const { return read_raw_js_snippet_; } 42 bool read_raw_js_snippet() const { return read_raw_js_snippet_; }
39 bool read_from_stdin() const { return read_from_stdin_; } 43 bool read_from_stdin() const { return read_from_stdin_; }
40 std::string filename() const { return filename_; } 44 bool fix() const { return fix_; }
45 bool print_banner() const { return print_banner_; }
46 bool wrap() const { return wrap_; }
47 bool execute() const { return execute_; }
41 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type() const { 48 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type() const {
42 return const_pool_type_; 49 return const_pool_type_;
43 } 50 }
51 std::string input_filename() const { return input_filename_; }
52 std::string output_filename() const { return output_file_name_; }
53 std::string top_function_name() const { return top_function_name_; }
44 54
45 private: 55 private:
46 bool parsing_failed_; 56 bool parsing_failed_;
47 bool print_help_; 57 bool print_help_;
48 bool read_raw_js_snippet_; 58 bool read_raw_js_snippet_;
49 bool read_from_stdin_; 59 bool read_from_stdin_;
60 bool fix_;
61 bool print_banner_;
62 bool wrap_;
63 bool execute_;
50 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type_; 64 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type_;
51 std::string filename_; 65 std::string input_filename_;
66 std::string output_file_name_;
67 std::string top_function_name_;
68
69 friend void ParseOptionsHeader(ProgramOptions*, std::istream&);
52 }; 70 };
53 71
54 class ArrayBufferAllocator final : public v8::ArrayBuffer::Allocator { 72 class ArrayBufferAllocator final : public v8::ArrayBuffer::Allocator {
55 public: 73 public:
56 void* Allocate(size_t length) override { 74 void* Allocate(size_t length) override {
57 void* data = AllocateUninitialized(length); 75 void* data = AllocateUninitialized(length);
58 if (data != nullptr) memset(data, 0, length); 76 if (data != nullptr) memset(data, 0, length);
59 return data; 77 return data;
60 } 78 }
61 void* AllocateUninitialized(size_t length) override { return malloc(length); } 79 void* AllocateUninitialized(size_t length) override { return malloc(length); }
(...skipping 26 matching lines...) Expand all
88 } else if (strcmp(type_string, "mixed") == 0) { 106 } else if (strcmp(type_string, "mixed") == 0) {
89 return BytecodeExpectationsPrinter::ConstantPoolType::kMixed; 107 return BytecodeExpectationsPrinter::ConstantPoolType::kMixed;
90 } 108 }
91 return BytecodeExpectationsPrinter::ConstantPoolType::kUnknown; 109 return BytecodeExpectationsPrinter::ConstantPoolType::kUnknown;
92 } 110 }
93 111
94 // static 112 // static
95 ProgramOptions ProgramOptions::FromCommandLine(int argc, char** argv) { 113 ProgramOptions ProgramOptions::FromCommandLine(int argc, char** argv) {
96 ProgramOptions options; 114 ProgramOptions options;
97 115
98 if (argc <= 1) return options;
99
100 for (int i = 1; i < argc; ++i) { 116 for (int i = 1; i < argc; ++i) {
101 if (strcmp(argv[i], "--help") == 0) { 117 if (strcmp(argv[i], "--help") == 0) {
102 options.print_help_ = true; 118 options.print_help_ = true;
103 } else if (strcmp(argv[i], "--raw-js") == 0) { 119 } else if (strcmp(argv[i], "--raw-js") == 0) {
104 options.read_raw_js_snippet_ = true; 120 options.read_raw_js_snippet_ = true;
105 } else if (strncmp(argv[i], "--pool-type=", 12) == 0) { 121 } else if (strncmp(argv[i], "--pool-type=", 12) == 0) {
106 options.const_pool_type_ = ParseConstantPoolType(argv[i] + 12); 122 options.const_pool_type_ = ParseConstantPoolType(argv[i] + 12);
107 } else if (strcmp(argv[i], "--stdin") == 0) { 123 } else if (strcmp(argv[i], "--stdin") == 0) {
108 options.read_from_stdin_ = true; 124 options.read_from_stdin_ = true;
125 } else if (strcmp(argv[i], "--fix") == 0) {
126 options.fix_ = true;
127 } else if (strcmp(argv[i], "--no-banner") == 0) {
128 options.print_banner_ = false;
129 } else if (strcmp(argv[i], "--no-wrap") == 0) {
130 options.wrap_ = false;
131 } else if (strcmp(argv[i], "--no-execute") == 0) {
132 options.execute_ = false;
133 } else if (strncmp(argv[i], "--output=", 9) == 0) {
134 options.output_file_name_ = argv[i] + 9;
135 } else if (strncmp(argv[i], "--wrapper-name=", 15) == 0) {
136 options.top_function_name_ = argv[i] + 15;
109 } else if (strncmp(argv[i], "--", 2) != 0) { // It doesn't start with -- 137 } else if (strncmp(argv[i], "--", 2) != 0) { // It doesn't start with --
110 if (!options.filename_.empty()) { 138 if (!options.input_filename_.empty()) {
111 std::cerr << "ERROR: More than one input file specified\n"; 139 std::cerr << "ERROR: More than one input file specified\n";
112 options.parsing_failed_ = true; 140 options.parsing_failed_ = true;
113 break; 141 break;
114 } 142 }
115 options.filename_ = argv[i]; 143 options.input_filename_ = argv[i];
116 } else { 144 } else {
117 std::cerr << "ERROR: Unknonwn option " << argv[i] << "\n"; 145 std::cerr << "ERROR: Unknonwn option " << argv[i] << "\n";
118 options.parsing_failed_ = true; 146 options.parsing_failed_ = true;
119 break; 147 break;
120 } 148 }
121 } 149 }
122 150
123 return options; 151 return options;
124 } 152 }
125 153
154 bool ParseBoolean(const char* string) {
155 if (strcmp(string, "yes") == 0) {
156 return true;
157 } else if (strcmp(string, "no") == 0) {
158 return false;
159 } else {
160 UNREACHABLE();
161 return false;
162 }
163 }
164
165 void ParseOptionsHeader(ProgramOptions* options,
166 std::istream& stream) { // NOLINT
167 std::string line;
168
169 // Skip to the beginning of the options header
170 while (std::getline(stream, line)) {
171 if (line == "---") break;
172 }
173
174 while (std::getline(stream, line)) {
175 if (line.compare(0, 11, "pool type: ") == 0) {
176 options->const_pool_type_ = ParseConstantPoolType(line.c_str() + 11);
177 } else if (line.compare(0, 9, "execute: ") == 0) {
178 options->execute_ = ParseBoolean(line.c_str() + 9);
179 } else if (line.compare(0, 6, "wrap: ") == 0) {
180 options->wrap_ = ParseBoolean(line.c_str() + 6);
181 } else if (line.compare(0, 13, "wrapper name: ") == 0) {
182 options->top_function_name_ = line.c_str() + 14;
183 } else {
184 break;
185 }
186 }
187 }
188
189 const char* BooleanString(bool value) { return value ? "yes" : "no"; }
rmcilroy 2016/02/16 16:43:48 nit - move up near ParseBoolean
Stefano Sanfilippo 2016/02/16 20:28:26 Done.
190
191 const char* ConstantPoolTypeString(
192 BytecodeExpectationsPrinter::ConstantPoolType type) {
193 switch (type) {
194 case BytecodeExpectationsPrinter::ConstantPoolType::kDouble:
195 return "double";
196 case BytecodeExpectationsPrinter::ConstantPoolType::kInteger:
197 return "integer";
198 case BytecodeExpectationsPrinter::ConstantPoolType::kMixed:
199 return "mixed";
200 case BytecodeExpectationsPrinter::ConstantPoolType::kString:
201 return "string";
202 default:
203 UNREACHABLE();
204 return nullptr;
205 }
206 }
207
208 void EmitOptionsHeader(std::ostream& stream, // NOLINT
209 const ProgramOptions& options) {
210 stream << "---"
211 "\npool type: "
212 << ConstantPoolTypeString(options.const_pool_type())
213 << "\nexecute: " << BooleanString(options.execute())
214 << "\nwrap: " << BooleanString(options.wrap());
215
216 if (!options.top_function_name().empty()) {
217 stream << "\nwrapper name: " << options.top_function_name();
218 }
rmcilroy 2016/02/16 16:43:48 Could you emit a seperator between the options and
Stefano Sanfilippo 2016/02/16 20:28:26 I have updated the code to use the separator of th
219
220 stream << "\n\n";
221 }
222
126 bool ProgramOptions::Validate() const { 223 bool ProgramOptions::Validate() const {
127 if (parsing_failed_) return false; 224 if (parsing_failed_) return false;
128 if (print_help_) return true; 225 if (print_help_) return true;
129 226
130 if (const_pool_type_ == 227 if (const_pool_type_ ==
131 BytecodeExpectationsPrinter::ConstantPoolType::kUnknown) { 228 BytecodeExpectationsPrinter::ConstantPoolType::kUnknown) {
132 std::cerr << "ERROR: Unknown constant pool type.\n"; 229 std::cerr << "ERROR: Unknown constant pool type.\n";
133 return false; 230 return false;
134 } 231 }
135 232
136 if (!read_from_stdin_ && filename_.empty()) { 233 if (!read_from_stdin_ && input_filename_.empty()) {
137 std::cerr << "ERROR: No input file specified.\n"; 234 std::cerr << "ERROR: No input file specified.\n";
138 return false; 235 return false;
139 } 236 }
140 237
141 if (read_from_stdin_ && !filename_.empty()) { 238 if (read_from_stdin_ && !input_filename_.empty()) {
142 std::cerr << "ERROR: Reading from stdin, but input files supplied.\n"; 239 std::cerr << "ERROR: Reading from stdin, but input files supplied.\n";
143 return false; 240 return false;
144 } 241 }
145 242
243 if (!wrap_ && !top_function_name_.empty()) {
244 std::cerr << "ERROR: not wrapping, but wrapper name specified.\n";
245 return false;
246 }
247
rmcilroy 2016/02/16 16:43:48 You should also validate that --rebaseline and --r
Stefano Sanfilippo 2016/02/16 20:28:26 Done.
146 return true; 248 return true;
147 } 249 }
148 250
149 V8InitializationScope::V8InitializationScope(const char* exec_path) 251 V8InitializationScope::V8InitializationScope(const char* exec_path)
150 : platform_(v8::platform::CreateDefaultPlatform()) { 252 : platform_(v8::platform::CreateDefaultPlatform()) {
151 i::FLAG_ignition = true; 253 i::FLAG_ignition = true;
152 i::FLAG_always_opt = false; 254 i::FLAG_always_opt = false;
153 i::FLAG_allow_natives_syntax = true; 255 i::FLAG_allow_natives_syntax = true;
154 256
155 v8::V8::InitializeICU(); 257 v8::V8::InitializeICU();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 } 289 }
188 if (!found_begin_snippet) continue; 290 if (!found_begin_snippet) continue;
189 if (line == "\"") return true; 291 if (line == "\"") return true;
190 CHECK_GE(line.size(), 2u); // We should have the indent 292 CHECK_GE(line.size(), 2u); // We should have the indent
191 string_out->append(line.begin() + 2, line.end()); 293 string_out->append(line.begin() + 2, line.end());
192 *string_out += '\n'; 294 *string_out += '\n';
193 } 295 }
194 return false; 296 return false;
195 } 297 }
196 298
299 std::string UnescapeString(const std::string& escaped_string) {
300 std::string unescaped_string;
301 bool previous_was_backslash = false;
302 for (char c : escaped_string) {
303 if (previous_was_backslash) {
304 // If it was not an escape sequence, emit the backslash
rmcilroy 2016/02/16 16:43:48 /s/the backslash/the previous backslash./
Stefano Sanfilippo 2016/02/16 20:28:26 Done.
305 if (c != '\\' && c != '"') unescaped_string += '\\';
306 unescaped_string += c;
307 previous_was_backslash = false;
308 } else {
309 if (c == '\\') {
310 previous_was_backslash = true;
311 // Defer emission to the point where we can check if it was an escape.
312 } else {
313 unescaped_string += c;
314 }
315 }
316 }
317 return unescaped_string;
318 }
319
197 void ExtractSnippetsFromStream(std::vector<std::string>* snippet_list, 320 void ExtractSnippetsFromStream(std::vector<std::string>* snippet_list,
321 ProgramOptions* options,
198 std::istream& body_stream, // NOLINT 322 std::istream& body_stream, // NOLINT
199 bool read_raw_js_snippet) { 323 bool read_raw_js_snippet) {
200 if (read_raw_js_snippet) { 324 if (read_raw_js_snippet) {
201 snippet_list->push_back(ReadRawJSSnippet(body_stream)); 325 snippet_list->push_back(ReadRawJSSnippet(body_stream));
202 } else { 326 } else {
327 ParseOptionsHeader(options, body_stream);
rmcilroy 2016/02/16 16:43:48 This should only happen for --rebaseline I think (
Stefano Sanfilippo 2016/02/16 20:28:26 Please see below.
203 std::string snippet; 328 std::string snippet;
204 while (ReadNextSnippet(body_stream, &snippet)) { 329 while (ReadNextSnippet(body_stream, &snippet)) {
205 snippet_list->push_back(snippet); 330 snippet_list->push_back(UnescapeString(snippet));
206 } 331 }
207 } 332 }
208 } 333 }
209 334
210 bool ExtractSnippets(std::vector<std::string>* snippet_list, 335 bool ExtractSnippets(std::vector<std::string>* snippet_list,
211 const ProgramOptions& options) { 336 ProgramOptions* options) {
rmcilroy 2016/02/16 16:43:48 This should still be const, right? Any reason to m
Stefano Sanfilippo 2016/02/16 20:28:26 The reason is that ParseOptionsHeader called insid
rmcilroy 2016/02/17 10:16:59 I think the solution is to split out the opening o
rmcilroy 2016/02/17 10:16:59 I think the solution is to split out the opening o
Stefano Sanfilippo 2016/02/17 14:32:29 I've rewritten the piece using a better approach w
212 if (options.read_from_stdin()) { 337 if (options->read_from_stdin()) {
213 ExtractSnippetsFromStream(snippet_list, std::cin, 338 ExtractSnippetsFromStream(snippet_list, options, std::cin,
214 options.read_raw_js_snippet()); 339 options->read_raw_js_snippet());
215 } else { 340 } else {
216 std::ifstream body_file(options.filename().c_str()); 341 std::ifstream body_file(options->input_filename().c_str());
217 if (!body_file.is_open()) { 342 if (!body_file.is_open()) {
218 std::cerr << "ERROR: Could not open '" << options.filename() << "'.\n"; 343 std::cerr << "ERROR: Could not open '" << options->input_filename()
344 << "'.\n";
219 return false; 345 return false;
220 } 346 }
221 ExtractSnippetsFromStream(snippet_list, body_file, 347 ExtractSnippetsFromStream(snippet_list, options, body_file,
222 options.read_raw_js_snippet()); 348 options->read_raw_js_snippet());
223 } 349 }
224 return true; 350 return true;
225 } 351 }
226 352
227 void GenerateExpectationsFile( 353 void GenerateExpectationsFile(std::ostream& stream, // NOLINT
228 std::ostream& stream, // NOLINT 354 const std::vector<std::string>& snippet_list,
229 const std::vector<std::string>& snippet_list, 355 const ProgramOptions& options,
230 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type, 356 const char* exec_path) {
231 const char* exec_path) {
232 V8InitializationScope platform(exec_path); 357 V8InitializationScope platform(exec_path);
233 { 358 {
234 v8::Isolate::Scope isolate_scope(platform.isolate()); 359 v8::Isolate::Scope isolate_scope(platform.isolate());
235 v8::HandleScope handle_scope(platform.isolate()); 360 v8::HandleScope handle_scope(platform.isolate());
236 v8::Local<v8::Context> context = v8::Context::New(platform.isolate()); 361 v8::Local<v8::Context> context = v8::Context::New(platform.isolate());
237 v8::Context::Scope context_scope(context); 362 v8::Context::Scope context_scope(context);
238 363
239 stream << "#\n# Autogenerated by generate-bytecode-expectations\n#\n\n"; 364 if (options.print_banner()) {
365 stream << "#\n# Autogenerated by generate-bytecode-expectations\n#\n\n";
366 }
240 367
241 BytecodeExpectationsPrinter printer(platform.isolate(), const_pool_type); 368 EmitOptionsHeader(stream, options);
369
370 BytecodeExpectationsPrinter printer(platform.isolate(),
371 options.const_pool_type());
372 printer.set_wrap(options.wrap());
373 printer.set_execute(options.execute());
374 if (!options.top_function_name().empty()) {
375 printer.set_top_function_name(options.top_function_name());
376 }
377
242 for (const std::string& snippet : snippet_list) { 378 for (const std::string& snippet : snippet_list) {
243 printer.PrintExpectation(stream, snippet); 379 printer.PrintExpectation(stream, snippet);
244 } 380 }
245 } 381 }
246 } 382 }
247 383
248 void PrintUsage(const char* exec_path) { 384 void PrintUsage(const char* exec_path) {
249 std::cerr 385 std::cerr
250 << "\nUsage: " << exec_path 386 << "\nUsage: " << exec_path
251 << " [OPTIONS]... [INPUT FILE]\n\n" 387 << " [OPTIONS]... [INPUT FILE]\n\n"
252 "Options:\n" 388 "Options:\n"
253 " --help Print this help message.\n" 389 " --help Print this help message.\n"
254 " --raw-js Read raw JavaScript, instead of the output format.\n" 390 " --raw-js Read raw JavaScript, instead of the output format.\n"
255 " --stdin Read from standard input instead of file.\n" 391 " --stdin Read from standard input instead of file.\n"
392 " --fix Overwrite input file.\n"
rmcilroy 2016/02/16 16:43:48 Call this "--rebaseline Rebaseline input snippet
Stefano Sanfilippo 2016/02/16 20:28:26 Done.
393 " --no-banner Do not add the \"generated by\" banner.\n"
rmcilroy 2016/02/16 16:43:48 Why is this one required? All golden files should
Stefano Sanfilippo 2016/02/16 20:28:26 ATM the banner is emitted by the utility before ca
rmcilroy 2016/02/17 10:17:00 I think the banner should be printed by this tool
Stefano Sanfilippo 2016/02/17 14:32:29 Done. I ended up changing the API from accepting a
394 " --no-wrap Do not wrap the snippet in a function.\n"
395 " --no-execute Do not execute after compilation.\n"
396 " --output=file.name Specify the output file. "
397 "If not specified, output goes to stdout.\n"
398 " --wrapper-name=foo Specify the name of the wrapper function.\n"
256 " --pool-type=(int|double|string|mixed)\n" 399 " --pool-type=(int|double|string|mixed)\n"
257 " specify the type of the entries in the constant pool " 400 " Specify the type of the entries in the constant pool "
258 "(default: mixed).\n" 401 "(default: mixed).\n"
259 "\n" 402 "\n"
260 "Each raw JavaScript file is interpreted as a single snippet.\n\n" 403 "Each raw JavaScript file is interpreted as a single snippet.\n\n"
261 "This tool is intended as a help in writing tests.\n" 404 "This tool is intended as a help in writing tests.\n"
262 "Please, DO NOT blindly copy and paste the output " 405 "Please, DO NOT blindly copy and paste the output "
263 "into the test suite.\n"; 406 "into the test suite.\n";
264 } 407 }
265 408
266 } // namespace 409 } // namespace
267 410
268 int main(int argc, char** argv) { 411 int main(int argc, char** argv) {
269 ProgramOptions options = ProgramOptions::FromCommandLine(argc, argv); 412 ProgramOptions options = ProgramOptions::FromCommandLine(argc, argv);
270 413
271 if (!options.Validate() || options.print_help()) { 414 if (!options.Validate() || options.print_help()) {
272 PrintUsage(argv[0]); 415 PrintUsage(argv[0]);
273 return options.print_help() ? 0 : 1; 416 return options.print_help() ? 0 : 1;
274 } 417 }
275 418
276 std::vector<std::string> snippet_list; 419 std::vector<std::string> snippet_list;
277 if (!ExtractSnippets(&snippet_list, options)) { 420 if (!ExtractSnippets(&snippet_list, &options)) {
278 return 2; 421 return 2;
279 } 422 }
280 423
281 GenerateExpectationsFile(std::cout, snippet_list, options.const_pool_type(), 424 CHECK(options.Validate());
282 argv[0]); 425
426 if (!options.output_filename().empty() || options.fix()) {
427 std::ofstream output_file(options.fix()
428 ? options.input_filename().c_str()
429 : options.output_filename().c_str());
430 if (!output_file.is_open()) {
431 std::cerr << "ERROR: Could not open '" << options.output_filename()
432 << "' for writing.\n";
433 return 3;
434 }
435 GenerateExpectationsFile(output_file, snippet_list, options, argv[0]);
436 } else {
437 GenerateExpectationsFile(std::cout, snippet_list, options, argv[0]);
438 }
283 } 439 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698