Add support for aborts. (#2176)
Aborts are similar to exceptions except they are not caught by catch and finally blocks. Callbacks should honor aborts as well and return them without processing them. Aborts are never thrown by JavaScript code. In the future certain events such as out-of-memory condition may also throw aborts. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
@@ -902,7 +902,7 @@ ecma_free_unused_memory (jmem_free_unused_memory_severity_t severity) /**< sever
|
||||
{
|
||||
--JERRY_CONTEXT (ecma_prop_hashmap_alloc_state);
|
||||
}
|
||||
JERRY_CONTEXT (ecma_prop_hashmap_alloc_last_is_hs_gc) = false;
|
||||
JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_HIGH_SEV_GC;
|
||||
#endif /* !CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */
|
||||
|
||||
/*
|
||||
@@ -921,14 +921,14 @@ ecma_free_unused_memory (jmem_free_unused_memory_severity_t severity) /**< sever
|
||||
JERRY_ASSERT (severity == JMEM_FREE_UNUSED_MEMORY_SEVERITY_HIGH);
|
||||
|
||||
#ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE
|
||||
if (JERRY_CONTEXT (ecma_prop_hashmap_alloc_last_is_hs_gc))
|
||||
if (JERRY_CONTEXT (status_flags) & ECMA_STATUS_HIGH_SEV_GC)
|
||||
{
|
||||
JERRY_CONTEXT (ecma_prop_hashmap_alloc_state) = ECMA_PROP_HASHMAP_ALLOC_MAX;
|
||||
}
|
||||
else if (JERRY_CONTEXT (ecma_prop_hashmap_alloc_state) < ECMA_PROP_HASHMAP_ALLOC_MAX)
|
||||
{
|
||||
++JERRY_CONTEXT (ecma_prop_hashmap_alloc_state);
|
||||
JERRY_CONTEXT (ecma_prop_hashmap_alloc_last_is_hs_gc) = true;
|
||||
JERRY_CONTEXT (status_flags) |= ECMA_STATUS_HIGH_SEV_GC;
|
||||
}
|
||||
#endif /* !CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */
|
||||
|
||||
|
||||
@@ -64,6 +64,19 @@ typedef enum
|
||||
ECMA_INIT_MEM_STATS = (1u << 2), /**< dump memory statistics */
|
||||
} ecma_init_flag_t;
|
||||
|
||||
/**
|
||||
* JerryScript status flags.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_STATUS_API_AVAILABLE = (1u << 0), /**< api available */
|
||||
ECMA_STATUS_DIRECT_EVAL = (1u << 1), /**< eval is called directly */
|
||||
#ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE
|
||||
ECMA_STATUS_HIGH_SEV_GC = (1u << 2), /**< last gc run was a high severity run */
|
||||
#endif /* !CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */
|
||||
ECMA_STATUS_EXCEPTION = (1u << 3), /**< last exception is a normal exception */
|
||||
} ecma_status_flag_t;
|
||||
|
||||
/**
|
||||
* Type of ecma value
|
||||
*/
|
||||
@@ -1161,12 +1174,27 @@ typedef struct
|
||||
lit_utf8_size_t long_utf8_string_length; /**< length of this long utf-8 string in bytes */
|
||||
} ecma_long_string_t;
|
||||
|
||||
/**
|
||||
* Abort flag for error reference.
|
||||
*/
|
||||
#define ECMA_ERROR_REF_ABORT 0x1
|
||||
|
||||
/**
|
||||
* Value for increasing or decreasing the reference counter.
|
||||
*/
|
||||
#define ECMA_ERROR_REF_ONE (1u << 1)
|
||||
|
||||
/**
|
||||
* Maximum value of the reference counter.
|
||||
*/
|
||||
#define ECMA_ERROR_MAX_REF (UINT32_MAX - 1u)
|
||||
|
||||
/**
|
||||
* Representation of a thrown value on API level.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t refs; /**< reference counter */
|
||||
uint32_t refs_and_flags; /**< reference counter */
|
||||
ecma_value_t value; /**< referenced value */
|
||||
} ecma_error_reference_t;
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-lcache.h"
|
||||
#include "ecma-property-hashmap.h"
|
||||
#include "jcontext.h"
|
||||
#include "jrt-bit-fields.h"
|
||||
#include "byte-code.h"
|
||||
#include "re-compiler.h"
|
||||
@@ -26,7 +27,6 @@
|
||||
|
||||
#ifdef JERRY_DEBUGGER
|
||||
#include "debugger.h"
|
||||
#include "jcontext.h"
|
||||
#endif /* JERRY_DEBUGGER */
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
@@ -1335,15 +1335,28 @@ JERRY_STATIC_ASSERT (sizeof (ecma_error_reference_t) == 8,
|
||||
* @return error reference value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_create_error_reference (ecma_value_t value) /**< referenced value */
|
||||
ecma_create_error_reference (ecma_value_t value, /**< referenced value */
|
||||
bool is_exception) /**< error reference is an exception */
|
||||
{
|
||||
ecma_error_reference_t *error_ref_p = (ecma_error_reference_t *) jmem_pools_alloc (sizeof (ecma_error_reference_t));
|
||||
|
||||
error_ref_p->refs = 1;
|
||||
error_ref_p->refs_and_flags = ECMA_ERROR_REF_ONE | (is_exception ? 0 : ECMA_ERROR_REF_ABORT);
|
||||
error_ref_p->value = value;
|
||||
return ecma_make_error_reference_value (error_ref_p);
|
||||
} /* ecma_create_error_reference */
|
||||
|
||||
/**
|
||||
* Create an error reference from the currently thrown error value.
|
||||
*
|
||||
* @return error reference value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_create_error_reference_from_context (void)
|
||||
{
|
||||
return ecma_create_error_reference (JERRY_CONTEXT (error_value),
|
||||
(JERRY_CONTEXT (status_flags) & ECMA_STATUS_EXCEPTION) != 0);
|
||||
} /* ecma_create_error_reference_from_context */
|
||||
|
||||
/**
|
||||
* Create an error reference from a given object.
|
||||
*
|
||||
@@ -1355,7 +1368,7 @@ ecma_create_error_reference (ecma_value_t value) /**< referenced value */
|
||||
inline ecma_value_t __attr_always_inline___
|
||||
ecma_create_error_object_reference (ecma_object_t *object_p) /**< referenced object */
|
||||
{
|
||||
return ecma_create_error_reference (ecma_make_object_value (object_p));
|
||||
return ecma_create_error_reference (ecma_make_object_value (object_p), true);
|
||||
} /* ecma_create_error_object_reference */
|
||||
|
||||
/**
|
||||
@@ -1364,9 +1377,9 @@ ecma_create_error_object_reference (ecma_object_t *object_p) /**< referenced obj
|
||||
void
|
||||
ecma_ref_error_reference (ecma_error_reference_t *error_ref_p) /**< error reference */
|
||||
{
|
||||
if (likely (error_ref_p->refs < UINT32_MAX))
|
||||
if (likely (error_ref_p->refs_and_flags < ECMA_ERROR_MAX_REF))
|
||||
{
|
||||
error_ref_p->refs++;
|
||||
error_ref_p->refs_and_flags += ECMA_ERROR_REF_ONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1380,11 +1393,11 @@ ecma_ref_error_reference (ecma_error_reference_t *error_ref_p) /**< error refere
|
||||
void
|
||||
ecma_deref_error_reference (ecma_error_reference_t *error_ref_p) /**< error reference */
|
||||
{
|
||||
JERRY_ASSERT (error_ref_p->refs > 0);
|
||||
JERRY_ASSERT (error_ref_p->refs_and_flags >= ECMA_ERROR_REF_ONE);
|
||||
|
||||
error_ref_p->refs--;
|
||||
error_ref_p->refs_and_flags -= ECMA_ERROR_REF_ONE;
|
||||
|
||||
if (error_ref_p->refs == 0)
|
||||
if (error_ref_p->refs_and_flags < ECMA_ERROR_REF_ONE)
|
||||
{
|
||||
ecma_free_value (error_ref_p->value);
|
||||
jmem_pools_free (error_ref_p, sizeof (ecma_error_reference_t));
|
||||
@@ -1397,15 +1410,28 @@ ecma_deref_error_reference (ecma_error_reference_t *error_ref_p) /**< error refe
|
||||
* @return value referenced by the error
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_clear_error_reference (ecma_value_t value)
|
||||
ecma_clear_error_reference (ecma_value_t value, /**< error reference */
|
||||
bool set_abort_flag) /**< set abort flag */
|
||||
{
|
||||
ecma_error_reference_t *error_ref_p = ecma_get_error_reference_from_value (value);
|
||||
|
||||
JERRY_ASSERT (error_ref_p->refs > 0);
|
||||
|
||||
if (error_ref_p->refs > 1)
|
||||
if (set_abort_flag)
|
||||
{
|
||||
error_ref_p->refs--;
|
||||
if (error_ref_p->refs_and_flags & ECMA_ERROR_REF_ABORT)
|
||||
{
|
||||
JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_EXCEPTION;
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_CONTEXT (status_flags) |= ECMA_STATUS_EXCEPTION;
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_ASSERT (error_ref_p->refs_and_flags >= ECMA_ERROR_REF_ONE);
|
||||
|
||||
if (error_ref_p->refs_and_flags >= 2 * ECMA_ERROR_REF_ONE)
|
||||
{
|
||||
error_ref_p->refs_and_flags -= ECMA_ERROR_REF_ONE;
|
||||
return ecma_copy_value (error_ref_p->value);
|
||||
}
|
||||
|
||||
|
||||
@@ -352,11 +352,12 @@ void ecma_set_property_lcached (ecma_property_t *property_p, bool is_lcached);
|
||||
ecma_property_descriptor_t ecma_make_empty_property_descriptor (void);
|
||||
void ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p);
|
||||
|
||||
ecma_value_t ecma_create_error_reference (ecma_value_t value);
|
||||
ecma_value_t ecma_create_error_reference (ecma_value_t value, bool is_exception);
|
||||
ecma_value_t ecma_create_error_reference_from_context (void);
|
||||
ecma_value_t ecma_create_error_object_reference (ecma_object_t *object_p);
|
||||
void ecma_ref_error_reference (ecma_error_reference_t *error_ref_p);
|
||||
void ecma_deref_error_reference (ecma_error_reference_t *error_ref_p);
|
||||
ecma_value_t ecma_clear_error_reference (ecma_value_t value);
|
||||
ecma_value_t ecma_clear_error_reference (ecma_value_t value, bool set_abort_flag);
|
||||
|
||||
void ecma_bytecode_ref (ecma_compiled_code_t *bytecode_p);
|
||||
void ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p);
|
||||
|
||||
@@ -43,7 +43,7 @@ ecma_init (void)
|
||||
|
||||
#ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE
|
||||
JERRY_CONTEXT (ecma_prop_hashmap_alloc_state) = ECMA_PROP_HASHMAP_ALLOC_ON;
|
||||
JERRY_CONTEXT (ecma_prop_hashmap_alloc_last_is_hs_gc) = false;
|
||||
JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_HIGH_SEV_GC;
|
||||
#endif /* !CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
||||
|
||||
@@ -157,6 +157,7 @@ ecma_raise_standard_error (ecma_standard_error_t error_type, /**< error type */
|
||||
}
|
||||
|
||||
JERRY_CONTEXT (error_value) = ecma_make_object_value (error_obj_p);
|
||||
JERRY_CONTEXT (status_flags) |= ECMA_STATUS_EXCEPTION;
|
||||
return ECMA_VALUE_ERROR;
|
||||
} /* ecma_raise_standard_error */
|
||||
|
||||
@@ -243,6 +244,7 @@ ecma_raise_standard_error_with_format (ecma_standard_error_t error_type, /**< er
|
||||
ecma_deref_ecma_string (error_msg_p);
|
||||
|
||||
JERRY_CONTEXT (error_value) = ecma_make_object_value (error_obj_p);
|
||||
JERRY_CONTEXT (status_flags) |= ECMA_STATUS_EXCEPTION;
|
||||
return ECMA_VALUE_ERROR;
|
||||
} /* ecma_raise_standard_error_with_format */
|
||||
|
||||
|
||||
@@ -470,14 +470,14 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
|
||||
|
||||
if (unlikely (ecma_is_value_error_reference (ret_value)))
|
||||
{
|
||||
JERRY_CONTEXT (error_value) = ecma_clear_error_reference (ret_value);
|
||||
JERRY_CONTEXT (error_value) = ecma_clear_error_reference (ret_value, true);
|
||||
ret_value = ECMA_VALUE_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION);
|
||||
JERRY_CONTEXT (is_direct_eval_form_call) = false;
|
||||
JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_DIRECT_EVAL;
|
||||
|
||||
/* 2-3. */
|
||||
ecma_extended_object_t *ext_function_p = (ecma_extended_object_t *) func_obj_p;
|
||||
|
||||
Reference in New Issue
Block a user