aboutsummaryrefslogtreecommitdiff
path: root/jerry-core
diff options
context:
space:
mode:
Diffstat (limited to 'jerry-core')
-rw-r--r--jerry-core/CMakeLists.txt7
-rw-r--r--jerry-core/jcontext/jcontext.h8
-rw-r--r--jerry-core/jerry.c30
-rw-r--r--jerry-core/jerryscript.h19
-rw-r--r--jerry-core/vm/vm.c50
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;
}
}