Skip to content

Commit 8ae6592

Browse files
galpeterakosthekiss
authored andcommitted
Move snapshot generation function to the snapshot tool (#2057)
Now there is a snapshot tool which can merge snapshots but was unable to generate snapshots by itself. This change moves the snapshot generation utilities to the snapshot tool. JerryScript-DCO-1.0-Signed-off-by: Peter Gal pgal.u-szeged@partner.samsung.com
1 parent ee24965 commit 8ae6592

File tree

4 files changed

+301
-144
lines changed

4 files changed

+301
-144
lines changed

jerry-main/main-unix-snapshot.c

Lines changed: 276 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "jerryscript.h"
1919
#include "jerryscript-port.h"
20+
#include "jerryscript-port-default.h"
2021

2122
#include "cli.h"
2223

@@ -33,6 +34,52 @@
3334

3435
static uint8_t input_buffer[ JERRY_BUFFER_SIZE ];
3536
static uint32_t output_buffer[ JERRY_BUFFER_SIZE / 4 ];
37+
static const char *output_file_name_p = "js.snapshot";
38+
39+
/**
40+
* Check whether JerryScript has a requested feature enabled or not. If not,
41+
* print a warning message.
42+
*
43+
* @return the status of the feature.
44+
*/
45+
static bool
46+
check_feature (jerry_feature_t feature, /**< feature to check */
47+
const char *option) /**< command line option that triggered this check */
48+
{
49+
if (!jerry_is_feature_enabled (feature))
50+
{
51+
jerry_port_default_set_log_level (JERRY_LOG_LEVEL_WARNING);
52+
jerry_port_log (JERRY_LOG_LEVEL_WARNING, "Ignoring '%s' option because this feature is disabled!\n", option);
53+
return false;
54+
}
55+
return true;
56+
} /* check_feature */
57+
58+
/**
59+
* Utility method to check and print error in the given cli state.
60+
*
61+
* @return true - if any error is detected
62+
* false - if there is no error in the cli state
63+
*/
64+
static bool
65+
check_cli_error (const cli_state_t *const cli_state_p)
66+
{
67+
if (cli_state_p->error != NULL)
68+
{
69+
if (cli_state_p->arg != NULL)
70+
{
71+
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s %s\n", cli_state_p->error, cli_state_p->arg);
72+
}
73+
else
74+
{
75+
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", cli_state_p->error);
76+
}
77+
78+
return true;
79+
}
80+
81+
return false;
82+
} /* check_cli_error */
3683

3784
/**
3885
* Loading a single file into the memory.
@@ -73,6 +120,227 @@ read_file (uint8_t *input_pos_p, /**< next position in the input buffer */
73120
return bytes_read;
74121
} /* read_file */
75122

123+
/**
124+
* Generate command line option IDs
125+
*/
126+
typedef enum
127+
{
128+
OPT_GENERATE_HELP,
129+
OPT_GENERATE_CONTEXT,
130+
OPT_GENERATE_SHOW_OP,
131+
OPT_GENERATE_LITERAL_LIST,
132+
OPT_GENERATE_LITERAL_C,
133+
OPT_GENERATE_OUT,
134+
} generate_opt_id_t;
135+
136+
/**
137+
* Generate command line options
138+
*/
139+
static const cli_opt_t generate_opts[] =
140+
{
141+
CLI_OPT_DEF (.id = OPT_GENERATE_HELP, .opt = "h", .longopt = "help",
142+
.help = "print this help and exit"),
143+
CLI_OPT_DEF (.id = OPT_GENERATE_SHOW_OP, .longopt = "show-opcodes",
144+
.help = "print generated opcodes"),
145+
CLI_OPT_DEF (.id = OPT_GENERATE_CONTEXT, .opt = "c", .longopt = "context",
146+
.meta = "MODE",
147+
.help = "specify the execution context of the snapshot: "
148+
"global or eval (default: global)."),
149+
CLI_OPT_DEF (.id = OPT_GENERATE_LITERAL_LIST, .longopt = "save-literals-list-format",
150+
.meta = "FILE",
151+
.help = "export literals found in parsed JS input (in list format)"),
152+
CLI_OPT_DEF (.id = OPT_GENERATE_LITERAL_C, .longopt = "save-literals-c-format",
153+
.meta = "FILE",
154+
.help = "export literals found in parsed JS input (in C source format)"),
155+
CLI_OPT_DEF (.id = OPT_GENERATE_OUT, .opt = "o", .meta="FILE",
156+
.help = "specify output file name (default: js.snapshot)"),
157+
CLI_OPT_DEF (.id = CLI_OPT_DEFAULT, .meta = "FILE",
158+
.help = "input snapshot file")
159+
};
160+
161+
/**
162+
* Process 'generate' command.
163+
*
164+
* @return error code (0 - no error)
165+
*/
166+
static int
167+
process_generate (cli_state_t *cli_state_p, /**< cli state */
168+
int argc, /**< number of arguments */
169+
char *prog_name_p) /**< program name */
170+
{
171+
(void) argc;
172+
173+
bool is_save_literals_mode_in_c_format = false;
174+
bool is_snapshot_mode_for_global = true;
175+
jerry_init_flag_t flags = JERRY_INIT_EMPTY;
176+
177+
uint32_t number_of_files = 0;
178+
uint8_t *source_p = input_buffer;
179+
size_t source_length = 0;
180+
const char *save_literals_file_name_p = NULL;
181+
182+
cli_change_opts (cli_state_p, generate_opts);
183+
184+
for (int id = cli_consume_option (cli_state_p); id != CLI_OPT_END; id = cli_consume_option (cli_state_p))
185+
{
186+
switch (id)
187+
{
188+
case OPT_GENERATE_HELP:
189+
{
190+
cli_help (prog_name_p, "generate", generate_opts);
191+
return JERRY_STANDALONE_EXIT_CODE_OK;
192+
}
193+
case OPT_GENERATE_OUT:
194+
{
195+
output_file_name_p = cli_consume_string (cli_state_p);
196+
break;
197+
}
198+
case OPT_GENERATE_LITERAL_LIST:
199+
case OPT_GENERATE_LITERAL_C:
200+
{
201+
if (save_literals_file_name_p != NULL)
202+
{
203+
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: literal file name already specified");
204+
return JERRY_STANDALONE_EXIT_CODE_FAIL;
205+
}
206+
207+
is_save_literals_mode_in_c_format = (id == OPT_GENERATE_LITERAL_C);
208+
save_literals_file_name_p = cli_consume_string (cli_state_p);
209+
break;
210+
}
211+
case OPT_GENERATE_SHOW_OP:
212+
{
213+
if (check_feature (JERRY_FEATURE_PARSER_DUMP, cli_state_p->arg))
214+
{
215+
jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG);
216+
flags |= JERRY_INIT_SHOW_OPCODES;
217+
}
218+
break;
219+
}
220+
case OPT_GENERATE_CONTEXT:
221+
{
222+
const char *mode_str_p = cli_consume_string (cli_state_p);
223+
224+
if (cli_state_p->error != NULL)
225+
{
226+
break;
227+
}
228+
229+
if (!strcmp ("global", mode_str_p))
230+
{
231+
is_snapshot_mode_for_global = true;
232+
}
233+
else if (!strcmp ("eval", mode_str_p))
234+
{
235+
is_snapshot_mode_for_global = false;
236+
}
237+
else
238+
{
239+
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Incorrect argument for context mode: %s\n", mode_str_p);
240+
return JERRY_STANDALONE_EXIT_CODE_FAIL;
241+
}
242+
break;
243+
}
244+
case CLI_OPT_DEFAULT:
245+
{
246+
const char *file_name_p = cli_consume_string (cli_state_p);
247+
248+
if (cli_state_p->error == NULL)
249+
{
250+
source_length = read_file (source_p, file_name_p);
251+
252+
if (source_length == 0)
253+
{
254+
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Input file is empty\n");
255+
return JERRY_STANDALONE_EXIT_CODE_FAIL;
256+
}
257+
258+
number_of_files++;
259+
}
260+
break;
261+
}
262+
default:
263+
{
264+
cli_state_p->error = "Internal error";
265+
break;
266+
}
267+
}
268+
}
269+
270+
if (check_cli_error (cli_state_p))
271+
{
272+
return JERRY_STANDALONE_EXIT_CODE_FAIL;
273+
}
274+
275+
if (number_of_files != 1)
276+
{
277+
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: No input file specified!\n");
278+
return JERRY_STANDALONE_EXIT_CODE_FAIL;
279+
}
280+
281+
jerry_init (flags);
282+
283+
if (!jerry_is_valid_utf8_string (source_p, (jerry_size_t) source_length))
284+
{
285+
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Input must be a valid UTF-8 string.\n");
286+
return JERRY_STANDALONE_EXIT_CODE_FAIL;
287+
}
288+
289+
size_t snapshot_size = jerry_parse_and_save_snapshot ((jerry_char_t *) source_p,
290+
source_length,
291+
is_snapshot_mode_for_global,
292+
false,
293+
output_buffer,
294+
sizeof (output_buffer) / sizeof (uint32_t));
295+
if (snapshot_size == 0)
296+
{
297+
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Generating snapshot failed!\n");
298+
return JERRY_STANDALONE_EXIT_CODE_FAIL;
299+
}
300+
301+
FILE *snapshot_file_p = fopen (output_file_name_p, "w");
302+
if (snapshot_file_p == NULL)
303+
{
304+
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Unable to write snapshot file: '%s'\n", output_file_name_p);
305+
return JERRY_STANDALONE_EXIT_CODE_FAIL;
306+
}
307+
308+
fwrite (output_buffer, sizeof (uint8_t), snapshot_size, snapshot_file_p);
309+
fclose (snapshot_file_p);
310+
311+
printf ("Created snapshot file: '%s' (%lu bytes)\n", output_file_name_p, (unsigned long) snapshot_size);
312+
313+
if (save_literals_file_name_p != NULL)
314+
{
315+
const size_t literal_buffer_size = jerry_parse_and_save_literals ((jerry_char_t *) source_p,
316+
source_length,
317+
false,
318+
output_buffer,
319+
sizeof (output_buffer) / sizeof (uint32_t),
320+
is_save_literals_mode_in_c_format);
321+
if (literal_buffer_size == 0)
322+
{
323+
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Literal saving failed!\n");
324+
return JERRY_STANDALONE_EXIT_CODE_FAIL;
325+
}
326+
327+
FILE *literal_file_p = fopen (save_literals_file_name_p, "w");
328+
329+
if (literal_file_p == NULL)
330+
{
331+
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Unable to write literal file: '%s'\n", save_literals_file_name_p);
332+
return JERRY_STANDALONE_EXIT_CODE_FAIL;
333+
}
334+
335+
fwrite (output_buffer, sizeof (uint8_t), literal_buffer_size, literal_file_p);
336+
fclose (literal_file_p);
337+
338+
printf ("Created literal file: '%s' (%lu bytes)\n", save_literals_file_name_p, (unsigned long) literal_buffer_size);
339+
}
340+
341+
return 0;
342+
} /* process_generate */
343+
76344
/**
77345
* Merge command line option IDs
78346
*/
@@ -90,7 +358,7 @@ static const cli_opt_t merge_opts[] =
90358
CLI_OPT_DEF (.id = OPT_MERGE_HELP, .opt = "h", .longopt = "help",
91359
.help = "print this help and exit"),
92360
CLI_OPT_DEF (.id = OPT_MERGE_OUT, .opt = "o",
93-
.help = "specify output file name (default: merged.snapshot)"),
361+
.help = "specify output file name (default: js.snapshot)"),
94362
CLI_OPT_DEF (.id = CLI_OPT_DEFAULT, .meta = "FILE",
95363
.help = "input snapshot files, minimum two")
96364
};
@@ -111,7 +379,6 @@ process_merge (cli_state_t *cli_state_p, /**< cli state */
111379

112380
cli_change_opts (cli_state_p, merge_opts);
113381

114-
const char *output_file_name_p = "merged.snapshot";
115382
const uint32_t *merge_buffers[argc];
116383
size_t merge_buffer_sizes[argc];
117384
uint32_t number_of_files = 0;
@@ -160,17 +427,8 @@ process_merge (cli_state_t *cli_state_p, /**< cli state */
160427
}
161428
}
162429

163-
if (cli_state_p->error != NULL)
430+
if (check_cli_error (cli_state_p))
164431
{
165-
if (cli_state_p->arg != NULL)
166-
{
167-
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s %s\n", cli_state_p->error, cli_state_p->arg);
168-
}
169-
else
170-
{
171-
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", cli_state_p->error);
172-
}
173-
174432
return JERRY_STANDALONE_EXIT_CODE_FAIL;
175433
}
176434

@@ -238,6 +496,7 @@ print_commands (char *prog_name_p) /**< program name */
238496
cli_help (prog_name_p, NULL, main_opts);
239497

240498
printf ("\nAvailable commands:\n"
499+
" generate\n"
241500
" merge\n"
242501
"\nPassing -h or --help after a command displays its help.\n");
243502
} /* print_commands */
@@ -275,6 +534,10 @@ main (int argc, /**< number of arguments */
275534
{
276535
return process_merge (&cli_state, argc, argv[0]);
277536
}
537+
else if (!strcmp ("generate", command_p))
538+
{
539+
return process_generate (&cli_state, argc, argv[0]);
540+
}
278541

279542
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: unknown command: %s\n\n", command_p);
280543
print_commands (argv[0]);
@@ -289,17 +552,8 @@ main (int argc, /**< number of arguments */
289552
}
290553
}
291554

292-
if (cli_state.error != NULL)
555+
if (check_cli_error (&cli_state))
293556
{
294-
if (cli_state.arg != NULL)
295-
{
296-
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s %s\n", cli_state.error, cli_state.arg);
297-
}
298-
else
299-
{
300-
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", cli_state.error);
301-
}
302-
303557
return JERRY_STANDALONE_EXIT_CODE_FAIL;
304558
}
305559

0 commit comments

Comments
 (0)