Rework ecma collection (#3086)

After this patch the ecma value collection is a resizable buffer of ecma-values where the adjacent elements are allocated next to each other.

JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
Robert Fancsik
2019-09-12 13:05:24 +02:00
committed by Zoltan Herczeg
parent f3d3c34c30
commit fc30f003ba
35 changed files with 511 additions and 776 deletions
+19 -13
View File
@@ -200,21 +200,29 @@ ecma_gc_mark_promise_object (ecma_extended_object_t *ext_object_p) /**< extended
}
/* Mark all reactions. */
ecma_value_t *ecma_value_p;
ecma_value_p = ecma_collection_iterator_init (((ecma_promise_object_t *) ext_object_p)->fulfill_reactions);
ecma_promise_object_t *promise_object_p = (ecma_promise_object_t *) ext_object_p;
ecma_collection_t *collection_p = promise_object_p->fulfill_reactions;
while (ecma_value_p != NULL)
if (collection_p != NULL)
{
ecma_gc_set_object_visited (ecma_get_object_from_value (*ecma_value_p));
ecma_value_p = ecma_collection_iterator_next (ecma_value_p);
ecma_value_t *buffer_p = collection_p->buffer_p;
for (uint32_t i = 0; i < collection_p->item_count; i++)
{
ecma_gc_set_object_visited (ecma_get_object_from_value (buffer_p[i]));
}
}
ecma_value_p = ecma_collection_iterator_init (((ecma_promise_object_t *) ext_object_p)->reject_reactions);
collection_p = promise_object_p->reject_reactions;
while (ecma_value_p != NULL)
if (collection_p != NULL)
{
ecma_gc_set_object_visited (ecma_get_object_from_value (*ecma_value_p));
ecma_value_p = ecma_collection_iterator_next (ecma_value_p);
ecma_value_t *buffer_p = collection_p->buffer_p;
for (uint32_t i = 0; i < collection_p->item_count; i++)
{
ecma_gc_set_object_visited (ecma_get_object_from_value (buffer_p[i]));
}
}
} /* ecma_gc_mark_promise_object */
@@ -768,10 +776,8 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
case LIT_MAGIC_STRING_PROMISE_UL:
{
ecma_free_value_if_not_object (ext_object_p->u.class_prop.u.value);
ecma_free_values_collection (((ecma_promise_object_t *) object_p)->fulfill_reactions,
ECMA_COLLECTION_NO_REF_OBJECTS);
ecma_free_values_collection (((ecma_promise_object_t *) object_p)->reject_reactions,
ECMA_COLLECTION_NO_REF_OBJECTS);
ecma_collection_free_if_not_object (((ecma_promise_object_t *) object_p)->fulfill_reactions);
ecma_collection_free_if_not_object (((ecma_promise_object_t *) object_p)->reject_reactions);
ecma_dealloc_extended_object (object_p, sizeof (ecma_promise_object_t));
return;
}
+20 -42
View File
@@ -76,7 +76,6 @@ typedef enum
ECMA_TYPE_SYMBOL = 4, /**< pointer to description of a symbol */
ECMA_TYPE_DIRECT_STRING = 5, /**< directly encoded string values */
ECMA_TYPE_ERROR = 7, /**< pointer to description of an error reference (only supported by C API) */
ECMA_TYPE_POINTER = ECMA_TYPE_ERROR, /**< a generic aligned pointer */
ECMA_TYPE_SNAPSHOT_OFFSET = ECMA_TYPE_ERROR, /**< offset to a snapshot number/string */
ECMA_TYPE___MAX = ECMA_TYPE_ERROR /** highest value for ecma types */
} ecma_type_t;
@@ -1216,57 +1215,36 @@ typedef double ecma_number_t;
*/
#define ECMA_STRING_NOT_ARRAY_INDEX UINT32_MAX
/*
* Ecma-collection: a growable list of ecma-values. Currently the list is
* a chain list, where appending new items at the end is cheap operation.
*
* Enumerating elements is also cheap, since each page is terminated by a
* special ecma-value: collection-type. This type has a pointer to the next
* chunk. The last chunk is terminated by a NULL pointer. There when the
* next value is requested from the iterator it simply checks the next
* memory location. If it is not a collection-type value, it returns with
* the value. Otherwise it gets the start address of the next chunk, and
* return the value there.
*
* The collection-type value is always the last item of a collection chunk,
* even if the chunk is not completely filled with values (this is only true
* for the last chunk). Each chunk must have at least one non collection-type
* value as well.
*/
/**
* Collection flags.
*/
typedef enum
{
ECMA_COLLECTION_NO_REF_OBJECTS = (1u << 0), /**< do not increase the refcount of objects */
ECMA_COLLECTION_NO_COPY = (1u << 1), /**< do not copy values */
} ecma_collection_flag_t;
/**
* Description of a collection's header.
* Ecma-collection: a growable list of ecma-values.
*/
typedef struct
{
jmem_cpointer_t first_chunk_cp; /**< compressed pointer to first chunk with collection's data */
jmem_cpointer_t last_chunk_cp; /**< compressed pointer to last chunk with collection's data */
ecma_length_t item_count; /**< number of items in the collection */
} ecma_collection_header_t;
uint32_t item_count; /**< number of items in the collection */
uint32_t capacity; /**< number of items can be stored in the underlying buffer */
ecma_value_t *buffer_p; /**< underlying data buffer */
} ecma_collection_t;
/**
* Maximum number of items stored by a collection chunk (excluding the last collection-type value).
* Initial capacity of an ecma-collection
*/
#define ECMA_COLLECTION_CHUNK_ITEMS 5
#define ECMA_COLLECTION_INITIAL_CAPACITY 4
/**
* Collection chunk item.
* Ecma-collenction grow factor when the collection underlying buffer need to be reallocated
*/
typedef struct
{
ecma_value_t items[ECMA_COLLECTION_CHUNK_ITEMS + 1]; /**< ecma-value list, where the last value is a special
* collection-type value which points to the next chunk,
* so the chunk area is enlarged by one for this value */
} ecma_collection_chunk_t;
#define ECMA_COLLECTION_GROW_FACTOR (ECMA_COLLECTION_INITIAL_CAPACITY * 2)
/**
* Compute the total allocated size of the collection based on it's capacity
*/
#define ECMA_COLLECTION_ALLOCATED_SIZE(capacity) \
(uint32_t) (sizeof (ecma_collection_t) + (capacity * sizeof (ecma_value_t)))
/**
* Initial allocated size of an ecma-collection
*/
#define ECMA_COLLECTION_INITIAL_SIZE ECMA_COLLECTION_ALLOCATED_SIZE (ECMA_COLLECTION_INITIAL_CAPACITY)
/**
* Direct string types (2 bit).
@@ -0,0 +1,150 @@
/* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecma-alloc.h"
#include "ecma-gc.h"
#include "ecma-globals.h"
#include "ecma-helpers.h"
#include "jrt.h"
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmahelpers Helpers for operations with ECMA data types
* @{
*/
/**
* Allocate a collection of ecma values.
*
* @return pointer to the collection
*/
ecma_collection_t *
ecma_new_collection (void)
{
ecma_collection_t *collection_p;
collection_p = (ecma_collection_t *) jmem_heap_alloc_block (sizeof (ecma_collection_t));
collection_p->item_count = 0;
collection_p->capacity = ECMA_COLLECTION_INITIAL_CAPACITY;
const uint32_t size = ECMA_COLLECTION_ALLOCATED_SIZE (ECMA_COLLECTION_INITIAL_CAPACITY);
collection_p->buffer_p = (ecma_value_t *) jmem_heap_alloc_block (size);
return collection_p;
} /* ecma_new_collection */
/**
* Deallocate a collection of ecma values without freeing it's values
*/
inline void JERRY_ATTR_ALWAYS_INLINE
ecma_collection_destroy (ecma_collection_t *collection_p) /**< value collection */
{
JERRY_ASSERT (collection_p != NULL);
jmem_heap_free_block (collection_p->buffer_p, ECMA_COLLECTION_ALLOCATED_SIZE (collection_p->capacity));
jmem_heap_free_block (collection_p, sizeof (ecma_collection_t));
} /* ecma_collection_destroy */
/**
* Free the object collection elements and deallocate the collection
*/
void
ecma_collection_free_objects (ecma_collection_t *collection_p) /**< value collection */
{
JERRY_ASSERT (collection_p != NULL);
ecma_value_t *buffer_p = collection_p->buffer_p;
for (uint32_t i = 0; i < collection_p->item_count; i++)
{
if (ecma_is_value_object (buffer_p[i]))
{
ecma_deref_object (ecma_get_object_from_value (buffer_p[i]));
}
}
ecma_collection_destroy (collection_p);
} /* ecma_collection_free_objects */
/**
* Free the non-object collection elements and deallocate the collection
*/
void
ecma_collection_free_if_not_object (ecma_collection_t *collection_p) /**< value collection */
{
JERRY_ASSERT (collection_p != NULL);
ecma_value_t *buffer_p = collection_p->buffer_p;
for (uint32_t i = 0; i < collection_p->item_count; i++)
{
ecma_free_value_if_not_object (buffer_p[i]);
}
ecma_collection_destroy (collection_p);
} /* ecma_collection_free_if_not_object */
/**
* Free the collection elements and deallocate the collection
*/
void
ecma_collection_free (ecma_collection_t *collection_p) /**< value collection */
{
JERRY_ASSERT (collection_p != NULL);
ecma_value_t *buffer_p = collection_p->buffer_p;
for (uint32_t i = 0; i < collection_p->item_count; i++)
{
ecma_free_value (buffer_p[i]);
}
ecma_collection_destroy (collection_p);
} /* ecma_collection_free */
/**
* Append new value to ecma values collection
*
* Note: The reference count of the values are not increased
*/
void
ecma_collection_push_back (ecma_collection_t *collection_p, /**< value collection */
ecma_value_t value) /**< ecma value to append */
{
JERRY_ASSERT (collection_p != NULL);
ecma_value_t *buffer_p = collection_p->buffer_p;
if (JERRY_LIKELY (collection_p->item_count < collection_p->capacity))
{
buffer_p[collection_p->item_count++] = value;
return;
}
const uint32_t new_capacity = collection_p->capacity + ECMA_COLLECTION_GROW_FACTOR;
const uint32_t old_size = ECMA_COLLECTION_ALLOCATED_SIZE (collection_p->capacity);
const uint32_t new_size = ECMA_COLLECTION_ALLOCATED_SIZE (new_capacity);
buffer_p = jmem_heap_realloc_block (buffer_p, old_size, new_size);
buffer_p[collection_p->item_count++] = value;
collection_p->capacity = new_capacity;
collection_p->buffer_p = buffer_p;
} /* ecma_collection_push_back */
/**
* @}
* @}
*/
-52
View File
@@ -389,18 +389,6 @@ 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 */
/**
* Check if the value is an aligned pointer.
*
* @return true - if the value contains an aligned pointer,
* false - otherwise
*/
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
ecma_is_value_pointer (ecma_value_t value) /**< ecma value */
{
return (ecma_get_value_type_field (value) == ECMA_TYPE_POINTER);
} /* ecma_is_value_pointer */
/**
* Debug assertion that specified value's type is one of ECMA-defined
* script-visible types, i.e.: undefined, null, boolean, number, string, object.
@@ -658,29 +646,6 @@ ecma_make_error_reference_value (const ecma_error_reference_t *error_ref_p) /**<
return ecma_pointer_to_ecma_value (error_ref_p) | ECMA_TYPE_ERROR;
} /* ecma_make_error_reference_value */
/**
* Create an ecma value from an aligned pointer
*
* @return ecma-value representation of the aligned pointer
*/
inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
ecma_make_pointer_value (const void *any_p) /**< any aligned pointer */
{
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
uintptr_t uint_ptr = (uintptr_t) any_p;
JERRY_ASSERT ((uint_ptr & ECMA_VALUE_TYPE_MASK) == 0);
return ((ecma_value_t) uint_ptr) | ECMA_TYPE_POINTER;
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
jmem_cpointer_t ptr_cp;
ECMA_SET_POINTER (ptr_cp, any_p);
return (((ecma_value_t) ptr_cp) << ECMA_VALUE_SHIFT) | ECMA_TYPE_POINTER;
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
} /* ecma_make_pointer_value */
/**
* Get integer value from an integer ecma value
*
@@ -813,23 +778,6 @@ ecma_get_error_reference_from_value (ecma_value_t value) /**< ecma value */
return (ecma_error_reference_t *) ecma_get_pointer_from_ecma_value (value);
} /* ecma_get_error_reference_from_value */
/**
* Get an aligned pointer from an ecma value
*
* @return pointer value
*/
inline void * JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
ecma_get_pointer_from_value (ecma_value_t value) /**< ecma value */
{
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_POINTER);
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
return (void *) (uintptr_t) ((value) & ~ECMA_VALUE_TYPE_MASK);
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
return ECMA_GET_POINTER (void, value >> ECMA_VALUE_SHIFT);
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
} /* ecma_get_pointer_from_value */
/**
* Invert a boolean value
*
@@ -1,201 +0,0 @@
/* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecma-alloc.h"
#include "ecma-globals.h"
#include "ecma-helpers.h"
#include "jrt.h"
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmahelpers Helpers for operations with ECMA data types
* @{
*/
/**
* The type of ecma error and ecma collection chunk must be the same.
*/
JERRY_STATIC_ASSERT (ECMA_TYPE_ERROR == ECMA_TYPE_POINTER,
ecma_type_error_must_be_the_same_as_ecma_type_pointer);
/**
* Allocate a collection of ecma values.
*
* @return pointer to the collection's header
*/
ecma_collection_header_t *
ecma_new_values_collection (void)
{
ecma_collection_header_t *header_p;
header_p = (ecma_collection_header_t *) jmem_pools_alloc (sizeof (ecma_collection_header_t));
header_p->item_count = 0;
header_p->first_chunk_cp = ECMA_NULL_POINTER;
header_p->last_chunk_cp = ECMA_NULL_POINTER;
return header_p;
} /* ecma_new_values_collection */
/**
* Free the collection of ecma values.
*/
void
ecma_free_values_collection (ecma_collection_header_t *header_p, /**< collection's header */
uint32_t flags) /**< combination of ecma_collection_flag_t flags */
{
jmem_cpointer_t chunk_cp = header_p->first_chunk_cp;
jmem_pools_free (header_p, sizeof (ecma_collection_header_t));
if (chunk_cp == JMEM_CP_NULL)
{
return;
}
ecma_collection_chunk_t *chunk_p = ECMA_GET_NON_NULL_POINTER (ecma_collection_chunk_t, chunk_cp);
do
{
ecma_value_t *item_p = chunk_p->items;
JERRY_ASSERT (!ecma_is_value_pointer (*item_p));
do
{
if (!(flags & ECMA_COLLECTION_NO_COPY)
&& (!ecma_is_value_object (*item_p)
|| !(flags & ECMA_COLLECTION_NO_REF_OBJECTS)))
{
ecma_free_value (*item_p);
}
item_p++;
}
while (!ecma_is_value_pointer (*item_p));
ecma_collection_chunk_t *next_chunk_p = (ecma_collection_chunk_t *) ecma_get_pointer_from_value (*item_p);
jmem_heap_free_block (chunk_p, sizeof (ecma_collection_chunk_t));
chunk_p = next_chunk_p;
}
while (chunk_p != NULL);
} /* ecma_free_values_collection */
/**
* Append new value to ecma values collection
*/
void
ecma_append_to_values_collection (ecma_collection_header_t *header_p, /**< collection's header */
ecma_value_t value, /**< ecma value to append */
uint32_t flags) /**< combination of ecma_collection_flag_t flags */
{
ecma_length_t item_index;
ecma_collection_chunk_t *chunk_p;
if (JERRY_UNLIKELY (header_p->item_count == 0))
{
item_index = 0;
chunk_p = (ecma_collection_chunk_t *) jmem_heap_alloc_block (sizeof (ecma_collection_chunk_t));
ECMA_SET_NON_NULL_POINTER (header_p->first_chunk_cp, chunk_p);
header_p->last_chunk_cp = header_p->first_chunk_cp;
}
else
{
item_index = header_p->item_count % ECMA_COLLECTION_CHUNK_ITEMS;
chunk_p = ECMA_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
header_p->last_chunk_cp);
if (JERRY_UNLIKELY (item_index == 0))
{
JERRY_ASSERT (ecma_is_value_pointer (chunk_p->items[ECMA_COLLECTION_CHUNK_ITEMS])
&& ecma_get_pointer_from_value (chunk_p->items[ECMA_COLLECTION_CHUNK_ITEMS]) == NULL);
ecma_collection_chunk_t *next_chunk_p;
next_chunk_p = (ecma_collection_chunk_t *) jmem_heap_alloc_block (sizeof (ecma_collection_chunk_t));
chunk_p->items[ECMA_COLLECTION_CHUNK_ITEMS] = ecma_make_pointer_value ((void *) next_chunk_p);
ECMA_SET_NON_NULL_POINTER (header_p->last_chunk_cp, next_chunk_p);
chunk_p = next_chunk_p;
}
else
{
JERRY_ASSERT (ecma_is_value_pointer (chunk_p->items[item_index])
&& ecma_get_pointer_from_value (chunk_p->items[item_index]) == NULL);
}
}
if (!(flags & ECMA_COLLECTION_NO_COPY)
&& (!ecma_is_value_object (value)
|| !(flags & ECMA_COLLECTION_NO_REF_OBJECTS)))
{
value = ecma_copy_value (value);
}
chunk_p->items[item_index] = value;
chunk_p->items[item_index + 1] = ecma_make_pointer_value (NULL);
header_p->item_count++;
} /* ecma_append_to_values_collection */
/**
* Initialize new collection iterator for the collection
*
* @return pointer to the first item
*/
ecma_value_t *
ecma_collection_iterator_init (ecma_collection_header_t *header_p) /**< header of collection */
{
if (JERRY_UNLIKELY (!header_p || header_p->item_count == 0))
{
return NULL;
}
ecma_collection_chunk_t *chunk_p = ECMA_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
header_p->first_chunk_cp);
return chunk_p->items;
} /* ecma_collection_iterator_init */
/**
* Move collection iterator to next element if there is any.
*
* @return pointer to the next item
*/
ecma_value_t *
ecma_collection_iterator_next (ecma_value_t *ecma_value_p) /**< current value */
{
JERRY_ASSERT (ecma_value_p != NULL);
ecma_value_p++;
if (JERRY_UNLIKELY (ecma_is_value_pointer (*ecma_value_p)))
{
ecma_value_p = ((ecma_collection_chunk_t *) ecma_get_pointer_from_value (*ecma_value_p))->items;
JERRY_ASSERT (ecma_value_p == NULL || !ecma_is_value_pointer (*ecma_value_p));
return ecma_value_p;
}
return ecma_value_p;
} /* ecma_collection_iterator_next */
/**
* @}
* @}
*/
+7 -12
View File
@@ -184,7 +184,6 @@ bool JERRY_ATTR_CONST ecma_is_value_direct_string (ecma_value_t value);
bool JERRY_ATTR_CONST ecma_is_value_non_direct_string (ecma_value_t value);
bool JERRY_ATTR_CONST ecma_is_value_object (ecma_value_t value);
bool JERRY_ATTR_CONST ecma_is_value_error_reference (ecma_value_t value);
bool JERRY_ATTR_CONST ecma_is_value_pointer (ecma_value_t value);
void ecma_check_value_type_is_spec_defined (ecma_value_t value);
@@ -203,7 +202,6 @@ ecma_value_t JERRY_ATTR_PURE ecma_make_prop_name_value (const ecma_string_t *ecm
ecma_value_t JERRY_ATTR_PURE ecma_make_magic_string_value (lit_magic_string_id_t id);
ecma_value_t JERRY_ATTR_PURE ecma_make_object_value (const ecma_object_t *object_p);
ecma_value_t JERRY_ATTR_PURE ecma_make_error_reference_value (const ecma_error_reference_t *error_ref_p);
ecma_value_t JERRY_ATTR_PURE ecma_make_pointer_value (const void *any_p);
ecma_integer_value_t JERRY_ATTR_CONST ecma_get_integer_from_value (ecma_value_t value);
ecma_number_t JERRY_ATTR_PURE ecma_get_float_from_value (ecma_value_t value);
ecma_number_t * ecma_get_pointer_from_float_value (ecma_value_t value);
@@ -215,7 +213,6 @@ ecma_string_t JERRY_ATTR_PURE *ecma_get_symbol_from_value (ecma_value_t value);
ecma_string_t JERRY_ATTR_PURE *ecma_get_prop_name_from_value (ecma_value_t value);
ecma_object_t JERRY_ATTR_PURE *ecma_get_object_from_value (ecma_value_t value);
ecma_error_reference_t JERRY_ATTR_PURE *ecma_get_error_reference_from_value (ecma_value_t value);
void * JERRY_ATTR_PURE ecma_get_pointer_from_value (ecma_value_t value);
ecma_value_t JERRY_ATTR_CONST ecma_invert_boolean_value (ecma_value_t value);
ecma_value_t ecma_copy_value (ecma_value_t value);
ecma_value_t ecma_fast_copy_value (ecma_value_t value);
@@ -351,15 +348,13 @@ lit_utf8_size_t ecma_number_to_binary_floating_point_number (ecma_number_t num,
lit_utf8_byte_t *out_digits_p,
int32_t *out_decimal_exp_p);
/* ecma-helpers-values-collection.c */
ecma_collection_header_t *ecma_new_values_collection (void);
void ecma_free_values_collection (ecma_collection_header_t *header_p, uint32_t flags);
void ecma_append_to_values_collection (ecma_collection_header_t *header_p, ecma_value_t v, uint32_t flags);
ecma_value_t *
ecma_collection_iterator_init (ecma_collection_header_t *header_p);
ecma_value_t *
ecma_collection_iterator_next (ecma_value_t *iterator_p);
/* ecma-helpers-collection.c */
ecma_collection_t *ecma_new_collection (void);
void ecma_collection_push_back (ecma_collection_t *collection_p, ecma_value_t value);
void ecma_collection_destroy (ecma_collection_t *collection_p);
void ecma_collection_free (ecma_collection_t *collection_p);
void ecma_collection_free_if_not_object (ecma_collection_t *collection_p);
void ecma_collection_free_objects (ecma_collection_t *collection_p);
/* ecma-helpers.c */
ecma_object_t *ecma_create_object (ecma_object_t *prototype_object_p, size_t ext_object_size, ecma_object_type_t type);
+19 -24
View File
@@ -298,7 +298,7 @@ ecma_find_or_create_literal_number (ecma_number_t number_arg) /**< number to be
* Append the value at the end of the appropriate list if it is not present there.
*/
void ecma_save_literals_append_value (ecma_value_t value, /**< value to be appended */
ecma_collection_header_t *lit_pool_p) /**< list of known values */
ecma_collection_t *lit_pool_p) /**< list of known values */
{
/* Unlike direct numbers, direct strings are converted to character literals. */
if (!ecma_is_value_string (value) && !ecma_is_value_float_number (value))
@@ -306,21 +306,19 @@ void ecma_save_literals_append_value (ecma_value_t value, /**< value to be appen
return;
}
ecma_value_t *iterator_p = ecma_collection_iterator_init (lit_pool_p);
ecma_value_t *buffer_p = lit_pool_p->buffer_p;
while (iterator_p != NULL)
for (uint32_t i = 0; i < lit_pool_p->item_count; i++)
{
/* Strings / numbers are direct strings or stored in the literal storage.
* Therefore direct comparison is enough to find the same strings / numbers. */
if (*iterator_p == value)
if (buffer_p[i] == value)
{
return;
}
iterator_p = ecma_collection_iterator_next (iterator_p);
}
ecma_append_to_values_collection (lit_pool_p, value, ECMA_COLLECTION_NO_COPY);
ecma_collection_push_back (lit_pool_p, value);
} /* ecma_save_literals_append_value */
/**
@@ -328,7 +326,7 @@ void ecma_save_literals_append_value (ecma_value_t value, /**< value to be appen
*/
void
ecma_save_literals_add_compiled_code (const ecma_compiled_code_t *compiled_code_p, /**< byte-code data */
ecma_collection_header_t *lit_pool_p) /**< list of known values */
ecma_collection_t *lit_pool_p) /**< list of known values */
{
ecma_value_t *literal_p;
uint32_t argument_end = 0;
@@ -414,7 +412,7 @@ ecma_save_literals_add_compiled_code (const ecma_compiled_code_t *compiled_code_
* false - otherwise
*/
bool
ecma_save_literals_for_snapshot (ecma_collection_header_t *lit_pool_p, /**< list of known values */
ecma_save_literals_for_snapshot (ecma_collection_t *lit_pool_p, /**< list of known values */
uint32_t *buffer_p, /**< [out] output snapshot buffer */
size_t buffer_size, /**< size of the buffer */
size_t *in_out_buffer_offset_p, /**< [in,out] write position in the buffer */
@@ -437,18 +435,18 @@ ecma_save_literals_for_snapshot (ecma_collection_header_t *lit_pool_p, /**< list
max_lit_table_size = (UINT32_MAX >> JERRY_SNAPSHOT_LITERAL_SHIFT);
}
ecma_value_t *iterator_p = ecma_collection_iterator_init (lit_pool_p);
ecma_value_t *lit_buffer_p = lit_pool_p->buffer_p;
/* Compute the size of the literal pool. */
while (iterator_p != NULL)
for (uint32_t i = 0; i < lit_pool_p->item_count; i++)
{
if (ecma_is_value_float_number (*iterator_p))
if (ecma_is_value_float_number (lit_buffer_p[i]))
{
lit_table_size += (uint32_t) sizeof (ecma_number_t);
}
else
{
ecma_string_t *string_p = ecma_get_string_from_value (*iterator_p);
ecma_string_t *string_p = ecma_get_string_from_value (lit_buffer_p[i]);
lit_table_size += (uint32_t) JERRY_ALIGNUP (sizeof (uint16_t) + ecma_string_get_size (string_p),
JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
@@ -457,11 +455,9 @@ ecma_save_literals_for_snapshot (ecma_collection_header_t *lit_pool_p, /**< list
/* Check whether enough space is available and the maximum size is not reached. */
if (lit_table_size > max_lit_table_size)
{
ecma_free_values_collection (lit_pool_p, ECMA_COLLECTION_NO_COPY);
ecma_collection_destroy (lit_pool_p);
return false;
}
iterator_p = ecma_collection_iterator_next (iterator_p);
}
lit_mem_to_snapshot_id_map_entry_t *map_p;
@@ -479,28 +475,28 @@ ecma_save_literals_for_snapshot (ecma_collection_header_t *lit_pool_p, /**< list
*out_map_p = map_p;
*out_map_len_p = total_count;
iterator_p = ecma_collection_iterator_init (lit_pool_p);
lit_buffer_p = lit_pool_p->buffer_p;
/* Generate literal pool data. */
while (iterator_p != NULL)
for (uint32_t i = 0; i < lit_pool_p->item_count; i++)
{
map_p->literal_id = *iterator_p;
map_p->literal_id = lit_buffer_p[i];
map_p->literal_offset = (literal_offset << JERRY_SNAPSHOT_LITERAL_SHIFT) | ECMA_TYPE_SNAPSHOT_OFFSET;
ecma_length_t length;
if (ecma_is_value_float_number (*iterator_p))
if (ecma_is_value_float_number (lit_buffer_p[i]))
{
map_p->literal_offset |= JERRY_SNAPSHOT_LITERAL_IS_NUMBER;
ecma_number_t num = ecma_get_float_from_value (*iterator_p);
ecma_number_t num = ecma_get_float_from_value (lit_buffer_p[i]);
memcpy (destination_p, &num, sizeof (ecma_number_t));
length = JERRY_ALIGNUP (sizeof (ecma_number_t), JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
}
else
{
ecma_string_t *string_p = ecma_get_string_from_value (*iterator_p);
ecma_string_t *string_p = ecma_get_string_from_value (lit_buffer_p[i]);
length = ecma_string_get_size (string_p);
*(uint16_t *) destination_p = (uint16_t) length;
@@ -514,11 +510,10 @@ ecma_save_literals_for_snapshot (ecma_collection_header_t *lit_pool_p, /**< list
destination_p += length;
literal_offset += length;
iterator_p = ecma_collection_iterator_next (iterator_p);
map_p++;
}
ecma_free_values_collection (lit_pool_p, ECMA_COLLECTION_NO_COPY);
ecma_collection_destroy (lit_pool_p);
return true;
} /* ecma_save_literals_for_snapshot */
+3 -3
View File
@@ -44,10 +44,10 @@ ecma_value_t ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p,
ecma_value_t ecma_find_or_create_literal_number (ecma_number_t number_arg);
#if ENABLED (JERRY_SNAPSHOT_SAVE)
void ecma_save_literals_append_value (ecma_value_t value, ecma_collection_header_t *lit_pool_p);
void ecma_save_literals_append_value (ecma_value_t value, ecma_collection_t *lit_pool_p);
void ecma_save_literals_add_compiled_code (const ecma_compiled_code_t *compiled_code_p,
ecma_collection_header_t *lit_pool_p);
bool ecma_save_literals_for_snapshot (ecma_collection_header_t *lit_pool_p, uint32_t *buffer_p, size_t buffer_size,
ecma_collection_t *lit_pool_p);
bool ecma_save_literals_for_snapshot (ecma_collection_t *lit_pool_p, uint32_t *buffer_p, size_t buffer_size,
size_t *in_out_buffer_offset_p, lit_mem_to_snapshot_id_map_entry_t **out_map_p,
uint32_t *out_map_len_p);
#endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */