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

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: Reverting to the old API, remove PrepareI/OStream. 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 rebaseline_(false),
32 wrap_(true),
33 execute_(true),
31 const_pool_type_( 34 const_pool_type_(
32 BytecodeExpectationsPrinter::ConstantPoolType::kMixed) {} 35 BytecodeExpectationsPrinter::ConstantPoolType::kMixed) {}
33 36
34 bool Validate() const; 37 bool Validate() const;
35 38
36 bool parsing_failed() const { return parsing_failed_; } 39 bool parsing_failed() const { return parsing_failed_; }
37 bool print_help() const { return print_help_; } 40 bool print_help() const { return print_help_; }
38 bool read_raw_js_snippet() const { return read_raw_js_snippet_; } 41 bool read_raw_js_snippet() const { return read_raw_js_snippet_; }
39 bool read_from_stdin() const { return read_from_stdin_; } 42 bool read_from_stdin() const { return read_from_stdin_; }
40 std::string filename() const { return filename_; } 43 bool write_to_stdout() const {
44 return output_filename_.empty() && !rebaseline_;
45 }
46 bool rebaseline() const { return rebaseline_; }
47 bool wrap() const { return wrap_; }
48 bool execute() const { return execute_; }
41 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type() const { 49 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type() const {
42 return const_pool_type_; 50 return const_pool_type_;
43 } 51 }
52 std::string input_filename() const { return input_filename_; }
53 std::string output_filename() const { return output_filename_; }
54 std::string top_function_name() const { return top_function_name_; }
55
56 void set_const_pool_type(
57 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type) {
58 const_pool_type_ = const_pool_type;
59 }
60 void set_execute(bool execute) { execute_ = execute; }
61 void set_wrap(bool wrap) { wrap_ = wrap; }
62 void set_top_function_name(const std::string& top_function_name) {
63 top_function_name_ = top_function_name;
64 }
44 65
45 private: 66 private:
46 bool parsing_failed_; 67 bool parsing_failed_;
47 bool print_help_; 68 bool print_help_;
48 bool read_raw_js_snippet_; 69 bool read_raw_js_snippet_;
49 bool read_from_stdin_; 70 bool read_from_stdin_;
71 bool rebaseline_;
72 bool wrap_;
73 bool execute_;
50 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type_; 74 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type_;
51 std::string filename_; 75 std::string input_filename_;
76 std::string output_filename_;
77 std::string top_function_name_;
52 }; 78 };
53 79
54 class ArrayBufferAllocator final : public v8::ArrayBuffer::Allocator { 80 class ArrayBufferAllocator final : public v8::ArrayBuffer::Allocator {
55 public: 81 public:
56 void* Allocate(size_t length) override { 82 void* Allocate(size_t length) override {
57 void* data = AllocateUninitialized(length); 83 void* data = AllocateUninitialized(length);
58 if (data != nullptr) memset(data, 0, length); 84 if (data != nullptr) memset(data, 0, length);
59 return data; 85 return data;
60 } 86 }
61 void* AllocateUninitialized(size_t length) override { return malloc(length); } 87 void* AllocateUninitialized(size_t length) override { return malloc(length); }
(...skipping 26 matching lines...) Expand all
88 } else if (strcmp(type_string, "mixed") == 0) { 114 } else if (strcmp(type_string, "mixed") == 0) {
89 return BytecodeExpectationsPrinter::ConstantPoolType::kMixed; 115 return BytecodeExpectationsPrinter::ConstantPoolType::kMixed;
90 } 116 }
91 return BytecodeExpectationsPrinter::ConstantPoolType::kUnknown; 117 return BytecodeExpectationsPrinter::ConstantPoolType::kUnknown;
92 } 118 }
93 119
94 // static 120 // static
95 ProgramOptions ProgramOptions::FromCommandLine(int argc, char** argv) { 121 ProgramOptions ProgramOptions::FromCommandLine(int argc, char** argv) {
96 ProgramOptions options; 122 ProgramOptions options;
97 123
98 if (argc <= 1) return options;
99
100 for (int i = 1; i < argc; ++i) { 124 for (int i = 1; i < argc; ++i) {
101 if (strcmp(argv[i], "--help") == 0) { 125 if (strcmp(argv[i], "--help") == 0) {
102 options.print_help_ = true; 126 options.print_help_ = true;
103 } else if (strcmp(argv[i], "--raw-js") == 0) { 127 } else if (strcmp(argv[i], "--raw-js") == 0) {
104 options.read_raw_js_snippet_ = true; 128 options.read_raw_js_snippet_ = true;
105 } else if (strncmp(argv[i], "--pool-type=", 12) == 0) { 129 } else if (strncmp(argv[i], "--pool-type=", 12) == 0) {
106 options.const_pool_type_ = ParseConstantPoolType(argv[i] + 12); 130 options.const_pool_type_ = ParseConstantPoolType(argv[i] + 12);
107 } else if (strcmp(argv[i], "--stdin") == 0) { 131 } else if (strcmp(argv[i], "--stdin") == 0) {
108 options.read_from_stdin_ = true; 132 options.read_from_stdin_ = true;
133 } else if (strcmp(argv[i], "--rebaseline") == 0) {
134 options.rebaseline_ = true;
135 } else if (strcmp(argv[i], "--no-wrap") == 0) {
136 options.wrap_ = false;
137 } else if (strcmp(argv[i], "--no-execute") == 0) {
138 options.execute_ = false;
139 } else if (strncmp(argv[i], "--output=", 9) == 0) {
140 options.output_filename_ = argv[i] + 9;
141 } else if (strncmp(argv[i], "--wrapper-name=", 15) == 0) {
142 options.top_function_name_ = argv[i] + 15;
109 } else if (strncmp(argv[i], "--", 2) != 0) { // It doesn't start with -- 143 } else if (strncmp(argv[i], "--", 2) != 0) { // It doesn't start with --
110 if (!options.filename_.empty()) { 144 if (!options.input_filename_.empty()) {
111 std::cerr << "ERROR: More than one input file specified\n"; 145 std::cerr << "ERROR: More than one input file specified\n";
112 options.parsing_failed_ = true; 146 options.parsing_failed_ = true;
113 break; 147 break;
114 } 148 }
115 options.filename_ = argv[i]; 149 options.input_filename_ = argv[i];
116 } else { 150 } else {
117 std::cerr << "ERROR: Unknonwn option " << argv[i] << "\n"; 151 std::cerr << "ERROR: Unknonwn option " << argv[i] << "\n";
118 options.parsing_failed_ = true; 152 options.parsing_failed_ = true;
119 break; 153 break;
120 } 154 }
121 } 155 }
122 156
123 return options; 157 return options;
124 } 158 }
125 159
160 bool ParseBoolean(const char* string) {
161 if (strcmp(string, "yes") == 0) {
162 return true;
163 } else if (strcmp(string, "no") == 0) {
164 return false;
165 } else {
166 UNREACHABLE();
167 return false;
168 }
169 }
170
171 void UpdateOptionsFromHeader(ProgramOptions* options,
rmcilroy 2016/02/18 09:58:33 Nit - make this a member function of ProgramOption
Stefano Sanfilippo 2016/02/18 11:14:12 Done.
172 std::istream& stream) { // NOLINT
173 std::string line;
174
175 // Skip to the beginning of the options header
176 while (std::getline(stream, line)) {
177 if (line == "---") break;
178 }
179
180 while (std::getline(stream, line)) {
181 if (line.compare(0, 11, "pool type: ") == 0) {
182 options->set_const_pool_type(ParseConstantPoolType(line.c_str() + 11));
183 } else if (line.compare(0, 9, "execute: ") == 0) {
184 options->set_execute(ParseBoolean(line.c_str() + 9));
185 } else if (line.compare(0, 6, "wrap: ") == 0) {
186 options->set_wrap(ParseBoolean(line.c_str() + 6));
187 } else if (line.compare(0, 14, "wrapper name: ") == 0) {
188 options->set_top_function_name(line.c_str() + 14);
189 } else if (line == "---") {
190 break;
191 } else if (line.empty()) {
192 continue;
193 } else {
194 UNREACHABLE();
195 return;
196 }
197 }
198 }
199
126 bool ProgramOptions::Validate() const { 200 bool ProgramOptions::Validate() const {
127 if (parsing_failed_) return false; 201 if (parsing_failed_) return false;
128 if (print_help_) return true; 202 if (print_help_) return true;
129 203
130 if (const_pool_type_ == 204 if (const_pool_type_ ==
131 BytecodeExpectationsPrinter::ConstantPoolType::kUnknown) { 205 BytecodeExpectationsPrinter::ConstantPoolType::kUnknown) {
132 std::cerr << "ERROR: Unknown constant pool type.\n"; 206 std::cerr << "ERROR: Unknown constant pool type.\n";
133 return false; 207 return false;
134 } 208 }
135 209
136 if (!read_from_stdin_ && filename_.empty()) { 210 if (!read_from_stdin_ && input_filename_.empty()) {
137 std::cerr << "ERROR: No input file specified.\n"; 211 std::cerr << "ERROR: No input file specified.\n";
138 return false; 212 return false;
139 } 213 }
140 214
141 if (read_from_stdin_ && !filename_.empty()) { 215 if (read_from_stdin_ && !input_filename_.empty()) {
142 std::cerr << "ERROR: Reading from stdin, but input files supplied.\n"; 216 std::cerr << "ERROR: Reading from stdin, but input files supplied.\n";
143 return false; 217 return false;
144 } 218 }
145 219
220 if (!wrap_ && !top_function_name_.empty()) {
221 std::cerr << "ERROR: Not wrapping, but wrapper name specified.\n";
222 return false;
223 }
224
225 if (rebaseline_ && read_raw_js_snippet_) {
226 std::cerr << "ERROR: Cannot use --rebaseline on a raw JS snippet.\n";
227 return false;
228 }
229
146 return true; 230 return true;
147 } 231 }
148 232
149 V8InitializationScope::V8InitializationScope(const char* exec_path) 233 V8InitializationScope::V8InitializationScope(const char* exec_path)
150 : platform_(v8::platform::CreateDefaultPlatform()) { 234 : platform_(v8::platform::CreateDefaultPlatform()) {
151 i::FLAG_ignition = true; 235 i::FLAG_ignition = true;
152 i::FLAG_always_opt = false; 236 i::FLAG_always_opt = false;
153 i::FLAG_allow_natives_syntax = true; 237 i::FLAG_allow_natives_syntax = true;
154 238
155 v8::V8::InitializeICU(); 239 v8::V8::InitializeICU();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 } 271 }
188 if (!found_begin_snippet) continue; 272 if (!found_begin_snippet) continue;
189 if (line == "\"") return true; 273 if (line == "\"") return true;
190 CHECK_GE(line.size(), 2u); // We should have the indent 274 CHECK_GE(line.size(), 2u); // We should have the indent
191 string_out->append(line.begin() + 2, line.end()); 275 string_out->append(line.begin() + 2, line.end());
192 *string_out += '\n'; 276 *string_out += '\n';
193 } 277 }
194 return false; 278 return false;
195 } 279 }
196 280
197 void ExtractSnippetsFromStream(std::vector<std::string>* snippet_list, 281 std::string UnescapeString(const std::string& escaped_string) {
198 std::istream& body_stream, // NOLINT 282 std::string unescaped_string;
199 bool read_raw_js_snippet) { 283 bool previous_was_backslash = false;
284 for (char c : escaped_string) {
285 if (previous_was_backslash) {
286 // If it was not an escape sequence, emit the previous backslash
287 if (c != '\\' && c != '"') unescaped_string += '\\';
288 unescaped_string += c;
289 previous_was_backslash = false;
290 } else {
291 if (c == '\\') {
292 previous_was_backslash = true;
293 // Defer emission to the point where we can check if it was an escape.
294 } else {
295 unescaped_string += c;
296 }
297 }
298 }
299 return unescaped_string;
300 }
301
302 void ExtractSnippets(std::vector<std::string>* snippet_list,
303 std::istream& body_stream, // NOLINT
304 bool read_raw_js_snippet) {
200 if (read_raw_js_snippet) { 305 if (read_raw_js_snippet) {
201 snippet_list->push_back(ReadRawJSSnippet(body_stream)); 306 snippet_list->push_back(ReadRawJSSnippet(body_stream));
202 } else { 307 } else {
203 std::string snippet; 308 std::string snippet;
204 while (ReadNextSnippet(body_stream, &snippet)) { 309 while (ReadNextSnippet(body_stream, &snippet)) {
205 snippet_list->push_back(snippet); 310 snippet_list->push_back(UnescapeString(snippet));
206 } 311 }
207 } 312 }
208 } 313 }
209 314
210 bool ExtractSnippets(std::vector<std::string>* snippet_list, 315 const char* ConstantPoolTypeToString(
211 const ProgramOptions& options) { 316 BytecodeExpectationsPrinter::ConstantPoolType type) {
212 if (options.read_from_stdin()) { 317 switch (type) {
213 ExtractSnippetsFromStream(snippet_list, std::cin, 318 case BytecodeExpectationsPrinter::ConstantPoolType::kDouble:
214 options.read_raw_js_snippet()); 319 return "double";
215 } else { 320 case BytecodeExpectationsPrinter::ConstantPoolType::kInteger:
216 std::ifstream body_file(options.filename().c_str()); 321 return "integer";
217 if (!body_file.is_open()) { 322 case BytecodeExpectationsPrinter::ConstantPoolType::kMixed:
218 std::cerr << "ERROR: Could not open '" << options.filename() << "'.\n"; 323 return "mixed";
219 return false; 324 case BytecodeExpectationsPrinter::ConstantPoolType::kString:
220 } 325 return "string";
221 ExtractSnippetsFromStream(snippet_list, body_file, 326 default:
222 options.read_raw_js_snippet()); 327 UNREACHABLE();
328 return nullptr;
223 } 329 }
224 return true;
225 } 330 }
226 331
227 void GenerateExpectationsFile( 332 const char* BooleanToString(bool value) { return value ? "yes" : "no"; }
228 std::ostream& stream, // NOLINT 333
229 const std::vector<std::string>& snippet_list, 334 void PrintOptionsHeader(std::ostream& stream, // NOLINT,
rmcilroy 2016/02/18 09:58:33 Also make this a member on ProgramOptions and call
Stefano Sanfilippo 2016/02/18 11:14:12 Done the first part. I have grouped helpers at the
230 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type, 335 const ProgramOptions& options) {
231 const char* exec_path) { 336 stream << "---"
337 "\npool type: "
338 << ConstantPoolTypeToString(options.const_pool_type())
339 << "\nexecute: " << BooleanToString(options.execute())
340 << "\nwrap: " << BooleanToString(options.wrap());
341
342 if (!options.top_function_name().empty()) {
343 stream << "\nwrapper name: " << options.top_function_name();
344 }
345
346 stream << "\n\n";
347 }
348
349 void GenerateExpectationsFile(std::ostream& stream, // NOLINT
350 const std::vector<std::string>& snippet_list,
351 const ProgramOptions& options,
352 const char* exec_path) {
232 V8InitializationScope platform(exec_path); 353 V8InitializationScope platform(exec_path);
233 { 354 {
234 v8::Isolate::Scope isolate_scope(platform.isolate()); 355 v8::Isolate::Scope isolate_scope(platform.isolate());
235 v8::HandleScope handle_scope(platform.isolate()); 356 v8::HandleScope handle_scope(platform.isolate());
236 v8::Local<v8::Context> context = v8::Context::New(platform.isolate()); 357 v8::Local<v8::Context> context = v8::Context::New(platform.isolate());
237 v8::Context::Scope context_scope(context); 358 v8::Context::Scope context_scope(context);
238 359
360 BytecodeExpectationsPrinter printer(platform.isolate(),
361 options.const_pool_type());
362 printer.set_wrap(options.wrap());
363 printer.set_execute(options.execute());
364 if (!options.top_function_name().empty()) {
365 printer.set_top_function_name(options.top_function_name());
366 }
367
239 stream << "#\n# Autogenerated by generate-bytecode-expectations\n#\n\n"; 368 stream << "#\n# Autogenerated by generate-bytecode-expectations\n#\n\n";
240 369 PrintOptionsHeader(stream, options);
241 BytecodeExpectationsPrinter printer(platform.isolate(), const_pool_type);
242 for (const std::string& snippet : snippet_list) { 370 for (const std::string& snippet : snippet_list) {
243 printer.PrintExpectation(stream, snippet); 371 printer.PrintExpectation(stream, snippet);
244 } 372 }
245 } 373 }
246 } 374 }
247 375
248 void PrintUsage(const char* exec_path) { 376 void PrintUsage(const char* exec_path) {
249 std::cerr 377 std::cerr
250 << "\nUsage: " << exec_path 378 << "\nUsage: " << exec_path
251 << " [OPTIONS]... [INPUT FILE]\n\n" 379 << " [OPTIONS]... [INPUT FILE]\n\n"
252 "Options:\n" 380 "Options:\n"
253 " --help Print this help message.\n" 381 " --help Print this help message.\n"
254 " --raw-js Read raw JavaScript, instead of the output format.\n" 382 " --raw-js Read raw JavaScript, instead of the output format.\n"
255 " --stdin Read from standard input instead of file.\n" 383 " --stdin Read from standard input instead of file.\n"
384 " --rebaseline Rebaseline input snippet file.\n"
385 " --no-wrap Do not wrap the snippet in a function.\n"
386 " --no-execute Do not execute after compilation.\n"
387 " --wrapper-name=foo Specify the name of the wrapper function.\n"
388 " --output=file.name\n"
389 " Specify the output file. If not specified, output goes to "
390 "stdout.\n"
256 " --pool-type=(int|double|string|mixed)\n" 391 " --pool-type=(int|double|string|mixed)\n"
257 " specify the type of the entries in the constant pool " 392 " Specify the type of the entries in the constant pool "
258 "(default: mixed).\n" 393 "(default: mixed).\n"
259 "\n" 394 "\n"
395 "When using --rebaseline, flags --no-wrap, --no-execute, "
396 "--wrapper-name and \n--pool-type will be overridden by the options "
397 "specified in the input file\n"
398 "header.\n\n"
260 "Each raw JavaScript file is interpreted as a single snippet.\n\n" 399 "Each raw JavaScript file is interpreted as a single snippet.\n\n"
261 "This tool is intended as a help in writing tests.\n" 400 "This tool is intended as a help in writing tests.\n"
262 "Please, DO NOT blindly copy and paste the output " 401 "Please, DO NOT blindly copy and paste the output "
263 "into the test suite.\n"; 402 "into the test suite.\n";
264 } 403 }
265 404
266 } // namespace 405 } // namespace
267 406
268 int main(int argc, char** argv) { 407 int main(int argc, char** argv) {
269 ProgramOptions options = ProgramOptions::FromCommandLine(argc, argv); 408 ProgramOptions options = ProgramOptions::FromCommandLine(argc, argv);
270 409
271 if (!options.Validate() || options.print_help()) { 410 if (!options.Validate() || options.print_help()) {
272 PrintUsage(argv[0]); 411 PrintUsage(argv[0]);
273 return options.print_help() ? 0 : 1; 412 return options.print_help() ? 0 : 1;
274 } 413 }
275 414
415 std::ifstream input_file_handle;
416 if (!options.read_from_stdin()) {
417 input_file_handle.open(options.input_filename().c_str());
418 if (!input_file_handle.is_open()) {
419 std::cerr << "ERROR: Could not open '" << options.input_filename()
420 << "' for reading.\n";
421 return 2;
422 }
423 }
424 std::istream& input_stream =
425 options.read_from_stdin() ? std::cin : input_file_handle;
426
427 if (!options.rebaseline()) {
428 UpdateOptionsFromHeader(&options, input_stream);
429 }
430 CHECK(options.Validate());
431
276 std::vector<std::string> snippet_list; 432 std::vector<std::string> snippet_list;
277 if (!ExtractSnippets(&snippet_list, options)) { 433 ExtractSnippets(&snippet_list, input_stream, options.read_raw_js_snippet());
278 return 2; 434
435 std::ofstream output_file_handle;
436 if (!options.write_to_stdout()) {
437 output_file_handle.open(options.rebaseline()
438 ? options.input_filename().c_str()
439 : options.output_filename().c_str());
440 if (!output_file_handle.is_open()) {
441 std::cerr << "ERROR: Could not open '" << options.output_filename()
442 << "' for writing.\n";
443 return 3;
444 }
279 } 445 }
446 std::ostream& output_stream =
447 options.write_to_stdout() ? std::cout : output_file_handle;
280 448
281 GenerateExpectationsFile(std::cout, snippet_list, options.const_pool_type(), 449 GenerateExpectationsFile(output_stream, snippet_list, options, argv[0]);
282 argv[0]);
283 } 450 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698