• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright JS Foundation and other contributors, http://js.foundation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "config.h"
17 #include "jerryscript.h"
18 
19 #include "test-common.h"
20 
21 /**
22  * Maximum size of snapshots buffer
23  */
24 #define SNAPSHOT_BUFFER_SIZE (256)
25 
26 /**
27  * Maximum size of literal buffer
28  */
29 #define LITERAL_BUFFER_SIZE (256)
30 
31 /**
32  * Magic strings
33  */
34 static const jerry_char_t *magic_strings[] =
35 {
36   (const jerry_char_t *) " ",
37   (const jerry_char_t *) "a",
38   (const jerry_char_t *) "b",
39   (const jerry_char_t *) "c",
40   (const jerry_char_t *) "from",
41   (const jerry_char_t *) "func",
42   (const jerry_char_t *) "string",
43   (const jerry_char_t *) "snapshot"
44 };
45 
46 /**
47  * Magic string lengths
48  */
49 static const jerry_length_t magic_string_lengths[] =
50 {
51   1, 1, 1, 1, 4, 4, 6, 8
52 };
53 
test_function_snapshot(void)54 static void test_function_snapshot (void)
55 {
56   /* function to snapshot */
57   if (!jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_SAVE)
58       || !jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_EXEC))
59   {
60     return;
61   }
62 
63   const jerry_init_flag_t flags = JERRY_INIT_EMPTY;
64   static uint32_t function_snapshot_buffer[SNAPSHOT_BUFFER_SIZE];
65 
66   const jerry_char_t func_args[] = "a, b";
67   const jerry_char_t code_to_snapshot[] = "return a + b";
68 
69   jerry_init (flags);
70   jerry_value_t generate_result;
71   generate_result = jerry_generate_function_snapshot (NULL,
72                                                       0,
73                                                       code_to_snapshot,
74                                                       sizeof (code_to_snapshot) - 1,
75                                                       func_args,
76                                                       sizeof (func_args) - 1,
77                                                       0,
78                                                       function_snapshot_buffer,
79                                                       SNAPSHOT_BUFFER_SIZE);
80   TEST_ASSERT (!jerry_value_is_error (generate_result)
81                && jerry_value_is_number (generate_result));
82 
83   size_t function_snapshot_size = (size_t) jerry_get_number_value (generate_result);
84   jerry_release_value (generate_result);
85 
86   jerry_cleanup ();
87 
88   jerry_init (flags);
89 
90   jerry_value_t function_obj = jerry_load_function_snapshot (function_snapshot_buffer,
91                                                              function_snapshot_size,
92                                                              0,
93                                                              0);
94 
95   TEST_ASSERT (!jerry_value_is_error (function_obj));
96   TEST_ASSERT (jerry_value_is_function (function_obj));
97 
98   jerry_value_t this_val = jerry_create_undefined ();
99   jerry_value_t args[2];
100   args[0] = jerry_create_number (1.0);
101   args[1] = jerry_create_number (2.0);
102 
103   jerry_value_t res = jerry_call_function (function_obj, this_val, args, 2);
104 
105   TEST_ASSERT (!jerry_value_is_error (res));
106   TEST_ASSERT (jerry_value_is_number (res));
107   double num = jerry_get_number_value (res);
108   TEST_ASSERT (num == 3);
109 
110   jerry_release_value (args[0]);
111   jerry_release_value (args[1]);
112   jerry_release_value (res);
113   jerry_release_value (function_obj);
114 
115   jerry_cleanup ();
116 } /* test_function_snapshot */
117 
arguments_test_exec_snapshot(uint32_t * snapshot_p,size_t snapshot_size,uint32_t exec_snapshot_flags)118 static void arguments_test_exec_snapshot (uint32_t *snapshot_p, size_t snapshot_size, uint32_t exec_snapshot_flags)
119 {
120   jerry_init (JERRY_INIT_EMPTY);
121   jerry_value_t res = jerry_exec_snapshot (snapshot_p, snapshot_size, 0, exec_snapshot_flags);
122   TEST_ASSERT (!jerry_value_is_error (res));
123   TEST_ASSERT (jerry_value_is_number (res));
124   double raw_value = jerry_get_number_value (res);
125   TEST_ASSERT (raw_value == 15);
126   jerry_release_value (res);
127 
128   jerry_cleanup ();
129 } /* arguments_test_exec_snapshot */
130 
test_function_arguments_snapshot(void)131 static void test_function_arguments_snapshot (void)
132 {
133   if (jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_SAVE)
134       && jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_EXEC))
135   {
136     static uint32_t arguments_snapshot_buffer[SNAPSHOT_BUFFER_SIZE];
137 
138     const jerry_char_t code_to_snapshot[] = TEST_STRING_LITERAL (
139       "function f(a,b,c) {"
140       "  arguments[0]++;"
141       "  arguments[1]++;"
142       "  arguments[2]++;"
143       "  return a + b + c;"
144       "}"
145       "f(3,4,5);"
146     );
147     jerry_init (JERRY_INIT_EMPTY);
148 
149     jerry_value_t generate_result;
150     generate_result = jerry_generate_snapshot (NULL,
151                                                0,
152                                                code_to_snapshot,
153                                                sizeof (code_to_snapshot) - 1,
154                                                0,
155                                                arguments_snapshot_buffer,
156                                                SNAPSHOT_BUFFER_SIZE);
157 
158     TEST_ASSERT (!jerry_value_is_error (generate_result)
159                  && jerry_value_is_number (generate_result));
160 
161     size_t snapshot_size = (size_t) jerry_get_number_value (generate_result);
162     jerry_release_value (generate_result);
163 
164     jerry_cleanup ();
165 
166     arguments_test_exec_snapshot (arguments_snapshot_buffer, snapshot_size, 0);
167     arguments_test_exec_snapshot (arguments_snapshot_buffer, snapshot_size, JERRY_SNAPSHOT_EXEC_COPY_DATA);
168   }
169 } /* test_function_arguments_snapshot */
170 
test_exec_snapshot(uint32_t * snapshot_p,size_t snapshot_size,uint32_t exec_snapshot_flags)171 static void test_exec_snapshot (uint32_t *snapshot_p, size_t snapshot_size, uint32_t exec_snapshot_flags)
172 {
173   char string_data[32];
174 
175   jerry_init (JERRY_INIT_EMPTY);
176 
177   jerry_register_magic_strings (magic_strings,
178                                 sizeof (magic_string_lengths) / sizeof (jerry_length_t),
179                                 magic_string_lengths);
180 
181   jerry_value_t res = jerry_exec_snapshot (snapshot_p, snapshot_size, 0, exec_snapshot_flags);
182 
183   TEST_ASSERT (!jerry_value_is_error (res));
184   TEST_ASSERT (jerry_value_is_string (res));
185   jerry_size_t sz = jerry_get_string_size (res);
186   TEST_ASSERT (sz == 20);
187   sz = jerry_string_to_char_buffer (res, (jerry_char_t *) string_data, sz);
188   TEST_ASSERT (sz == 20);
189   jerry_release_value (res);
190   TEST_ASSERT (!strncmp (string_data, "string from snapshot", (size_t) sz));
191 
192   jerry_cleanup ();
193 } /* test_exec_snapshot */
194 
195 int
main(void)196 main (void)
197 {
198   static uint32_t snapshot_buffer[SNAPSHOT_BUFFER_SIZE];
199 
200   TEST_INIT ();
201 
202   /* Dump / execute snapshot */
203   if (jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_SAVE)
204       && jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_EXEC))
205   {
206     const jerry_char_t code_to_snapshot[] = "(function () { return 'string from snapshot'; }) ();";
207 
208     jerry_init (JERRY_INIT_EMPTY);
209     jerry_value_t generate_result;
210     generate_result = jerry_generate_snapshot (NULL,
211                                                0,
212                                                code_to_snapshot,
213                                                sizeof (code_to_snapshot) - 1,
214                                                0,
215                                                snapshot_buffer,
216                                                SNAPSHOT_BUFFER_SIZE);
217     TEST_ASSERT (!jerry_value_is_error (generate_result)
218                  && jerry_value_is_number (generate_result));
219 
220     size_t snapshot_size = (size_t) jerry_get_number_value (generate_result);
221     jerry_release_value (generate_result);
222 
223     /* Check the snapshot data. Unused bytes should be filled with zeroes */
224     const uint8_t expected_data[] =
225     {
226       0x4A, 0x52, 0x52, 0x59, 0x2C, 0x00, 0x00, 0x00,
227       0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
228       0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
229       0x03, 0x00, 0x01, 0x00, 0x41, 0x00, 0x01, 0x00,
230       0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00,
231       0x2C, 0x00, 0xC9, 0x53, 0x00, 0x00, 0x00, 0x00,
232       0x03, 0x00, 0x01, 0x00, 0x41, 0x00, 0x00, 0x00,
233       0x00, 0x00, 0x01, 0x01, 0x07, 0x00, 0x00, 0x00,
234       0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235       0x14, 0x00, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
236       0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x73, 0x6E,
237       0x61, 0x70, 0x73, 0x68, 0x6F, 0x74,
238     };
239 
240     if (sizeof (expected_data) != snapshot_size || memcmp (expected_data, snapshot_buffer, sizeof (expected_data)))
241     {
242       printf ("Snapshot data has been changed, please update tests/unit-core/test-snapshot.c.\n");
243       printf ("-------------------------------------------------------------------------------\n");
244       printf ("    const uint8_t expected_data[] =\n");
245       printf ("    {");
246       for (unsigned int i = 0; i < snapshot_size; i++)
247       {
248         if ((i % 8) == 0)
249         {
250           printf ("\n     ");
251         }
252         printf (" 0x%02X,", ((uint8_t *) snapshot_buffer)[i]);
253       }
254       printf ("\n    };\n");
255       printf ("-------------------------------------------------------------------------------\n");
256     }
257 
258     TEST_ASSERT (sizeof (expected_data) == snapshot_size);
259     TEST_ASSERT (0 == memcmp (expected_data, snapshot_buffer, sizeof (expected_data)));
260 
261     jerry_cleanup ();
262 
263     test_exec_snapshot (snapshot_buffer, snapshot_size, 0);
264     test_exec_snapshot (snapshot_buffer, snapshot_size, JERRY_SNAPSHOT_EXEC_COPY_DATA);
265   }
266 
267   /* Static snapshot */
268   if (jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_SAVE)
269       && jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_EXEC))
270   {
271     const jerry_char_t code_to_snapshot[] = TEST_STRING_LITERAL (
272       "function func(a, b, c) {"
273       "  c = 'snapshot';"
274       "  return arguments[0] + ' ' + b + ' ' + arguments[2];"
275       "};"
276       "func('string', 'from');"
277     );
278 
279     jerry_init (JERRY_INIT_EMPTY);
280     jerry_register_magic_strings (magic_strings,
281                                   sizeof (magic_string_lengths) / sizeof (jerry_length_t),
282                                   magic_string_lengths);
283 
284     jerry_value_t generate_result;
285     generate_result = jerry_generate_snapshot (NULL,
286                                                0,
287                                                code_to_snapshot,
288                                                sizeof (code_to_snapshot) - 1,
289                                                JERRY_SNAPSHOT_SAVE_STATIC,
290                                                snapshot_buffer,
291                                                SNAPSHOT_BUFFER_SIZE);
292     TEST_ASSERT (!jerry_value_is_error (generate_result)
293                  && jerry_value_is_number (generate_result));
294 
295     size_t snapshot_size = (size_t) jerry_get_number_value (generate_result);
296     jerry_release_value (generate_result);
297 
298     /* Static snapshots are not supported by default. */
299     jerry_value_t exec_result = jerry_exec_snapshot (snapshot_buffer, snapshot_size, 0, 0);
300     TEST_ASSERT (jerry_value_is_error (exec_result));
301     jerry_release_value (exec_result);
302 
303     jerry_cleanup ();
304 
305     test_exec_snapshot (snapshot_buffer, snapshot_size, JERRY_SNAPSHOT_EXEC_ALLOW_STATIC);
306   }
307 
308   /* Merge snapshot */
309   if (jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_SAVE)
310       && jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_EXEC))
311   {
312     static uint32_t snapshot_buffer_0[SNAPSHOT_BUFFER_SIZE];
313     static uint32_t snapshot_buffer_1[SNAPSHOT_BUFFER_SIZE];
314     size_t snapshot_sizes[2];
315     static uint32_t merged_snapshot_buffer[SNAPSHOT_BUFFER_SIZE];
316 
317     const jerry_char_t code_to_snapshot1[] = "var a = 'hello'; 123";
318 
319     jerry_init (JERRY_INIT_EMPTY);
320     jerry_value_t generate_result;
321     generate_result = jerry_generate_snapshot (NULL,
322                                                0,
323                                                code_to_snapshot1,
324                                                sizeof (code_to_snapshot1) - 1,
325                                                0,
326                                                snapshot_buffer_0,
327                                                SNAPSHOT_BUFFER_SIZE);
328     TEST_ASSERT (!jerry_value_is_error (generate_result)
329                  && jerry_value_is_number (generate_result));
330 
331     snapshot_sizes[0] = (size_t) jerry_get_number_value (generate_result);
332     jerry_release_value (generate_result);
333 
334     jerry_cleanup ();
335 
336     const jerry_char_t code_to_snapshot2[] = "var b = 'hello'; 456";
337 
338     jerry_init (JERRY_INIT_EMPTY);
339     generate_result = jerry_generate_snapshot (NULL,
340                                                0,
341                                                code_to_snapshot2,
342                                                sizeof (code_to_snapshot2) - 1,
343                                                0,
344                                                snapshot_buffer_1,
345                                                SNAPSHOT_BUFFER_SIZE);
346     TEST_ASSERT (!jerry_value_is_error (generate_result)
347                  && jerry_value_is_number (generate_result));
348 
349     snapshot_sizes[1] = (size_t) jerry_get_number_value (generate_result);
350     jerry_release_value (generate_result);
351 
352     jerry_cleanup ();
353 
354     jerry_init (JERRY_INIT_EMPTY);
355 
356     const char *error_p;
357     const uint32_t *snapshot_buffers[2];
358 
359     snapshot_buffers[0] = snapshot_buffer_0;
360     snapshot_buffers[1] = snapshot_buffer_1;
361 
362     static uint32_t snapshot_buffer_0_bck[SNAPSHOT_BUFFER_SIZE];
363     static uint32_t snapshot_buffer_1_bck[SNAPSHOT_BUFFER_SIZE];
364 
365     memcpy (snapshot_buffer_0_bck, snapshot_buffer_0, SNAPSHOT_BUFFER_SIZE);
366     memcpy (snapshot_buffer_1_bck, snapshot_buffer_1, SNAPSHOT_BUFFER_SIZE);
367 
368     size_t merged_size = jerry_merge_snapshots (snapshot_buffers,
369                                                 snapshot_sizes,
370                                                 2,
371                                                 merged_snapshot_buffer,
372                                                 SNAPSHOT_BUFFER_SIZE,
373                                                 &error_p);
374 
375     jerry_cleanup ();
376 
377     TEST_ASSERT (0 == memcmp (snapshot_buffer_0_bck, snapshot_buffer_0, SNAPSHOT_BUFFER_SIZE));
378     TEST_ASSERT (0 == memcmp (snapshot_buffer_1_bck, snapshot_buffer_1, SNAPSHOT_BUFFER_SIZE));
379 
380     jerry_init (JERRY_INIT_EMPTY);
381 
382     jerry_value_t res = jerry_exec_snapshot (merged_snapshot_buffer, merged_size, 0, 0);
383     TEST_ASSERT (!jerry_value_is_error (res));
384     TEST_ASSERT (jerry_get_number_value (res) == 123);
385     jerry_release_value (res);
386 
387     res = jerry_exec_snapshot (merged_snapshot_buffer, merged_size, 1, 0);
388     TEST_ASSERT (!jerry_value_is_error (res));
389     TEST_ASSERT (jerry_get_number_value (res) == 456);
390     jerry_release_value (res);
391 
392     jerry_cleanup ();
393   }
394 
395   /* Save literals */
396   if (jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_SAVE))
397   {
398     /* C format generation */
399     jerry_init (JERRY_INIT_EMPTY);
400 
401     static jerry_char_t literal_buffer_c[LITERAL_BUFFER_SIZE];
402     static uint32_t literal_snapshot_buffer[SNAPSHOT_BUFFER_SIZE];
403     static const jerry_char_t code_for_c_format[] = "var object = { aa:'fo\" o\\n \\\\', Bb:'max', aaa:'xzy0' };";
404 
405     jerry_value_t generate_result;
406     generate_result = jerry_generate_snapshot (NULL,
407                                                0,
408                                                code_for_c_format,
409                                                sizeof (code_for_c_format) - 1,
410                                                0,
411                                                literal_snapshot_buffer,
412                                                SNAPSHOT_BUFFER_SIZE);
413 
414     TEST_ASSERT (!jerry_value_is_error (generate_result));
415     TEST_ASSERT (jerry_value_is_number (generate_result));
416 
417     size_t snapshot_size = (size_t) jerry_get_number_value (generate_result);
418     jerry_release_value (generate_result);
419 
420     /* In ES2015 we emit extra bytecode instructions to check global variable redeclaration. */
421     const size_t expected_size = (jerry_is_feature_enabled (JERRY_FEATURE_SYMBOL)) ? 132 : 124;
422     TEST_ASSERT (snapshot_size == expected_size);
423 
424     const size_t lit_c_buf_sz = jerry_get_literals_from_snapshot (literal_snapshot_buffer,
425                                                                   snapshot_size,
426                                                                   literal_buffer_c,
427                                                                   LITERAL_BUFFER_SIZE,
428                                                                   true);
429     TEST_ASSERT (lit_c_buf_sz == 239);
430 
431     static const char *expected_c_format = (
432                                             "jerry_length_t literal_count = 5;\n\n"
433                                             "jerry_char_t *literals[5] =\n"
434                                             "{\n"
435                                             "  \"Bb\",\n"
436                                             "  \"aa\",\n"
437                                             "  \"aaa\",\n"
438                                             "  \"xzy0\",\n"
439                                             "  \"fo\\\" o\\x0A \\\\\"\n"
440                                             "};\n\n"
441                                             "jerry_length_t literal_sizes[5] =\n"
442                                             "{\n"
443                                             "  2 /* Bb */,\n"
444                                             "  2 /* aa */,\n"
445                                             "  3 /* aaa */,\n"
446                                             "  4 /* xzy0 */,\n"
447                                             "  8 /* fo\" o\n \\ */\n"
448                                             "};\n"
449                                             );
450 
451     TEST_ASSERT (!strncmp ((char *) literal_buffer_c, expected_c_format, lit_c_buf_sz));
452 
453     /* List format generation */
454     static jerry_char_t literal_buffer_list[LITERAL_BUFFER_SIZE];
455     const size_t lit_list_buf_sz = jerry_get_literals_from_snapshot (literal_snapshot_buffer,
456                                                                      snapshot_size,
457                                                                      literal_buffer_list,
458                                                                      LITERAL_BUFFER_SIZE,
459                                                                      false);
460     TEST_ASSERT (lit_list_buf_sz == 34);
461     TEST_ASSERT (!strncmp ((char *) literal_buffer_list,
462                            "2 Bb\n2 aa\n3 aaa\n4 xzy0\n8 fo\" o\n \\\n",
463                            lit_list_buf_sz));
464 
465     jerry_cleanup ();
466   }
467 
468   test_function_snapshot ();
469 
470   test_function_arguments_snapshot ();
471 
472   return 0;
473 } /* main */
474