Rework error to use a global slot to store the error value.

This change frees up the error bit in ecma_value_t, which allows
to define 4 more value types (e.g. symbols). To keep API
compatibility we introduce a box for values with error flag.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2017-10-18 03:44:48 -07:00
committed by yichoi
parent 742654a3f1
commit 53cd324179
19 changed files with 582 additions and 288 deletions
+19 -13
View File
@@ -69,11 +69,12 @@ typedef enum
*/
typedef enum
{
ECMA_TYPE_DIRECT, /**< directly encoded value, a 28 bit signed integer or a simple value */
ECMA_TYPE_FLOAT, /**< pointer to a 64 or 32 bit floating point number */
ECMA_TYPE_STRING, /**< pointer to description of a string */
ECMA_TYPE_OBJECT, /**< pointer to description of an object */
ECMA_TYPE___MAX = ECMA_TYPE_OBJECT /** highest value for ecma types */
ECMA_TYPE_DIRECT = 0, /**< directly encoded value, a 28 bit signed integer or a simple value */
ECMA_TYPE_FLOAT = 1, /**< pointer to a 64 or 32 bit floating point number */
ECMA_TYPE_STRING = 2, /**< pointer to description of a string */
ECMA_TYPE_OBJECT = 3, /**< pointer to description of an object */
ECMA_TYPE_ERROR = 7, /**< pointer to description of an error reference */
ECMA_TYPE___MAX = ECMA_TYPE_ERROR /** highest value for ecma types */
} ecma_type_t;
/**
@@ -88,11 +89,12 @@ typedef enum
* - special register or stack values for vm
*/
ECMA_SIMPLE_VALUE_EMPTY, /**< uninitialized value */
ECMA_SIMPLE_VALUE_ARRAY_HOLE, /**< array hole, used for initialization of an array literal */
ECMA_SIMPLE_VALUE_ERROR, /**< an error is currently thrown */
ECMA_SIMPLE_VALUE_FALSE, /**< boolean false */
ECMA_SIMPLE_VALUE_TRUE, /**< boolean true */
ECMA_SIMPLE_VALUE_UNDEFINED, /**< undefined value */
ECMA_SIMPLE_VALUE_NULL, /**< null value */
ECMA_SIMPLE_VALUE_ARRAY_HOLE, /**< array hole, used for initialization of an array literal */
ECMA_SIMPLE_VALUE_NOT_FOUND, /**< a special value returned by ecma_op_object_find */
ECMA_SIMPLE_VALUE_REGISTER_REF, /**< register reference, a special "base" value for vm */
ECMA_SIMPLE_VALUE__COUNT /** count of simple ecma values */
@@ -122,12 +124,7 @@ typedef int32_t ecma_integer_value_t;
/**
* Mask for ecma types in ecma_type_t
*/
#define ECMA_VALUE_TYPE_MASK 0x3u
/**
* Error flag in ecma_type_t
*/
#define ECMA_VALUE_ERROR_FLAG 0x4u
#define ECMA_VALUE_TYPE_MASK 0x7u
/**
* Shift for value part in ecma_type_t
@@ -199,7 +196,7 @@ typedef int32_t ecma_integer_value_t;
* Checks whether the error flag is set.
*/
#define ECMA_IS_VALUE_ERROR(value) \
(unlikely ((value & ECMA_VALUE_ERROR_FLAG) != 0))
(unlikely ((value) == ecma_make_simple_value (ECMA_SIMPLE_VALUE_ERROR)))
/**
* Representation for native external pointer
@@ -1139,6 +1136,15 @@ typedef struct
lit_utf8_size_t long_utf8_string_length; /**< length of this long utf-8 string in bytes */
} ecma_long_string_t;
/**
* Representation of a thrown value on API level.
*/
typedef struct
{
uint32_t refs; /**< reference counter */
ecma_value_t value; /**< referenced value */
} ecma_error_reference_t;
/**
* Compiled byte code data.
*/
+48 -46
View File
@@ -28,15 +28,10 @@
* @{
*/
/**
* Masking the type and flags
*/
#define ECMA_VALUE_FULL_MASK (ECMA_VALUE_TYPE_MASK | ECMA_VALUE_ERROR_FLAG)
JERRY_STATIC_ASSERT (ECMA_TYPE___MAX <= ECMA_VALUE_TYPE_MASK,
ecma_types_must_be_less_than_mask);
JERRY_STATIC_ASSERT ((ECMA_VALUE_FULL_MASK + 1) == (1 << ECMA_VALUE_SHIFT),
JERRY_STATIC_ASSERT ((ECMA_VALUE_TYPE_MASK + 1) == (1 << ECMA_VALUE_SHIFT),
ecma_value_part_must_start_after_flags);
JERRY_STATIC_ASSERT (ECMA_VALUE_SHIFT <= JMEM_ALIGNMENT_LOG,
@@ -83,7 +78,7 @@ ecma_pointer_to_ecma_value (const void *ptr) /**< pointer */
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
uintptr_t uint_ptr = (uintptr_t) ptr;
JERRY_ASSERT ((uint_ptr & ECMA_VALUE_FULL_MASK) == 0);
JERRY_ASSERT ((uint_ptr & ECMA_VALUE_TYPE_MASK) == 0);
return (ecma_value_t) uint_ptr;
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
@@ -104,7 +99,7 @@ static inline void * __attr_pure___ __attr_always_inline___
ecma_get_pointer_from_ecma_value (ecma_value_t value) /**< value */
{
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
return (void *) (uintptr_t) ((value) & ~ECMA_VALUE_FULL_MASK);
return (void *) (uintptr_t) ((value) & ~ECMA_VALUE_TYPE_MASK);
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
return ECMA_GET_NON_NULL_POINTER (ecma_number_t,
value >> ECMA_VALUE_SHIFT);
@@ -145,7 +140,7 @@ static inline bool __attr_const___ __attr_always_inline___
ecma_is_value_equal_to_simple_value (ecma_value_t value, /**< ecma value */
ecma_simple_value_t simple_value) /**< simple value */
{
return (value | ECMA_VALUE_ERROR_FLAG) == (ecma_make_simple_value (simple_value) | ECMA_VALUE_ERROR_FLAG);
return value == ecma_make_simple_value (simple_value);
} /* ecma_is_value_equal_to_simple_value */
/**
@@ -321,6 +316,18 @@ ecma_is_value_object (ecma_value_t value) /**< ecma value */
return (ecma_get_value_type_field (value) == ECMA_TYPE_OBJECT);
} /* ecma_is_value_object */
/**
* Check if the value is error reference.
*
* @return true - if the value contains object value,
* false - otherwise
*/
inline bool __attr_const___ __attr_always_inline___
ecma_is_value_error_reference (ecma_value_t value) /**< ecma value */
{
return (ecma_get_value_type_field (value) == ECMA_TYPE_ERROR);
} /* ecma_is_value_error_reference */
/**
* Debug assertion that specified value's type is one of ECMA-defined
* script-visible types, i.e.: undefined, null, boolean, number, string, object.
@@ -485,7 +492,7 @@ ecma_make_uint32_value (uint32_t uint32_number) /**< uint32 number to be encoded
/**
* String value constructor
*/
ecma_value_t __attr_pure___
inline ecma_value_t __attr_pure___ __attr_always_inline___
ecma_make_string_value (const ecma_string_t *ecma_string_p) /**< string to reference in value */
{
JERRY_ASSERT (ecma_string_p != NULL);
@@ -496,7 +503,7 @@ ecma_make_string_value (const ecma_string_t *ecma_string_p) /**< string to refer
/**
* Object value constructor
*/
ecma_value_t __attr_pure___
inline ecma_value_t __attr_pure___ __attr_always_inline___
ecma_make_object_value (const ecma_object_t *object_p) /**< object to reference in value */
{
JERRY_ASSERT (object_p != NULL);
@@ -505,25 +512,15 @@ ecma_make_object_value (const ecma_object_t *object_p) /**< object to reference
} /* ecma_make_object_value */
/**
* Error value constructor
* Error reference constructor
*/
ecma_value_t __attr_const___
ecma_make_error_value (ecma_value_t value) /**< original ecma value */
inline ecma_value_t __attr_pure___ __attr_always_inline___
ecma_make_error_reference_value (const ecma_error_reference_t *error_ref_p) /**< error reference */
{
/* Error values cannot be converted. */
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (value));
JERRY_ASSERT (error_ref_p != NULL);
return value | ECMA_VALUE_ERROR_FLAG;
} /* ecma_make_error_value */
/**
* Error value constructor
*/
ecma_value_t __attr_pure___
ecma_make_error_obj_value (const ecma_object_t *object_p) /**< object to reference in value */
{
return ecma_make_error_value (ecma_make_object_value (object_p));
} /* ecma_make_error_obj_value */
return ecma_pointer_to_ecma_value (error_ref_p) | ECMA_TYPE_ERROR;
} /* ecma_make_error_reference_value */
/**
* Get integer value from an integer ecma value
@@ -588,6 +585,19 @@ ecma_get_object_from_value (ecma_value_t value) /**< ecma value */
return (ecma_object_t *) ecma_get_pointer_from_ecma_value (value);
} /* ecma_get_object_from_value */
/**
* Get pointer to error reference from ecma value
*
* @return the pointer
*/
inline ecma_error_reference_t *__attr_pure___ __attr_always_inline___
ecma_get_error_reference_from_value (ecma_value_t value) /**< ecma value */
{
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_ERROR);
return (ecma_error_reference_t *) ecma_get_pointer_from_ecma_value (value);
} /* ecma_get_error_reference_from_value */
/**
* Invert a boolean value
*
@@ -601,23 +611,6 @@ ecma_invert_boolean_value (ecma_value_t value) /**< ecma value */
return (value ^ (1 << ECMA_DIRECT_SHIFT));
} /* ecma_invert_boolean_value */
/**
* Get the value from an error ecma value
*
* @return ecma value
*/
ecma_value_t __attr_const___
ecma_get_value_from_error_value (ecma_value_t value) /**< ecma value */
{
JERRY_ASSERT (ECMA_IS_VALUE_ERROR (value));
value = (ecma_value_t) (value & ~ECMA_VALUE_ERROR_FLAG);
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (value));
return value;
} /* ecma_get_value_from_error_value */
/**
* Copy ecma value.
*
@@ -648,9 +641,12 @@ ecma_copy_value (ecma_value_t value) /**< value description */
ecma_ref_object (ecma_get_object_from_value (value));
return value;
}
default:
{
JERRY_UNREACHABLE ();
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
}
}
JERRY_UNREACHABLE ();
} /* ecma_copy_value */
/**
@@ -840,6 +836,12 @@ ecma_free_value (ecma_value_t value) /**< value description */
ecma_deref_object (ecma_get_object_from_value (value));
break;
}
default:
{
JERRY_UNREACHABLE ();
break;
}
}
} /* ecma_free_value */
+97
View File
@@ -1320,6 +1320,103 @@ ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p) /**< pro
*prop_desc_p = ecma_make_empty_property_descriptor ();
} /* ecma_free_property_descriptor */
/**
* The size of error reference must be 8 bytes to use jmem_pools_alloc().
*/
JERRY_STATIC_ASSERT (sizeof (ecma_error_reference_t) == 8,
ecma_error_reference_size_must_be_8_bytes);
/**
* Create an error reference from a given value.
*
* Note:
* Reference of the value is taken.
*
* @return error reference value
*/
ecma_value_t
ecma_create_error_reference (ecma_value_t value) /**< referenced value */
{
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->value = value;
return ecma_make_error_reference_value (error_ref_p);
} /* ecma_create_error_reference */
/**
* Create an error reference from a given object.
*
* Note:
* Reference of the value is taken.
*
* @return error reference 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));
} /* ecma_create_error_object_reference */
/**
* Increase ref count of an error reference.
*/
void
ecma_ref_error_reference (ecma_error_reference_t *error_ref_p) /**< error reference */
{
if (likely (error_ref_p->refs < UINT32_MAX))
{
error_ref_p->refs++;
}
else
{
jerry_fatal (ERR_REF_COUNT_LIMIT);
}
} /* ecma_ref_error_reference */
/**
* Decrease ref count of an error reference.
*/
void
ecma_deref_error_reference (ecma_error_reference_t *error_ref_p) /**< error reference */
{
JERRY_ASSERT (error_ref_p->refs > 0);
error_ref_p->refs--;
if (error_ref_p->refs == 0)
{
ecma_free_value (error_ref_p->value);
jmem_pools_free (error_ref_p, sizeof (ecma_error_reference_t));
}
} /* ecma_deref_error_reference */
/**
* Clears error reference, and returns with the value.
*
* @return value referenced by the error
*/
ecma_value_t
ecma_clear_error_reference (ecma_value_t value)
{
ecma_error_reference_t *error_ref_p = ecma_get_error_reference_from_value (value);
JERRY_ASSERT (error_ref_p->refs > 0);
ecma_value_t referenced_value = error_ref_p->value;
if (error_ref_p->refs > 1)
{
error_ref_p->refs--;
}
else
{
jmem_pools_free (error_ref_p, sizeof (ecma_error_reference_t));
}
return referenced_value;
} /* ecma_clear_error_reference */
/**
* Increase reference counter of Compact
* Byte Code or regexp byte code.
+8 -4
View File
@@ -128,6 +128,7 @@ bool ecma_is_value_float_number (ecma_value_t value) __attr_const___;
bool ecma_is_value_number (ecma_value_t value) __attr_const___;
bool ecma_is_value_string (ecma_value_t value) __attr_const___;
bool ecma_is_value_object (ecma_value_t value) __attr_const___;
bool ecma_is_value_error_reference (ecma_value_t value) __attr_const___;
void ecma_check_value_type_is_spec_defined (ecma_value_t value);
@@ -140,14 +141,13 @@ ecma_value_t ecma_make_int32_value (int32_t int32_number);
ecma_value_t ecma_make_uint32_value (uint32_t uint32_number);
ecma_value_t ecma_make_string_value (const ecma_string_t *ecma_string_p) __attr_pure___;
ecma_value_t ecma_make_object_value (const ecma_object_t *object_p) __attr_pure___;
ecma_value_t ecma_make_error_value (ecma_value_t value) __attr_const___;
ecma_value_t ecma_make_error_obj_value (const ecma_object_t *object_p) __attr_pure___;
ecma_value_t ecma_make_error_reference_value (const ecma_error_reference_t *error_ref_p) __attr_pure___;
ecma_integer_value_t ecma_get_integer_from_value (ecma_value_t value) __attr_const___;
ecma_number_t ecma_get_float_from_value (ecma_value_t value) __attr_pure___;
ecma_number_t ecma_get_number_from_value (ecma_value_t value) __attr_pure___;
ecma_string_t *ecma_get_string_from_value (ecma_value_t value) __attr_pure___;
ecma_object_t *ecma_get_object_from_value (ecma_value_t value) __attr_pure___;
ecma_value_t ecma_get_value_from_error_value (ecma_value_t value) __attr_const___;
ecma_error_reference_t *ecma_get_error_reference_from_value (ecma_value_t value) __attr_pure___;
ecma_value_t ecma_invert_boolean_value (ecma_value_t value) __attr_const___;
ecma_value_t ecma_copy_value (ecma_value_t value);
ecma_value_t ecma_fast_copy_value (ecma_value_t value);
@@ -339,7 +339,11 @@ 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_property_t *ecma_get_next_property_pair (ecma_property_pair_t *);
ecma_value_t ecma_create_error_reference (ecma_value_t value);
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);
void ecma_bytecode_ref (ecma_compiled_code_t *bytecode_p);
void ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p);