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:
Zoltan Herczeg
2018-01-30 01:13:44 +01:00
committed by yichoi
parent b548eae4ad
commit 918eb22a01
17 changed files with 477 additions and 144 deletions
+3 -3
View File
@@ -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 */
+29 -1
View File
@@ -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;
+40 -14
View File
@@ -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);
}
+3 -2
View File
@@ -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);
+1 -1
View File
@@ -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;