diff options
author | Zoltan Herczeg <zherczeg.u-szeged@partner.samsung.com> | 2017-04-28 14:19:23 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-28 14:19:23 +0200 |
commit | 894aa6d036cd29d8fe8b49382372dc7b1fc263a4 (patch) | |
tree | 1c4f67554efbdaae902af580a7a60621f1c82ba5 /jerry-core | |
parent | 0e38356e5bae168759d356ff09eab1625ad87f3a (diff) |
Support ECMAScript stopping in JerryScript. (#1753)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
Diffstat (limited to 'jerry-core')
-rw-r--r-- | jerry-core/CMakeLists.txt | 7 | ||||
-rw-r--r-- | jerry-core/jcontext/jcontext.h | 8 | ||||
-rw-r--r-- | jerry-core/jerry.c | 30 | ||||
-rw-r--r-- | jerry-core/jerryscript.h | 19 | ||||
-rw-r--r-- | jerry-core/vm/vm.c | 50 |
5 files changed, 114 insertions, 0 deletions
diff --git a/jerry-core/CMakeLists.txt b/jerry-core/CMakeLists.txt index f1d5f238..1649a0fd 100644 --- a/jerry-core/CMakeLists.txt +++ b/jerry-core/CMakeLists.txt @@ -32,6 +32,7 @@ set(FEATURE_SNAPSHOT_SAVE OFF CACHE BOOL "Enable saving snapshot files? set(FEATURE_SYSTEM_ALLOCATOR OFF CACHE BOOL "Enable system allocator?") set(FEATURE_VALGRIND OFF CACHE BOOL "Enable Valgrind support?") set(FEATURE_VALGRIND_FREYA OFF CACHE BOOL "Enable Valgrind-Freya support?") +set(FEATURE_VM_EXEC_STOP OFF CACHE BOOL "Enable VM execution stopping?") set(MEM_HEAP_SIZE_KB "512" CACHE STRING "Size of memory heap, in kilobytes") if(FEATURE_SYSTEM_ALLOCATOR) @@ -54,6 +55,7 @@ message(STATUS "FEATURE_SNAPSHOT_SAVE " ${FEATURE_SNAPSHOT_SAVE}) message(STATUS "FEATURE_SYSTEM_ALLOCATOR " ${FEATURE_SYSTEM_ALLOCATOR}) message(STATUS "FEATURE_VALGRIND " ${FEATURE_VALGRIND}) message(STATUS "FEATURE_VALGRIND_FREYA " ${FEATURE_VALGRIND_FREYA}) +message(STATUS "FEATURE_VM_EXEC_STOP " ${FEATURE_VM_EXEC_STOP}) message(STATUS "MEM_HEAP_SIZE_KB " ${MEM_HEAP_SIZE_KB}) # Include directories @@ -238,6 +240,11 @@ if(FEATURE_VALGRIND_FREYA) set(INCLUDE_CORE ${INCLUDE_CORE} ${INCLUDE_THIRD_PARTY_VALGRIND}) endif() +# Enable VM execution stopping +if (FEATURE_VM_EXEC_STOP) + set(DEFINES_JERRY ${DEFINES_JERRY} JERRY_VM_EXEC_STOP) +endif() + # Size of heap math(EXPR MEM_HEAP_AREA_SIZE "${MEM_HEAP_SIZE_KB} * 1024") set(DEFINES_JERRY ${DEFINES_JERRY} CONFIG_MEM_HEAP_AREA_SIZE=${MEM_HEAP_AREA_SIZE}) diff --git a/jerry-core/jcontext/jcontext.h b/jerry-core/jcontext/jcontext.h index 57d32be4..32f49b32 100644 --- a/jerry-core/jcontext/jcontext.h +++ b/jerry-core/jcontext/jcontext.h @@ -84,6 +84,14 @@ typedef struct uint8_t re_cache_idx; /**< evicted item index when regex cache is full (round-robin) */ #endif /* !CONFIG_DISABLE_REGEXP_BUILTIN */ +#ifdef JERRY_VM_EXEC_STOP + uint32_t vm_exec_stop_frequency; /**< reset value for vm_exec_stop_counter */ + uint32_t vm_exec_stop_counter; /**< down counter for reducing the calls of vm_exec_stop_cb */ + void *vm_exec_stop_user_p; /**< user pointer for vm_exec_stop_cb */ + jerry_vm_exec_stop_callback_t vm_exec_stop_cb; /**< user function which returns whether the + * ECMAScript execution should be stopped */ +#endif /* JERRY_VM_EXEC_STOP */ + #ifdef JERRY_DEBUGGER uint8_t debugger_send_buffer[JERRY_DEBUGGER_MAX_BUFFER_SIZE]; /**< buffer for sending messages */ uint8_t debugger_receive_buffer[JERRY_DEBUGGER_MAX_BUFFER_SIZE]; /**< buffer for receiving messages */ diff --git a/jerry-core/jerry.c b/jerry-core/jerry.c index 83b53908..fcca46bf 100644 --- a/jerry-core/jerry.c +++ b/jerry-core/jerry.c @@ -618,6 +618,9 @@ bool jerry_is_feature_enabled (const jerry_feature_t feature) #ifdef JERRY_DEBUGGER || feature == JERRY_FEATURE_DEBUGGER #endif /* JERRY_DEBUGGER */ +#ifdef JERRY_VM_EXEC_STOP + || feature == JERRY_FEATURE_VM_EXEC_STOP +#endif /* JERRY_VM_EXEC_STOP */ ); } /* jerry_is_feature_enabled */ @@ -2146,5 +2149,32 @@ jerry_is_valid_cesu8_string (const jerry_char_t *cesu8_buf_p, /**< CESU-8 string } /* jerry_is_valid_cesu8_string */ /** + * If JERRY_VM_EXEC_STOP is defined the callback passed to this function is + * periodically called with the user_p argument. If frequency is greater + * than 1, the callback is only called at every frequency ticks. + */ +void +jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, /**< periodically called user function */ + void *user_p, /**< pointer passed to the function */ + uint32_t frequency) /**< frequency of the function call */ +{ +#ifdef JERRY_VM_EXEC_STOP + if (frequency == 0) + { + frequency = 1; + } + + JERRY_CONTEXT (vm_exec_stop_frequency) = frequency; + JERRY_CONTEXT (vm_exec_stop_counter) = frequency; + JERRY_CONTEXT (vm_exec_stop_user_p) = user_p; + JERRY_CONTEXT (vm_exec_stop_cb) = stop_cb; +#else /* !JERRY_VM_EXEC_STOP */ + JERRY_UNUSED (stop_cb); + JERRY_UNUSED (user_p); + JERRY_UNUSED (frequency); +#endif /* JERRY_VM_EXEC_STOP */ +} /* jerry_set_vm_exec_stop_callback */ + +/** * @} */ diff --git a/jerry-core/jerryscript.h b/jerry-core/jerryscript.h index 154505d4..be9d4a53 100644 --- a/jerry-core/jerryscript.h +++ b/jerry-core/jerryscript.h @@ -86,6 +86,7 @@ typedef enum JERRY_FEATURE_SNAPSHOT_SAVE, /**< saving snapshot files */ JERRY_FEATURE_SNAPSHOT_EXEC, /**< executing snapshot files */ JERRY_FEATURE_DEBUGGER, /**< debugging */ + JERRY_FEATURE_VM_EXEC_STOP, /**< stopping ECMAScript execution */ JERRY_FEATURE__COUNT /**< number of features. NOTE: must be at the end of the list */ } jerry_feature_t; @@ -175,6 +176,19 @@ typedef void (*jerry_object_free_callback_t) (const uintptr_t native_p); typedef void (*jerry_object_native_free_callback_t) (void *native_p); /** + * Callback which tells whether the ECMAScript execution should be stopped. + * + * As long as the function returns with undefined the execution continues. + * When a non-undefined value is returned the execution stops and the value + * is thrown by the engine (if the error flag is not set for the returned + * value the engine automatically sets it). + * + * Note: if the function returns with a non-undefined value it + * must return with the same value for future calls. + */ +typedef jerry_value_t (*jerry_vm_exec_stop_callback_t) (void *user_p); + +/** * Function type applied for each data property of an object. */ typedef bool (*jerry_object_property_foreach_t) (const jerry_value_t property_name, @@ -389,6 +403,11 @@ size_t jerry_parse_and_save_literals (const jerry_char_t *source_p, size_t sourc uint32_t *buffer_p, size_t buffer_size, bool is_c_format); /** + * Miscellaneous functions. + */ +void jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, void *user_p, uint32_t frequency); + +/** * @} */ diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index fd0d3fa3..6f01ccb7 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -847,6 +847,29 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ if (opcode_data & VM_OC_BACKWARD_BRANCH) { +#ifdef JERRY_VM_EXEC_STOP + if (JERRY_CONTEXT (vm_exec_stop_cb) != NULL + && --JERRY_CONTEXT (vm_exec_stop_counter) == 0) + { + result = JERRY_CONTEXT (vm_exec_stop_cb) (JERRY_CONTEXT (vm_exec_stop_user_p)); + + if (ecma_is_value_undefined (result)) + { + JERRY_CONTEXT (vm_exec_stop_counter) = JERRY_CONTEXT (vm_exec_stop_frequency); + } + else + { + JERRY_CONTEXT (vm_exec_stop_counter) = 1; + + if (!ECMA_IS_VALUE_ERROR (result)) + { + result = ecma_make_error_value (result); + } + goto error; + } + } +#endif /* JERRY_VM_EXEC_STOP */ + branch_offset = -branch_offset; } } @@ -2595,6 +2618,33 @@ error: JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_THROW); stack_top_p[-2] = result; } + +#ifdef JERRY_VM_EXEC_STOP + if (JERRY_CONTEXT (vm_exec_stop_cb) != NULL + && --JERRY_CONTEXT (vm_exec_stop_counter) == 0) + { + result = JERRY_CONTEXT (vm_exec_stop_cb) (JERRY_CONTEXT (vm_exec_stop_user_p)); + + if (ecma_is_value_undefined (result)) + { + JERRY_CONTEXT (vm_exec_stop_counter) = JERRY_CONTEXT (vm_exec_stop_frequency); + } + else + { + JERRY_CONTEXT (vm_exec_stop_counter) = 1; + + left_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); + right_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + result = ecma_make_error_value (result); + } + goto error; + } + } +#endif /* JERRY_VM_EXEC_STOP */ + continue; } } |