aboutsummaryrefslogtreecommitdiff
path: root/jerry-main/main-jerry-test.c
diff options
context:
space:
mode:
authorYonggang Luo <luoyonggang@gmail.com>2021-02-04 20:13:57 +0800
committerGitHub <noreply@github.com>2021-02-04 13:13:57 +0100
commit982cd080832e2b2ca965ea96867d98fd7c4ff3a0 (patch)
treec1713707b6d1c86008dcf512518825f708295f62 /jerry-main/main-jerry-test.c
parente7d11eaf9efccb941a4d6ee7daf1e9a938dbbb09 (diff)
Rename unix to jerry for entrance files. (#4536)
JerryScript-DCO-1.0-Signed-off-by: Yonggang Luo luoyonggang@gmail.com
Diffstat (limited to 'jerry-main/main-jerry-test.c')
-rw-r--r--jerry-main/main-jerry-test.c244
1 files changed, 244 insertions, 0 deletions
diff --git a/jerry-main/main-jerry-test.c b/jerry-main/main-jerry-test.c
new file mode 100644
index 00000000..aea640c8
--- /dev/null
+++ b/jerry-main/main-jerry-test.c
@@ -0,0 +1,244 @@
+/* Copyright JS Foundation and other contributors, http://js.foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "jerryscript.h"
+#include "jerryscript-port.h"
+
+/**
+ * Maximum size of source code / snapshots buffer
+ */
+#define JERRY_BUFFER_SIZE (1048576)
+
+/**
+ * Standalone Jerry exit codes
+ */
+#define JERRY_STANDALONE_EXIT_CODE_OK (0)
+#define JERRY_STANDALONE_EXIT_CODE_FAIL (1)
+
+static uint8_t buffer[ JERRY_BUFFER_SIZE ];
+
+static const uint8_t *
+read_file (const char *file_name,
+ size_t *out_size_p)
+{
+ FILE *file = fopen (file_name, "rb");
+ if (file == NULL)
+ {
+ jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to open file: %s\n", file_name);
+ return NULL;
+ }
+
+ size_t bytes_read = fread (buffer, 1u, sizeof (buffer), file);
+ if (!bytes_read)
+ {
+ jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to read file: %s\n", file_name);
+ fclose (file);
+ return NULL;
+ }
+
+ fclose (file);
+
+ *out_size_p = bytes_read;
+ return (const uint8_t *) buffer;
+} /* read_file */
+
+static void
+print_help (char *name)
+{
+ printf ("Usage: %s [OPTION]... [FILE]...\n"
+ "\n"
+ "Options:\n"
+ " -h, --help\n"
+ "\n",
+ name);
+} /* print_help */
+
+/* Global "argc" and "argv" used to avoid argument passing via stack. */
+static int argc;
+static char **argv;
+
+static JERRY_ATTR_NOINLINE int
+run (void)
+{
+ jerry_init (JERRY_INIT_EMPTY);
+ jerry_value_t ret_value = jerry_create_undefined ();
+
+ for (int i = 1; i < argc; i++)
+ {
+ const char *file_name = argv[i];
+ size_t source_size;
+
+ const jerry_char_t *source_p = read_file (file_name, &source_size);
+
+ if (source_p == NULL)
+ {
+ ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) "");
+ break;
+ }
+ else
+ {
+ ret_value = jerry_parse (NULL, 0, source_p, source_size, JERRY_PARSE_NO_OPTS);
+
+ if (!jerry_value_is_error (ret_value))
+ {
+ jerry_value_t func_val = ret_value;
+ ret_value = jerry_run (func_val);
+ jerry_release_value (func_val);
+ }
+ }
+
+ if (jerry_value_is_error (ret_value))
+ {
+ break;
+ }
+
+ jerry_release_value (ret_value);
+ ret_value = jerry_create_undefined ();
+ }
+
+ int ret_code = !jerry_value_is_error (ret_value) ? JERRY_STANDALONE_EXIT_CODE_OK : JERRY_STANDALONE_EXIT_CODE_FAIL;
+
+ jerry_release_value (ret_value);
+ jerry_cleanup ();
+
+ return ret_code;
+} /* run */
+
+#if defined (JERRY_TEST_STACK_MEASURE) && (JERRY_TEST_STACK_MEASURE)
+
+/**
+ * How this stack measuring works:
+ *
+ * 1) Get the current stack pointer before doing the test execution.
+ * This will be the "Stack bottom".
+ * 2) Fill the stack towards lower addresses with a placeholder 32 bit value.
+ * A "STACK_MEASURE_RANGE" big area will be filled with the value starting
+ * from "Stack bottom".
+ * The "Stack bottom" + "STACK_MEASURE_RANGE" will be the "Stack top".
+ * 3) Run the tests.
+ * 4) Check the stack backwards from "Stack top" to see where the 32 bit placeholder
+ * value is not present. The point where the 32 bit value is not found is
+ * considered to be the "Stack max". The "Stack bottom" - "Stack max" substraction
+ * will give the stack usage in bytes.
+ *
+ *
+ * Based on this the expected stack layout is:
+ * The stack is expected to "grow" towards lower address.
+ *
+ * |-------|
+ * | | <- low address - "Stack top"
+ * |-------|
+ * | |
+ * |-------|
+ * ....
+ * |-------|
+ * | | <- "Stack max"
+ * |-------|
+ * ....
+ * |-------|
+ * | | <- high address - "Stack bottom"
+ * |-------|
+ *
+ */
+
+#if !(defined (__linux__) && __linux__)
+#error "Unsupported stack measurement platform!"
+#endif /* !(defined ( __linux__) && __linux__) */
+
+#if defined (__x86_64__)
+#define STACK_SAVE(TARGET) { __asm volatile ("mov %%rsp, %0" : "=m" (TARGET)); }
+#elif defined (__i386__)
+#define STACK_SAVE(TARGET) { __asm volatile ("mov %%esp, %0" : "=m" (TARGET)); }
+#elif defined (__arm__)
+#define STACK_SAVE(TARGET) { __asm volatile ("mov %0, sp" : "=r" (TARGET)); }
+#else /* !defined (__x86_64__) && !defined (__i386__) && !defined (__arm__) */
+#error "Unsupported stack measurement target!"
+#endif /* !defined (__x86_64__) && !defined (__i386__) && !defined (__arm__) */
+
+static void *g_stack_bottom = 0x0;
+
+#define STACK_MEASURE_RANGE ((2 * 1024 * 1024))
+#define STACK_PATTERN (0xDEADBEEF)
+#define STACK_INIT(TARGET, SIZE) do \
+ { \
+ for (size_t idx = 0; idx < (SIZE / sizeof (uint32_t)); idx++) \
+ { \
+ ((uint32_t*)(TARGET))[idx] = STACK_PATTERN; \
+ } \
+ } while (0)
+
+#define STACK_USAGE(TARGET, SIZE) stack_usage (TARGET, SIZE)
+#define STACK_TOP_PTR(TARGET, SIZE) (uint32_t *) (((uint8_t *) TARGET) - SIZE)
+
+static void
+stack_usage (uint32_t *stack_top_p, size_t length_in_bytes)
+{
+ uint32_t *stack_bottom_p = stack_top_p + (length_in_bytes / sizeof (uint32_t));
+ uint32_t *stack_p = stack_top_p;
+
+ while (stack_p < stack_bottom_p)
+ {
+ if (*stack_p != STACK_PATTERN)
+ {
+ break;
+ }
+ stack_p++;
+ }
+
+ jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Used stack: %d\n", (int) ((uint8_t *) stack_bottom_p - (uint8_t *) stack_p));
+} /* stack_usage */
+
+#else /* (JERRY_TEST_STACK_MEASURE) && (JERRY_TEST_STACK_MEASURE) */
+#define STACK_SAVE(TARGET)
+#define STACK_INIT(TARGET, SIZE)
+#define STACK_USAGE(TARGET, SIZE)
+#endif /* #if defined (JERRY_TEST_STACK_MEASURE) && (JERRY_TEST_STACK_MEASURE) */
+
+int main (int main_argc,
+ char **main_argv)
+{
+ union
+ {
+ double d;
+ unsigned u;
+ } now = { .d = jerry_port_get_current_time () };
+ srand (now.u);
+
+ argc = main_argc;
+ argv = main_argv;
+
+ if (argc <= 1 || (argc == 2 && (!strcmp ("-h", argv[1]) || !strcmp ("--help", argv[1]))))
+ {
+ print_help (argv[0]);
+ return JERRY_STANDALONE_EXIT_CODE_OK;
+ }
+
+ STACK_SAVE (g_stack_bottom);
+ STACK_INIT (STACK_TOP_PTR (g_stack_bottom, STACK_MEASURE_RANGE), STACK_MEASURE_RANGE);
+
+ int result = run ();
+
+ STACK_USAGE (STACK_TOP_PTR (g_stack_bottom, STACK_MEASURE_RANGE), STACK_MEASURE_RANGE);
+
+ if (result == JERRY_STANDALONE_EXIT_CODE_FAIL)
+ {
+ jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Unhandled exception: Script Error!\n");
+ }
+
+ return result;
+} /* main */