Rework array hole calculation for fast access mode arrays (#3248)
This patch gives possibility to Array.prototype builtin routine optimizations. JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
@@ -2055,8 +2055,7 @@ jerry_has_internal_property (const jerry_value_t obj_val, /**< object value */
|
||||
|
||||
ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL);
|
||||
|
||||
if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY
|
||||
&& ((ecma_extended_object_t *) obj_p)->u.array.is_fast_mode)
|
||||
if (ecma_op_object_is_fast_array (obj_p))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -2146,8 +2145,7 @@ jerry_delete_internal_property (const jerry_value_t obj_val, /**< object value *
|
||||
|
||||
ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL);
|
||||
|
||||
if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY
|
||||
&& ((ecma_extended_object_t *) obj_p)->u.array.is_fast_mode)
|
||||
if (ecma_op_object_is_fast_array (obj_p))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -2249,8 +2247,7 @@ jerry_get_internal_property (const jerry_value_t obj_val, /**< object value */
|
||||
|
||||
ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL);
|
||||
|
||||
if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY
|
||||
&& ((ecma_extended_object_t *) obj_p)->u.array.is_fast_mode)
|
||||
if (ecma_op_object_is_fast_array (obj_p))
|
||||
{
|
||||
return jerry_return (ECMA_VALUE_UNDEFINED);
|
||||
}
|
||||
@@ -2360,8 +2357,7 @@ jerry_set_internal_property (const jerry_value_t obj_val, /**< object value */
|
||||
|
||||
ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL);
|
||||
|
||||
if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY
|
||||
&& ((ecma_extended_object_t *) obj_p)->u.array.is_fast_mode)
|
||||
if (ecma_op_object_is_fast_array (obj_p))
|
||||
{
|
||||
ecma_fast_array_convert_to_normal (obj_p);
|
||||
}
|
||||
|
||||
@@ -458,14 +458,9 @@ jerry_debugger_send_scope_variables (const uint8_t *recv_buffer_p) /**< pointer
|
||||
JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
|
||||
ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p);
|
||||
|
||||
if (JERRY_UNLIKELY (ecma_get_object_type (binding_obj_p) == ECMA_OBJECT_TYPE_ARRAY))
|
||||
if (JERRY_UNLIKELY (ecma_op_object_is_fast_array (binding_obj_p)))
|
||||
{
|
||||
ecma_extended_object_t *ext_binding_obj_p = (ecma_extended_object_t *) binding_obj_p;
|
||||
|
||||
if (ext_binding_obj_p->u.array.is_fast_mode)
|
||||
{
|
||||
ecma_fast_array_convert_to_normal (binding_obj_p);
|
||||
}
|
||||
ecma_fast_array_convert_to_normal (binding_obj_p);
|
||||
}
|
||||
|
||||
prop_iter_cp = binding_obj_p->u1.property_list_cp;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "ecma-alloc.h"
|
||||
#include "ecma-array-object.h"
|
||||
#include "ecma-container-object.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-gc.h"
|
||||
@@ -482,7 +483,7 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (ext_object_p->u.array.is_fast_mode)
|
||||
if (ecma_op_array_is_fast_array (ext_object_p))
|
||||
{
|
||||
if (object_p->u1.property_list_cp != JMEM_CP_NULL)
|
||||
{
|
||||
@@ -611,11 +612,9 @@ ecma_gc_free_native_pointer (ecma_property_t *property_p) /**< property */
|
||||
static void
|
||||
ecma_free_fast_access_array (ecma_object_t *object_p) /**< fast access mode array object to free */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY);
|
||||
JERRY_ASSERT (ecma_op_object_is_fast_array (object_p));
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
JERRY_ASSERT (ext_object_p->u.array.is_fast_mode);
|
||||
|
||||
const uint32_t aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (ext_object_p->u.array.length);
|
||||
|
||||
if (object_p->u1.property_list_cp != JMEM_CP_NULL)
|
||||
@@ -651,15 +650,10 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
||||
if (obj_is_not_lex_env
|
||||
|| ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
||||
{
|
||||
if (obj_is_not_lex_env && ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY)
|
||||
if (obj_is_not_lex_env && ecma_op_object_is_fast_array (object_p))
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (ext_object_p->u.array.is_fast_mode)
|
||||
{
|
||||
ecma_free_fast_access_array (object_p);
|
||||
return;
|
||||
}
|
||||
ecma_free_fast_access_array (object_p);
|
||||
return;
|
||||
}
|
||||
|
||||
jmem_cpointer_t prop_iter_cp = object_p->u1.property_list_cp;
|
||||
@@ -1203,8 +1197,7 @@ ecma_free_unused_memory (jmem_pressure_t pressure) /**< current pressure */
|
||||
|| ecma_get_lex_env_type (obj_iter_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
||||
{
|
||||
if (!ecma_is_lexical_environment (obj_iter_p)
|
||||
&& ecma_get_object_type (obj_iter_p) == ECMA_OBJECT_TYPE_ARRAY
|
||||
&& ((ecma_extended_object_t *) obj_iter_p)->u.array.is_fast_mode)
|
||||
&& ecma_op_object_is_fast_array (obj_iter_p))
|
||||
{
|
||||
obj_iter_cp = obj_iter_p->gc_next_cp;
|
||||
continue;
|
||||
|
||||
@@ -837,10 +837,13 @@ typedef struct
|
||||
struct
|
||||
{
|
||||
uint32_t length; /**< length property value */
|
||||
ecma_property_t length_prop; /**< length property */
|
||||
bool is_fast_mode; /**< true - if the array is a fast access mode array
|
||||
* false - otherwise */
|
||||
uint8_t hole_count; /**< Number of array holes in a fast access mode array */
|
||||
union
|
||||
{
|
||||
ecma_property_t length_prop; /**< length property */
|
||||
uint32_t hole_count; /**< number of array holes in a fast access mode array
|
||||
* multiplied ECMA_FAST_ACCESS_HOLE_ONE */
|
||||
} u;
|
||||
|
||||
} array;
|
||||
|
||||
/**
|
||||
@@ -900,7 +903,6 @@ typedef struct
|
||||
#define ECMA_FAST_ARRAY_ALIGN_LENGTH(length) \
|
||||
(uint32_t) ((((length)) + ECMA_FAST_ARRAY_ALIGNMENT - 1) / ECMA_FAST_ARRAY_ALIGNMENT * ECMA_FAST_ARRAY_ALIGNMENT)
|
||||
|
||||
|
||||
/**
|
||||
* Compiled byte code data.
|
||||
*/
|
||||
|
||||
@@ -39,8 +39,7 @@ ecma_create_native_pointer_property (ecma_object_t *obj_p, /**< object to create
|
||||
{
|
||||
ecma_string_t *name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
|
||||
|
||||
if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY
|
||||
&& ((ecma_extended_object_t *) obj_p)->u.array.is_fast_mode)
|
||||
if (ecma_op_object_is_fast_array (obj_p))
|
||||
{
|
||||
ecma_fast_array_convert_to_normal (obj_p);
|
||||
}
|
||||
@@ -115,8 +114,7 @@ ecma_native_pointer_t *
|
||||
ecma_get_native_pointer_value (ecma_object_t *obj_p, /**< object to get property value from */
|
||||
void *info_p) /**< native pointer's type info */
|
||||
{
|
||||
if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY
|
||||
&& ((ecma_extended_object_t *) obj_p)->u.array.is_fast_mode)
|
||||
if (ecma_op_object_is_fast_array (obj_p))
|
||||
{
|
||||
/* Fast access mode array can not have native pointer properties */
|
||||
return NULL;
|
||||
@@ -164,8 +162,7 @@ bool
|
||||
ecma_delete_native_pointer_property (ecma_object_t *obj_p, /**< object to delete property from */
|
||||
void *info_p) /**< native pointer's type info */
|
||||
{
|
||||
if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY
|
||||
&& ((ecma_extended_object_t *) obj_p)->u.array.is_fast_mode)
|
||||
if (ecma_op_object_is_fast_array (obj_p))
|
||||
{
|
||||
/* Fast access mode array can not have native pointer properties */
|
||||
return false;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "ecma-alloc.h"
|
||||
#include "ecma-array-object.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
@@ -473,8 +474,7 @@ ecma_create_named_data_property (ecma_object_t *object_p, /**< object */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL && name_p != NULL);
|
||||
JERRY_ASSERT (ecma_is_lexical_environment (object_p)
|
||||
|| ecma_get_object_type (object_p) != ECMA_OBJECT_TYPE_ARRAY
|
||||
|| !((ecma_extended_object_t *) object_p)->u.array.is_fast_mode);
|
||||
|| !ecma_op_object_is_fast_array (object_p));
|
||||
JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL);
|
||||
JERRY_ASSERT ((prop_attributes & ~ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) == 0);
|
||||
|
||||
@@ -502,8 +502,7 @@ ecma_create_named_accessor_property (ecma_object_t *object_p, /**< object */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL && name_p != NULL);
|
||||
JERRY_ASSERT (ecma_is_lexical_environment (object_p)
|
||||
|| ecma_get_object_type (object_p) != ECMA_OBJECT_TYPE_ARRAY
|
||||
|| !((ecma_extended_object_t *) object_p)->u.array.is_fast_mode);
|
||||
|| !ecma_op_object_is_fast_array (object_p));
|
||||
JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL);
|
||||
JERRY_ASSERT ((prop_attributes & ~ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE) == 0);
|
||||
|
||||
@@ -537,8 +536,7 @@ ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in
|
||||
JERRY_ASSERT (obj_p != NULL);
|
||||
JERRY_ASSERT (name_p != NULL);
|
||||
JERRY_ASSERT (ecma_is_lexical_environment (obj_p)
|
||||
|| ecma_get_object_type (obj_p) != ECMA_OBJECT_TYPE_ARRAY
|
||||
|| !((ecma_extended_object_t *) obj_p)->u.array.is_fast_mode);
|
||||
|| !ecma_op_object_is_fast_array (obj_p));
|
||||
|
||||
ecma_property_t *property_p = NULL;
|
||||
|
||||
@@ -696,8 +694,7 @@ ecma_get_named_data_property (ecma_object_t *obj_p, /**< object to find property
|
||||
JERRY_ASSERT (obj_p != NULL);
|
||||
JERRY_ASSERT (name_p != NULL);
|
||||
JERRY_ASSERT (ecma_is_lexical_environment (obj_p)
|
||||
|| ecma_get_object_type (obj_p) != ECMA_OBJECT_TYPE_ARRAY
|
||||
|| !((ecma_extended_object_t *) obj_p)->u.array.is_fast_mode);
|
||||
|| !ecma_op_object_is_fast_array (obj_p));
|
||||
|
||||
ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p);
|
||||
|
||||
|
||||
@@ -35,6 +35,10 @@
|
||||
void
|
||||
ecma_init (void)
|
||||
{
|
||||
#if (JERRY_GC_MARK_LIMIT != 0)
|
||||
JERRY_CONTEXT (ecma_gc_mark_recursion_limit) = JERRY_GC_MARK_LIMIT;
|
||||
#endif /* (JERRY_GC_MARK_LIMIT != 0) */
|
||||
|
||||
ecma_init_global_lex_env ();
|
||||
|
||||
#if ENABLED (JERRY_PROPRETY_HASHMAP)
|
||||
@@ -47,10 +51,6 @@ ecma_init (void)
|
||||
JERRY_CONTEXT (stack_base) = (uintptr_t)&sp;
|
||||
#endif /* (JERRY_STACK_LIMIT != 0) */
|
||||
|
||||
#if (JERRY_GC_MARK_LIMIT != 0)
|
||||
JERRY_CONTEXT (ecma_gc_mark_recursion_limit) = JERRY_GC_MARK_LIMIT;
|
||||
#endif /* (JERRY_GC_MARK_LIMIT != 0) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_PROMISE)
|
||||
ecma_job_queue_init ();
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
|
||||
|
||||
@@ -425,8 +425,7 @@ ecma_builtin_array_prototype_object_pop (ecma_object_t *obj_p, /**< array object
|
||||
return get_value;
|
||||
}
|
||||
|
||||
if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY
|
||||
&& ((ecma_extended_object_t *) obj_p)->u.array.is_fast_mode)
|
||||
if (ecma_op_object_is_fast_array (obj_p))
|
||||
{
|
||||
if (!ecma_get_object_extensible (obj_p))
|
||||
{
|
||||
@@ -478,8 +477,7 @@ ecma_builtin_array_prototype_object_push (const ecma_value_t *argument_list_p, /
|
||||
{
|
||||
ecma_number_t n = (ecma_number_t) length;
|
||||
|
||||
if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY
|
||||
&& ((ecma_extended_object_t *) obj_p)->u.array.is_fast_mode)
|
||||
if (ecma_op_object_is_fast_array (obj_p))
|
||||
{
|
||||
if (!ecma_get_object_extensible (obj_p))
|
||||
{
|
||||
@@ -497,6 +495,7 @@ ecma_builtin_array_prototype_object_push (const ecma_value_t *argument_list_p, /
|
||||
}
|
||||
|
||||
uint32_t new_length = length + arguments_number;
|
||||
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
|
||||
ecma_value_t *buffer_p = ecma_fast_array_extend (obj_p, new_length) + length;
|
||||
|
||||
for (uint32_t index = 0; index < arguments_number; index++)
|
||||
@@ -504,6 +503,8 @@ ecma_builtin_array_prototype_object_push (const ecma_value_t *argument_list_p, /
|
||||
buffer_p[index] = ecma_copy_value_if_not_object (argument_list_p[index]);
|
||||
}
|
||||
|
||||
ext_obj_p->u.array.u.hole_count -= ECMA_FAST_ARRAY_HOLE_ONE * arguments_number;
|
||||
|
||||
return ecma_make_uint32_value (new_length);
|
||||
}
|
||||
|
||||
|
||||
@@ -293,7 +293,7 @@ ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /**< object */
|
||||
return new_array;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (((ecma_extended_object_t *) new_array_p)->u.array.is_fast_mode);
|
||||
JERRY_ASSERT (ecma_op_object_is_fast_array (new_array_p));
|
||||
|
||||
ecma_value_t *buffer_p = props_p->buffer_p;
|
||||
ecma_value_t *values_p = ecma_fast_array_extend (new_array_p, props_p->item_count);
|
||||
|
||||
@@ -1460,8 +1460,7 @@ ecma_builtin_string_prototype_object_split (ecma_value_t this_to_string_val, /**
|
||||
|
||||
if (separator_is_regexp)
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_type (match_obj_p) != ECMA_OBJECT_TYPE_ARRAY
|
||||
|| !((ecma_extended_object_t *) match_obj_p)->u.array.is_fast_mode);
|
||||
JERRY_ASSERT (!ecma_op_object_is_fast_array (match_obj_p));
|
||||
|
||||
ecma_property_value_t *index_prop_value_p = ecma_get_named_data_property (match_obj_p, magic_index_str_p);
|
||||
ecma_number_t index_num = ecma_get_number_from_value (index_prop_value_p->value);
|
||||
|
||||
@@ -431,9 +431,7 @@ ecma_instantiate_builtin (ecma_builtin_id_t obj_builtin_id) /**< built-in id */
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
|
||||
|
||||
ext_object_p->u.array.length = 0;
|
||||
ext_object_p->u.array.length_prop = ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_TYPE_VIRTUAL;
|
||||
ext_object_p->u.array.is_fast_mode = false;
|
||||
ext_object_p->u.array.hole_count = 0;
|
||||
ext_object_p->u.array.u.length_prop = ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_TYPE_VIRTUAL;
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_ARRAY) */
|
||||
|
||||
@@ -34,6 +34,32 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if ENABLED (JERRY_CPOINTER_32_BIT)
|
||||
/**
|
||||
* Maximum length of the array length to allocate fast mode access for it
|
||||
* e.g. new Array(5000) is constructed as fast mode access array,
|
||||
* but new Array(50000000) is consturcted as normal property list based array
|
||||
*/
|
||||
#define ECMA_FAST_ARRAY_MAX_INITIAL_LENGTH (1 << 17)
|
||||
#else /* ENABLED (JERRY_CPOINTER_32_BIT) */
|
||||
/**
|
||||
* Maximum length of the array length to allocate fast mode access for it
|
||||
* e.g. new Array(5000) is constructed as fast mode access array,
|
||||
* but new Array(50000000) is consturcted as normal property list based array
|
||||
*/
|
||||
#define ECMA_FAST_ARRAY_MAX_INITIAL_LENGTH (1 << 13)
|
||||
#endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
|
||||
|
||||
/**
|
||||
* Property name type flag for array indices.
|
||||
*/
|
||||
#define ECMA_FAST_ARRAY_UINT32_DIRECT_STRING_PROP_TYPE 0x80
|
||||
|
||||
/**
|
||||
* Property attribute for the array 'length' virtual property to indicate fast access mode array
|
||||
*/
|
||||
#define ECMA_FAST_ARRAY_FLAG (ECMA_DIRECT_STRING_MAGIC << ECMA_PROPERTY_NAME_TYPE_SHIFT)
|
||||
|
||||
/**
|
||||
* Allocate a new array object with the given length
|
||||
*
|
||||
@@ -60,13 +86,38 @@ ecma_op_new_array_object (ecma_length_t length) /**< length of the new array */
|
||||
|
||||
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
|
||||
ext_obj_p->u.array.length = length;
|
||||
ext_obj_p->u.array.length_prop = ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_TYPE_VIRTUAL;
|
||||
ext_obj_p->u.array.is_fast_mode = false;
|
||||
ext_obj_p->u.array.hole_count = 0;
|
||||
ext_obj_p->u.array.u.length_prop = ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_TYPE_VIRTUAL;
|
||||
|
||||
return object_p;
|
||||
} /* ecma_op_new_array_object */
|
||||
|
||||
/**
|
||||
* Check whether the given object is fast-access mode array
|
||||
*
|
||||
* @return true - if the object is fast-access mode array
|
||||
* false, otherwise
|
||||
*/
|
||||
inline bool JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_op_object_is_fast_array (ecma_object_t *object_p) /**< ecma-object */
|
||||
{
|
||||
return (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY &&
|
||||
ecma_op_array_is_fast_array ((ecma_extended_object_t *) object_p));
|
||||
} /* ecma_op_object_is_fast_array */
|
||||
|
||||
/**
|
||||
* Check whether the given array object is fast-access mode array
|
||||
*
|
||||
* @return true - if the array object is fast-access mode array
|
||||
* false, otherwise
|
||||
*/
|
||||
inline bool JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_op_array_is_fast_array (ecma_extended_object_t *array_p) /**< ecma-array-object */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_type ((ecma_object_t *) array_p) == ECMA_OBJECT_TYPE_ARRAY);
|
||||
|
||||
return array_p->u.array.u.length_prop & ECMA_FAST_ARRAY_FLAG;
|
||||
} /* ecma_op_array_is_fast_array */
|
||||
|
||||
/**
|
||||
* Allocate a new fast access mode array object with the given length
|
||||
*
|
||||
@@ -90,9 +141,10 @@ ecma_op_new_fast_array_object (ecma_length_t length) /**< length of the new fast
|
||||
}
|
||||
|
||||
ecma_object_t *object_p = ecma_op_new_array_object (length);
|
||||
|
||||
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
|
||||
ext_obj_p->u.array.is_fast_mode = true;
|
||||
|
||||
ext_obj_p->u.array.u.length_prop = (uint8_t) (ext_obj_p->u.array.u.length_prop | ECMA_FAST_ARRAY_FLAG);
|
||||
ext_obj_p->u.array.u.hole_count += length * ECMA_FAST_ARRAY_HOLE_ONE;
|
||||
|
||||
JERRY_ASSERT (object_p->u1.property_list_cp == JMEM_CP_NULL);
|
||||
|
||||
@@ -105,26 +157,19 @@ ecma_op_new_fast_array_object (ecma_length_t length) /**< length of the new fast
|
||||
return object_p;
|
||||
} /* ecma_op_new_fast_array_object */
|
||||
|
||||
/**
|
||||
* Property name type flag for array indices.
|
||||
*/
|
||||
#define ECMA_FAST_ARRAY_UINT32_DIRECT_STRING_PROP_TYPE 0x80
|
||||
|
||||
/**
|
||||
* Converts a fast access mode array back to a normal property list based array
|
||||
*/
|
||||
void
|
||||
ecma_fast_array_convert_to_normal (ecma_object_t *object_p) /**< fast access mode array object */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY);
|
||||
JERRY_ASSERT (ecma_op_object_is_fast_array (object_p));
|
||||
|
||||
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
JERRY_ASSERT (ext_obj_p->u.array.is_fast_mode);
|
||||
|
||||
if (object_p->u1.property_list_cp == JMEM_CP_NULL)
|
||||
{
|
||||
ext_obj_p->u.array.is_fast_mode = false;
|
||||
ext_obj_p->u.array.u.length_prop = (uint8_t) (ext_obj_p->u.array.u.length_prop & ~ECMA_FAST_ARRAY_FLAG);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -132,15 +177,6 @@ ecma_fast_array_convert_to_normal (ecma_object_t *object_p) /**< fast access mod
|
||||
const uint32_t aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (length);
|
||||
ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp);
|
||||
|
||||
/* Check whether the buffer contains only array holes */
|
||||
if (JERRY_UNLIKELY (ext_obj_p->u.array.length == ext_obj_p->u.array.hole_count))
|
||||
{
|
||||
ext_obj_p->u.array.is_fast_mode = false;
|
||||
jmem_heap_free_block (values_p, aligned_length * sizeof (ecma_value_t));
|
||||
object_p->u1.property_list_cp = JMEM_CP_NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
ecma_ref_object (object_p);
|
||||
|
||||
ecma_property_pair_t *property_pair_p = NULL;
|
||||
@@ -179,29 +215,13 @@ ecma_fast_array_convert_to_normal (ecma_object_t *object_p) /**< fast access mod
|
||||
prop_index = !prop_index;
|
||||
}
|
||||
|
||||
ext_obj_p->u.array.is_fast_mode = false;
|
||||
ext_obj_p->u.array.u.length_prop = (uint8_t) (ext_obj_p->u.array.u.length_prop & ~ECMA_FAST_ARRAY_FLAG);
|
||||
jmem_heap_free_block (values_p, aligned_length * sizeof (ecma_value_t));
|
||||
ECMA_SET_POINTER (object_p->u1.property_list_cp, property_pair_p);
|
||||
|
||||
ecma_deref_object (object_p);
|
||||
} /* ecma_fast_array_convert_to_normal */
|
||||
|
||||
#if ENABLED (JERRY_SYSTEM_ALLOCATOR)
|
||||
/**
|
||||
* Maximum length of the array length to allocate fast mode access for it
|
||||
* e.g. new Array(5000) is constructed as fast mode access array,
|
||||
* but new Array(50000000) is consturcted as normal property list based array
|
||||
*/
|
||||
#define ECMA_FAST_ARRAY_MAX_INITIAL_LENGTH (1 << 17)
|
||||
#else
|
||||
/**
|
||||
* Maximum length of the array length to allocate fast mode access for it
|
||||
* e.g. new Array(5000) is constructed as fast mode access array,
|
||||
* but new Array(50000000) is consturcted as normal property list based array
|
||||
*/
|
||||
#define ECMA_FAST_ARRAY_MAX_INITIAL_LENGTH (1 << 13)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* [[Put]] operation for a fast access mode array
|
||||
*
|
||||
@@ -215,13 +235,13 @@ ecma_fast_array_set_property (ecma_object_t *object_p, /**< fast access mode arr
|
||||
uint32_t index, /**< property name index */
|
||||
ecma_value_t value) /**< value to be set */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY);
|
||||
JERRY_ASSERT (ecma_op_object_is_fast_array (object_p));
|
||||
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
|
||||
JERRY_ASSERT (ext_obj_p->u.array.is_fast_mode);
|
||||
uint32_t old_length = ext_obj_p->u.array.length;
|
||||
|
||||
ecma_value_t *values_p;
|
||||
|
||||
if (JERRY_LIKELY (index < ext_obj_p->u.array.length))
|
||||
if (JERRY_LIKELY (index < old_length))
|
||||
{
|
||||
JERRY_ASSERT (object_p->u1.property_list_cp != JMEM_CP_NULL);
|
||||
|
||||
@@ -229,7 +249,7 @@ ecma_fast_array_set_property (ecma_object_t *object_p, /**< fast access mode arr
|
||||
|
||||
if (ecma_is_value_array_hole (values_p[index]))
|
||||
{
|
||||
ext_obj_p->u.array.hole_count = (uint8_t) JERRY_MAX (ext_obj_p->u.array.hole_count - 1, 0);
|
||||
ext_obj_p->u.array.u.hole_count -= ECMA_FAST_ARRAY_HOLE_ONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -241,10 +261,21 @@ ecma_fast_array_set_property (ecma_object_t *object_p, /**< fast access mode arr
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t new_holes = index - ext_obj_p->u.array.length;
|
||||
uint32_t old_length = ext_obj_p->u.array.length;
|
||||
uint32_t old_holes = ext_obj_p->u.array.u.hole_count;
|
||||
uint32_t new_holes = index - old_length;
|
||||
|
||||
if (JERRY_UNLIKELY (new_holes > ECMA_FAST_ARRAY_MAX_NEW_HOLES_COUNT
|
||||
|| ((old_holes >> ECMA_FAST_ARRAY_HOLE_SHIFT) + new_holes) > ECMA_FAST_ARRAY_MAX_HOLE_COUNT))
|
||||
{
|
||||
ecma_fast_array_convert_to_normal (object_p);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t new_length = index + 1;
|
||||
|
||||
JERRY_ASSERT (new_length < UINT32_MAX);
|
||||
|
||||
const uint32_t aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (old_length);
|
||||
|
||||
if (JERRY_LIKELY (index < aligned_length))
|
||||
@@ -252,24 +283,15 @@ ecma_fast_array_set_property (ecma_object_t *object_p, /**< fast access mode arr
|
||||
JERRY_ASSERT (object_p->u1.property_list_cp != JMEM_CP_NULL);
|
||||
|
||||
values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp);
|
||||
/* This area is filled with ECMA_VALUE_ARRAY_HOLE, but not counted in u.array.u.hole_count */
|
||||
JERRY_ASSERT (ecma_is_value_array_hole (values_p[index]));
|
||||
ext_obj_p->u.array.u.hole_count += new_holes * ECMA_FAST_ARRAY_HOLE_ONE;
|
||||
ext_obj_p->u.array.length = new_length;
|
||||
ext_obj_p->u.array.hole_count = (uint8_t) JERRY_MIN (ext_obj_p->u.array.hole_count + new_holes,
|
||||
ECMA_FAST_ARRAY_MAX_HOLE_COUNT);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (ext_obj_p->u.array.hole_count <= ECMA_FAST_ARRAY_MAX_HOLE_COUNT);
|
||||
|
||||
if (new_holes > (uint32_t) (ECMA_FAST_ARRAY_MAX_HOLE_COUNT - ext_obj_p->u.array.hole_count))
|
||||
{
|
||||
ecma_fast_array_convert_to_normal (object_p);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
values_p = ecma_fast_array_extend (object_p, new_length);
|
||||
ext_obj_p->u.array.hole_count = (uint8_t) (ext_obj_p->u.array.hole_count + new_holes);
|
||||
ext_obj_p->u.array.u.hole_count -= ECMA_FAST_ARRAY_HOLE_ONE;
|
||||
}
|
||||
|
||||
values_p[index] = ecma_copy_value_if_not_object (value);
|
||||
@@ -287,11 +309,10 @@ ecma_value_t *
|
||||
ecma_fast_array_extend (ecma_object_t *object_p, /**< fast access mode array object */
|
||||
uint32_t new_length) /**< new length of the fast access mode array */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY);
|
||||
JERRY_ASSERT (ecma_op_object_is_fast_array (object_p));
|
||||
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
|
||||
uint32_t old_length = ext_obj_p->u.array.length;
|
||||
|
||||
JERRY_ASSERT (ext_obj_p->u.array.is_fast_mode);
|
||||
JERRY_ASSERT (old_length < new_length);
|
||||
|
||||
ecma_ref_object (object_p);
|
||||
@@ -317,6 +338,7 @@ ecma_fast_array_extend (ecma_object_t *object_p, /**< fast access mode array obj
|
||||
new_values_p[i] = ECMA_VALUE_ARRAY_HOLE;
|
||||
}
|
||||
|
||||
ext_obj_p->u.array.u.hole_count += (new_length - old_length) * ECMA_FAST_ARRAY_HOLE_ONE;
|
||||
ext_obj_p->u.array.length = new_length;
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER (object_p->u1.property_list_cp, new_values_p);
|
||||
@@ -338,7 +360,7 @@ ecma_array_object_delete_property (ecma_object_t *object_p, /**< object */
|
||||
JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY);
|
||||
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (!ext_obj_p->u.array.is_fast_mode)
|
||||
if (!ecma_op_object_is_fast_array (object_p))
|
||||
{
|
||||
ecma_delete_property (object_p, prop_value_p);
|
||||
return;
|
||||
@@ -360,22 +382,8 @@ ecma_array_object_delete_property (ecma_object_t *object_p, /**< object */
|
||||
|
||||
ecma_free_value_if_not_object (values_p[index]);
|
||||
|
||||
if (JERRY_UNLIKELY (ext_obj_p->u.array.length == 1))
|
||||
{
|
||||
const uint32_t old_length_aligned = ECMA_FAST_ARRAY_ALIGN_LENGTH (ext_obj_p->u.array.length);
|
||||
jmem_heap_free_block (values_p, old_length_aligned * sizeof (ecma_value_t));
|
||||
ext_obj_p->u.array.hole_count = 0;
|
||||
ext_obj_p->u.array.length = 0;
|
||||
object_p->u1.property_list_cp = JMEM_CP_NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
values_p[index] = ECMA_VALUE_ARRAY_HOLE;
|
||||
|
||||
if (++ext_obj_p->u.array.hole_count > ECMA_FAST_ARRAY_MAX_HOLE_COUNT)
|
||||
{
|
||||
ecma_fast_array_convert_to_normal (object_p);
|
||||
}
|
||||
ext_obj_p->u.array.u.hole_count += ECMA_FAST_ARRAY_HOLE_ONE;
|
||||
} /* ecma_array_object_delete_property */
|
||||
|
||||
/**
|
||||
@@ -387,39 +395,22 @@ uint32_t
|
||||
ecma_delete_fast_array_properties (ecma_object_t *object_p, /**< fast access mode array */
|
||||
uint32_t new_length) /**< new length of the fast access mode array */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY);
|
||||
JERRY_ASSERT (ecma_op_object_is_fast_array (object_p));
|
||||
|
||||
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
JERRY_ASSERT (ext_obj_p->u.array.is_fast_mode);
|
||||
|
||||
ecma_ref_object (object_p);
|
||||
ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp);
|
||||
|
||||
uint32_t old_length = ext_obj_p->u.array.length;
|
||||
const uint32_t old_aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (old_length);
|
||||
JERRY_ASSERT (new_length < old_length);
|
||||
JERRY_ASSERT (ext_obj_p->u.array.is_fast_mode);
|
||||
|
||||
if (new_length == 0)
|
||||
{
|
||||
for (uint32_t i = 0; i < old_length; i++)
|
||||
{
|
||||
ecma_free_value_if_not_object (values_p[i]);
|
||||
}
|
||||
|
||||
jmem_heap_free_block (values_p, old_aligned_length * sizeof (ecma_value_t));
|
||||
object_p->u1.property_list_cp = JMEM_CP_NULL;
|
||||
ext_obj_p->u.array.length = new_length;
|
||||
ecma_deref_object (object_p);
|
||||
return new_length;
|
||||
}
|
||||
|
||||
for (uint32_t i = new_length; i < old_length; i++)
|
||||
{
|
||||
if (ecma_is_value_array_hole (values_p[i]))
|
||||
{
|
||||
ext_obj_p->u.array.hole_count = (uint8_t) JERRY_MAX (ext_obj_p->u.array.hole_count - 1, 0);
|
||||
ext_obj_p->u.array.u.hole_count -= ECMA_FAST_ARRAY_HOLE_ONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -427,21 +418,33 @@ ecma_delete_fast_array_properties (ecma_object_t *object_p, /**< fast access mod
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t new_aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (new_length);
|
||||
jmem_cpointer_t new_property_list_cp;
|
||||
|
||||
ecma_value_t *new_values_p;
|
||||
new_values_p = (ecma_value_t *) jmem_heap_realloc_block (values_p,
|
||||
old_aligned_length * sizeof (ecma_value_t),
|
||||
new_aligned_length * sizeof (ecma_value_t));
|
||||
|
||||
for (uint32_t i = new_length; i < new_aligned_length; i++)
|
||||
if (new_length == 0)
|
||||
{
|
||||
new_values_p[i] = ECMA_VALUE_ARRAY_HOLE;
|
||||
jmem_heap_free_block (values_p, old_aligned_length * sizeof (ecma_value_t));
|
||||
new_property_list_cp = JMEM_CP_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint32_t new_aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (new_length);
|
||||
|
||||
ecma_value_t *new_values_p;
|
||||
new_values_p = (ecma_value_t *) jmem_heap_realloc_block (values_p,
|
||||
old_aligned_length * sizeof (ecma_value_t),
|
||||
new_aligned_length * sizeof (ecma_value_t));
|
||||
|
||||
for (uint32_t i = new_length; i < new_aligned_length; i++)
|
||||
{
|
||||
new_values_p[i] = ECMA_VALUE_ARRAY_HOLE;
|
||||
}
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER (new_property_list_cp, new_values_p);
|
||||
}
|
||||
|
||||
ext_obj_p->u.array.length = new_length;
|
||||
object_p->u1.property_list_cp = new_property_list_cp;
|
||||
|
||||
ECMA_SET_POINTER (object_p->u1.property_list_cp, new_values_p);
|
||||
ecma_deref_object (object_p);
|
||||
|
||||
return new_length;
|
||||
@@ -457,12 +460,11 @@ static void
|
||||
ecma_fast_array_set_length (ecma_object_t *object_p, /**< fast access mode array object */
|
||||
uint32_t new_length) /**< new length of the fast access mode array object*/
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY);
|
||||
JERRY_ASSERT (ecma_op_object_is_fast_array (object_p));
|
||||
|
||||
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
|
||||
uint32_t old_length = ext_obj_p->u.array.length;
|
||||
|
||||
JERRY_ASSERT (ext_obj_p->u.array.is_fast_mode);
|
||||
JERRY_ASSERT (new_length >= old_length);
|
||||
|
||||
if (new_length == old_length)
|
||||
@@ -470,18 +472,18 @@ ecma_fast_array_set_length (ecma_object_t *object_p, /**< fast access mode array
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t new_holes = new_length - old_length - 1;
|
||||
uint32_t old_holes = ext_obj_p->u.array.u.hole_count;
|
||||
uint32_t new_holes = new_length - old_length;
|
||||
|
||||
JERRY_ASSERT (ext_obj_p->u.array.hole_count <= ECMA_FAST_ARRAY_MAX_HOLE_COUNT);
|
||||
|
||||
if (new_holes > (uint32_t) (ECMA_FAST_ARRAY_MAX_HOLE_COUNT - ext_obj_p->u.array.hole_count))
|
||||
if (JERRY_UNLIKELY (new_holes > ECMA_FAST_ARRAY_MAX_NEW_HOLES_COUNT
|
||||
|| ((old_holes >> ECMA_FAST_ARRAY_HOLE_SHIFT) + new_holes) > ECMA_FAST_ARRAY_MAX_HOLE_COUNT))
|
||||
{
|
||||
ecma_fast_array_convert_to_normal (object_p);
|
||||
return;
|
||||
}
|
||||
|
||||
ecma_fast_array_extend (object_p, new_length);
|
||||
ext_obj_p->u.array.hole_count = (uint8_t) (ext_obj_p->u.array.hole_count + new_holes);
|
||||
else
|
||||
{
|
||||
ecma_fast_array_extend (object_p, new_length);
|
||||
}
|
||||
|
||||
return;
|
||||
} /* ecma_fast_array_set_length */
|
||||
@@ -498,11 +500,9 @@ ecma_collection_t *
|
||||
ecma_fast_array_get_property_names (ecma_object_t *object_p, /**< fast access mode array object */
|
||||
uint32_t opts) /**< any combination of ecma_list_properties_options_t values */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY);
|
||||
JERRY_ASSERT (ecma_op_object_is_fast_array (object_p));
|
||||
|
||||
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
|
||||
JERRY_ASSERT (ext_obj_p->u.array.is_fast_mode);
|
||||
|
||||
ecma_collection_t *ret_p = ecma_new_collection ();
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
@@ -610,7 +610,7 @@ ecma_op_create_array_object (const ecma_value_t *arguments_list_p, /**< list of
|
||||
return ecma_make_object_value (ecma_op_new_array_object (length));
|
||||
}
|
||||
|
||||
JERRY_ASSERT (((ecma_extended_object_t *) object_p)->u.array.is_fast_mode);
|
||||
JERRY_ASSERT (ecma_op_object_is_fast_array (object_p));
|
||||
|
||||
return ecma_make_object_value (object_p);
|
||||
}
|
||||
@@ -637,6 +637,7 @@ ecma_op_create_array_object (const ecma_value_t *arguments_list_p, /**< list of
|
||||
}
|
||||
|
||||
ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp);
|
||||
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
for (uint32_t index = 0;
|
||||
index < array_items_count;
|
||||
@@ -646,6 +647,8 @@ ecma_op_create_array_object (const ecma_value_t *arguments_list_p, /**< list of
|
||||
values_p[index] = ecma_copy_value_if_not_object (array_items_p[index]);
|
||||
}
|
||||
|
||||
ext_obj_p->u.array.u.hole_count -= ECMA_FAST_ARRAY_HOLE_ONE * array_items_count;
|
||||
|
||||
return ecma_make_object_value (object_p);
|
||||
} /* ecma_op_create_array_object */
|
||||
|
||||
@@ -697,9 +700,7 @@ ecma_delete_array_properties (ecma_object_t *object_p, /**< object */
|
||||
JERRY_ASSERT (new_length < old_length);
|
||||
JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY);
|
||||
|
||||
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (ext_obj_p->u.array.is_fast_mode)
|
||||
if (ecma_op_object_is_fast_array (object_p))
|
||||
{
|
||||
return ecma_delete_fast_array_properties (object_p, new_length);
|
||||
}
|
||||
@@ -906,17 +907,17 @@ ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object
|
||||
{
|
||||
if (!(flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE))
|
||||
{
|
||||
uint8_t new_prop_value = (uint8_t) (ext_object_p->u.array.length_prop & ~ECMA_PROPERTY_FLAG_WRITABLE);
|
||||
ext_object_p->u.array.length_prop = new_prop_value;
|
||||
uint8_t new_prop_value = (uint8_t) (ext_object_p->u.array.u.length_prop & ~ECMA_PROPERTY_FLAG_WRITABLE);
|
||||
ext_object_p->u.array.u.length_prop = new_prop_value;
|
||||
}
|
||||
else if (!ecma_is_property_writable (ext_object_p->u.array.length_prop))
|
||||
else if (!ecma_is_property_writable (ext_object_p->u.array.u.length_prop))
|
||||
{
|
||||
return ecma_reject (is_throw);
|
||||
}
|
||||
}
|
||||
return ECMA_VALUE_TRUE;
|
||||
}
|
||||
else if (!ecma_is_property_writable (ext_object_p->u.array.length_prop))
|
||||
else if (!ecma_is_property_writable (ext_object_p->u.array.u.length_prop))
|
||||
{
|
||||
return ecma_reject (is_throw);
|
||||
}
|
||||
@@ -927,7 +928,7 @@ ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object
|
||||
{
|
||||
current_len_uint32 = ecma_delete_array_properties (object_p, new_len_uint32, old_len_uint32);
|
||||
}
|
||||
else if (ext_object_p->u.array.is_fast_mode)
|
||||
else if (ecma_op_object_is_fast_array (object_p))
|
||||
{
|
||||
ecma_fast_array_set_length (object_p, new_len_uint32);
|
||||
}
|
||||
@@ -937,8 +938,8 @@ ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object
|
||||
if ((flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE_DEFINED)
|
||||
&& !(flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE))
|
||||
{
|
||||
uint8_t new_prop_value = (uint8_t) (ext_object_p->u.array.length_prop & ~ECMA_PROPERTY_FLAG_WRITABLE);
|
||||
ext_object_p->u.array.length_prop = new_prop_value;
|
||||
uint8_t new_prop_value = (uint8_t) (ext_object_p->u.array.u.length_prop & ~ECMA_PROPERTY_FLAG_WRITABLE);
|
||||
ext_object_p->u.array.u.length_prop = new_prop_value;
|
||||
}
|
||||
|
||||
if (current_len_uint32 == new_len_uint32)
|
||||
@@ -1027,7 +1028,7 @@ ecma_op_array_object_define_own_property (ecma_object_t *object_p, /**< the arra
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (ext_object_p->u.array.is_fast_mode)
|
||||
if (ecma_op_object_is_fast_array (object_p))
|
||||
{
|
||||
if ((property_desc_p->flags & ECMA_FAST_ARRAY_DATA_PROP_FLAGS) == ECMA_FAST_ARRAY_DATA_PROP_FLAGS)
|
||||
{
|
||||
@@ -1042,7 +1043,7 @@ ecma_op_array_object_define_own_property (ecma_object_t *object_p, /**< the arra
|
||||
return ECMA_VALUE_TRUE;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (!ext_object_p->u.array.is_fast_mode);
|
||||
JERRY_ASSERT (!ecma_op_array_is_fast_array (ext_object_p));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1050,7 +1051,7 @@ ecma_op_array_object_define_own_property (ecma_object_t *object_p, /**< the arra
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_ASSERT (!ext_object_p->u.array.is_fast_mode);
|
||||
JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p));
|
||||
uint32_t index = ecma_string_get_array_index (property_name_p);
|
||||
|
||||
if (index == ECMA_STRING_NOT_ARRAY_INDEX)
|
||||
@@ -1060,7 +1061,7 @@ ecma_op_array_object_define_own_property (ecma_object_t *object_p, /**< the arra
|
||||
|
||||
bool update_length = (index >= ext_object_p->u.array.length);
|
||||
|
||||
if (update_length && !ecma_is_property_writable (ext_object_p->u.array.length_prop))
|
||||
if (update_length && !ecma_is_property_writable (ext_object_p->u.array.u.length_prop))
|
||||
{
|
||||
return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW);
|
||||
}
|
||||
|
||||
@@ -25,12 +25,28 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Maximum number of array holes in a fast mode access array.
|
||||
* If the number of holes exceeds this limit, the array is converted back
|
||||
* Maximum number of new array holes in a fast mode access array.
|
||||
* If the number of new holes exceeds this limit, the array is converted back
|
||||
* to normal property list based array.
|
||||
*/
|
||||
#define ECMA_FAST_ARRAY_MAX_HOLE_COUNT 32
|
||||
#define ECMA_FAST_ARRAY_MAX_NEW_HOLES_COUNT 32
|
||||
|
||||
/**
|
||||
* Bitshift index for fast array hole count representation
|
||||
*/
|
||||
#define ECMA_FAST_ARRAY_HOLE_SHIFT 8
|
||||
|
||||
/**
|
||||
* This number represents 1 array hole in underlying buffer of a fast acces mode array
|
||||
*/
|
||||
#define ECMA_FAST_ARRAY_HOLE_ONE (1 << ECMA_FAST_ARRAY_HOLE_SHIFT)
|
||||
|
||||
/**
|
||||
* Maximum number of array holes in a fast access mode array
|
||||
*/
|
||||
#define ECMA_FAST_ARRAY_MAX_HOLE_COUNT (1 << 24)
|
||||
|
||||
/**
|
||||
* Flags for ecma_op_array_object_set_length
|
||||
@@ -52,6 +68,12 @@ ecma_op_new_array_object (ecma_length_t length);
|
||||
ecma_object_t *
|
||||
ecma_op_new_fast_array_object (ecma_length_t length);
|
||||
|
||||
bool
|
||||
ecma_op_object_is_fast_array (ecma_object_t *object_p);
|
||||
|
||||
bool
|
||||
ecma_op_array_is_fast_array (ecma_extended_object_t *array_p);
|
||||
|
||||
ecma_value_t *
|
||||
ecma_fast_array_extend (ecma_object_t *object_p, uint32_t new_lengt);
|
||||
|
||||
|
||||
@@ -247,8 +247,7 @@ ecma_op_container_to_key (ecma_value_t key_arg) /**< key argument */
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (key_arg);
|
||||
ecma_string_t *key_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_MAP_KEY);
|
||||
|
||||
if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY
|
||||
&& ((ecma_extended_object_t *) obj_p)->u.array.is_fast_mode)
|
||||
if (ecma_op_object_is_fast_array (obj_p))
|
||||
{
|
||||
ecma_fast_array_convert_to_normal (obj_p);
|
||||
}
|
||||
|
||||
@@ -284,8 +284,7 @@ ecma_op_general_object_define_own_property (ecma_object_t *object_p, /**< the ob
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL
|
||||
&& !ecma_is_lexical_environment (object_p));
|
||||
JERRY_ASSERT (ecma_get_object_type (object_p) != ECMA_OBJECT_TYPE_ARRAY
|
||||
|| !((ecma_extended_object_t *) object_p)->u.array.is_fast_mode);
|
||||
JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p));
|
||||
JERRY_ASSERT (property_name_p != NULL);
|
||||
|
||||
ecma_property_types_t property_desc_type = ECMA_PROPERTY_TYPE_GENERIC;
|
||||
|
||||
@@ -134,10 +134,10 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */
|
||||
property_ref_p->virtual_value = ecma_make_uint32_value (ext_object_p->u.array.length);
|
||||
}
|
||||
|
||||
return ext_object_p->u.array.length_prop;
|
||||
return ext_object_p->u.array.u.length_prop & (ECMA_PROPERTY_TYPE_VIRTUAL | ECMA_PROPERTY_FLAG_WRITABLE);
|
||||
}
|
||||
|
||||
if (ext_object_p->u.array.is_fast_mode)
|
||||
if (ecma_op_array_is_fast_array (ext_object_p))
|
||||
{
|
||||
uint32_t index = ecma_string_get_array_index (property_name_p);
|
||||
|
||||
@@ -492,7 +492,7 @@ ecma_op_object_find_own (ecma_value_t base_value, /**< base value */
|
||||
return ecma_make_uint32_value (ext_object_p->u.array.length);
|
||||
}
|
||||
|
||||
if (JERRY_LIKELY (ext_object_p->u.array.is_fast_mode))
|
||||
if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_object_p)))
|
||||
{
|
||||
uint32_t index = ecma_string_get_array_index (property_name_p);
|
||||
|
||||
@@ -765,8 +765,7 @@ ecma_op_object_get_own_data_prop (ecma_object_t *object_p, /**< the object */
|
||||
ecma_string_t *property_name_p) /**< property name */
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_lexical_environment (object_p)
|
||||
|| ecma_get_object_type (object_p) != ECMA_OBJECT_TYPE_ARRAY
|
||||
|| !((ecma_extended_object_t *) object_p)->u.array.is_fast_mode);
|
||||
|| !ecma_op_object_is_fast_array (object_p));
|
||||
|
||||
ecma_value_t result = ecma_op_object_find_own (ecma_make_object_value (object_p),
|
||||
object_p,
|
||||
@@ -1066,7 +1065,7 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */
|
||||
|
||||
if (ecma_string_is_length (property_name_p))
|
||||
{
|
||||
if (ecma_is_property_writable (ext_object_p->u.array.length_prop))
|
||||
if (ecma_is_property_writable (ext_object_p->u.array.u.length_prop))
|
||||
{
|
||||
return ecma_op_array_object_set_length (object_p, value, 0);
|
||||
}
|
||||
@@ -1074,7 +1073,7 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */
|
||||
return ecma_reject (is_throw);
|
||||
}
|
||||
|
||||
if (JERRY_LIKELY (ext_object_p->u.array.is_fast_mode))
|
||||
if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_object_p)))
|
||||
{
|
||||
if (JERRY_UNLIKELY (!ecma_get_object_extensible (object_p)))
|
||||
{
|
||||
@@ -1093,7 +1092,7 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_ASSERT (!(ext_object_p->u.array.is_fast_mode));
|
||||
JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p));
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1313,7 +1312,7 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */
|
||||
if (index < UINT32_MAX
|
||||
&& index >= ext_object_p->u.array.length)
|
||||
{
|
||||
if (!ecma_is_property_writable (ext_object_p->u.array.length_prop))
|
||||
if (!ecma_is_property_writable (ext_object_p->u.array.u.length_prop))
|
||||
{
|
||||
return ecma_reject (is_throw);
|
||||
}
|
||||
@@ -1756,14 +1755,9 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
JERRY_ASSERT (obj_p != NULL
|
||||
&& !ecma_is_lexical_environment (obj_p));
|
||||
|
||||
if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY)
|
||||
if (ecma_op_object_is_fast_array (obj_p))
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
|
||||
|
||||
if (ext_object_p->u.array.is_fast_mode)
|
||||
{
|
||||
return ecma_fast_array_get_property_names (obj_p, opts);
|
||||
}
|
||||
return ecma_fast_array_get_property_names (obj_p, opts);
|
||||
}
|
||||
|
||||
ecma_collection_t *ret_p = ecma_new_collection ();
|
||||
@@ -1905,9 +1899,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
|
||||
jmem_cpointer_t prop_iter_cp = prototype_chain_iter_p->u1.property_list_cp;
|
||||
|
||||
if (ecma_get_object_type (prototype_chain_iter_p) == ECMA_OBJECT_TYPE_ARRAY
|
||||
&& ((ecma_extended_object_t *) prototype_chain_iter_p)->u.array.is_fast_mode
|
||||
&& prop_iter_cp != JMEM_CP_NULL)
|
||||
if (ecma_op_object_is_fast_array (prototype_chain_iter_p) && prop_iter_cp != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) prototype_chain_iter_p;
|
||||
|
||||
|
||||
+73
-2
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "ecma-alloc.h"
|
||||
#include "ecma-array-object.h"
|
||||
#include "ecma-builtins.h"
|
||||
#include "ecma-conversion.h"
|
||||
#include "ecma-exceptions.h"
|
||||
@@ -92,8 +93,7 @@ opfunc_set_accessor (bool is_getter, /**< is getter accessor */
|
||||
{
|
||||
ecma_object_t *object_p = ecma_get_object_from_value (object);
|
||||
|
||||
JERRY_ASSERT (ecma_get_object_type (object_p) != ECMA_OBJECT_TYPE_ARRAY
|
||||
|| !((ecma_extended_object_t *) object_p)->u.array.is_fast_mode);
|
||||
JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p));
|
||||
|
||||
ecma_property_t *property_p = ecma_find_named_property (object_p, accessor_name_p);
|
||||
|
||||
@@ -256,6 +256,77 @@ opfunc_for_in (ecma_value_t left_value, /**< left value */
|
||||
return NULL;
|
||||
} /* opfunc_for_in */
|
||||
|
||||
/**
|
||||
* 'VM_OC_APPEND_ARRAY' opcode handler, for setting array object properties
|
||||
*/
|
||||
void JERRY_ATTR_NOINLINE
|
||||
opfunc_append_array (ecma_value_t *stack_top_p, /**< current stack top */
|
||||
uint8_t values_length) /**< number of elements to set */
|
||||
{
|
||||
ecma_object_t *array_obj_p = ecma_get_object_from_value (stack_top_p[-1]);
|
||||
|
||||
JERRY_ASSERT (ecma_get_object_type (array_obj_p) == ECMA_OBJECT_TYPE_ARRAY);
|
||||
|
||||
ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_obj_p;
|
||||
uint32_t old_length = ext_array_obj_p->u.array.length;
|
||||
|
||||
if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_array_obj_p)))
|
||||
{
|
||||
uint32_t filled_holes = 0;
|
||||
ecma_value_t *values_p = ecma_fast_array_extend (array_obj_p, old_length + values_length);
|
||||
|
||||
for (uint32_t i = 0; i < values_length; i++)
|
||||
{
|
||||
values_p[old_length + i] = stack_top_p[i];
|
||||
|
||||
if (!ecma_is_value_array_hole (stack_top_p[i]))
|
||||
{
|
||||
filled_holes++;
|
||||
|
||||
if (ecma_is_value_object (stack_top_p[i]))
|
||||
{
|
||||
ecma_deref_object (ecma_get_object_from_value (stack_top_p[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ext_array_obj_p->u.array.u.hole_count -= filled_holes * ECMA_FAST_ARRAY_HOLE_ONE;
|
||||
|
||||
if (JERRY_UNLIKELY ((values_length - filled_holes) > ECMA_FAST_ARRAY_MAX_NEW_HOLES_COUNT))
|
||||
{
|
||||
ecma_fast_array_convert_to_normal (array_obj_p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t i = 0; i < values_length; i++)
|
||||
{
|
||||
if (!ecma_is_value_array_hole (stack_top_p[i]))
|
||||
{
|
||||
ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (old_length + i);
|
||||
|
||||
ecma_property_value_t *prop_value_p;
|
||||
|
||||
prop_value_p = ecma_create_named_data_property (array_obj_p,
|
||||
index_str_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
|
||||
NULL);
|
||||
|
||||
ecma_deref_ecma_string (index_str_p);
|
||||
prop_value_p->value = stack_top_p[i];
|
||||
|
||||
if (ecma_is_value_object (stack_top_p[i]))
|
||||
{
|
||||
ecma_free_value (stack_top_p[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ext_array_obj_p->u.array.length = old_length + values_length;
|
||||
}
|
||||
}
|
||||
} /* opfunc_append_array */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@@ -93,6 +93,9 @@ vm_op_delete_var (ecma_value_t name_literal, ecma_object_t *lex_env_p);
|
||||
ecma_collection_t *
|
||||
opfunc_for_in (ecma_value_t left_value, ecma_value_t *result_obj_p);
|
||||
|
||||
void
|
||||
opfunc_append_array (ecma_value_t *stack_top_p, uint8_t values_length);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@@ -70,7 +70,7 @@ vm_get_backtrace (uint32_t max_depth) /**< maximum backtrace depth, 0 = unlimite
|
||||
|
||||
vm_frame_ctx_t *context_p = JERRY_CONTEXT (vm_top_context_p);
|
||||
ecma_object_t *array_p = ecma_get_object_from_value (result_array);
|
||||
JERRY_ASSERT (((ecma_extended_object_t *) array_p)->u.array.is_fast_mode);
|
||||
JERRY_ASSERT (ecma_op_object_is_fast_array (array_p));
|
||||
uint32_t index = 0;
|
||||
|
||||
while (context_p != NULL)
|
||||
|
||||
+4
-63
@@ -67,7 +67,7 @@ vm_op_get_value (ecma_value_t object, /**< base object */
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (JERRY_LIKELY (ext_object_p->u.array.is_fast_mode
|
||||
if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_object_p)
|
||||
&& (uint32_t) int_value < ext_object_p->u.array.length))
|
||||
{
|
||||
ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp);
|
||||
@@ -1305,8 +1305,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
|
||||
ecma_object_t *object_p = ecma_get_object_from_value (stack_top_p[index]);
|
||||
|
||||
JERRY_ASSERT (ecma_get_object_type (object_p) != ECMA_OBJECT_TYPE_ARRAY
|
||||
|| !((ecma_extended_object_t *) object_p)->u.array.is_fast_mode);
|
||||
JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p));
|
||||
|
||||
ecma_property_t *property_p = ecma_find_named_property (object_p, prop_name_p);
|
||||
|
||||
@@ -1711,67 +1710,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
}
|
||||
case VM_OC_APPEND_ARRAY:
|
||||
{
|
||||
ecma_object_t *array_obj_p;
|
||||
uint32_t values_length = *byte_code_p++;
|
||||
|
||||
uint8_t values_length = *byte_code_p++;
|
||||
stack_top_p -= values_length;
|
||||
|
||||
array_obj_p = ecma_get_object_from_value (stack_top_p[-1]);
|
||||
ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_obj_p;
|
||||
uint32_t old_length = ext_array_obj_p->u.array.length;
|
||||
|
||||
if (JERRY_LIKELY (ext_array_obj_p->u.array.is_fast_mode))
|
||||
{
|
||||
ecma_value_t *values_p = ecma_fast_array_extend (array_obj_p, old_length + values_length);
|
||||
|
||||
for (uint32_t i = 0; i < values_length; i++)
|
||||
{
|
||||
values_p[old_length + i] = stack_top_p[i];
|
||||
|
||||
if (JERRY_UNLIKELY (ecma_is_value_array_hole (stack_top_p[i])))
|
||||
{
|
||||
ext_array_obj_p->u.array.hole_count++;
|
||||
}
|
||||
else if (ecma_is_value_object (stack_top_p[i]))
|
||||
{
|
||||
ecma_deref_object (ecma_get_object_from_value (stack_top_p[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if (JERRY_UNLIKELY (ext_array_obj_p->u.array.length > ECMA_FAST_ARRAY_MAX_HOLE_COUNT))
|
||||
{
|
||||
ecma_fast_array_convert_to_normal (array_obj_p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t i = 0; i < values_length; i++)
|
||||
{
|
||||
if (!ecma_is_value_array_hole (stack_top_p[i]))
|
||||
{
|
||||
ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (old_length + i);
|
||||
|
||||
ecma_property_value_t *prop_value_p;
|
||||
|
||||
prop_value_p = ecma_create_named_data_property (array_obj_p,
|
||||
index_str_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
|
||||
NULL);
|
||||
|
||||
ecma_deref_ecma_string (index_str_p);
|
||||
prop_value_p->value = stack_top_p[i];
|
||||
|
||||
if (ecma_is_value_object (stack_top_p[i]))
|
||||
{
|
||||
ecma_free_value (stack_top_p[i]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ext_array_obj_p->u.array.length = old_length + values_length;
|
||||
}
|
||||
|
||||
opfunc_append_array (stack_top_p, values_length);
|
||||
continue;
|
||||
}
|
||||
case VM_OC_PUSH_UNDEFINED_BASE:
|
||||
|
||||
Reference in New Issue
Block a user