Files
jerryscript/jerry-core/ecma/base/ecma-helpers-values-collection.c
T
Robert Fancsik 47f2f0ea8b General optimizations around compressed pointer management (#3019)
ECMA_GET_POINTER is removed from:
 - property list iteration
 - lexical environment chain iteration
 - prototype chain iteration

For all these iteration the compressed pointer can be used to get the elements and only decompressed them if it is necessary.

- Properly guard ecma property hashmap routines
- Remove the redundant NULL pointer check from ecma_create_property
- Remove ecma_gc_get_object_next since it became unnecessary
- Substitute ECMA_{GET,SET}_POINTER with ECMA_{GET,SET}_NON_NULL pointer when we can assume the pointer is not NULL
- Remove ecma_get_object_prototype and ecma_get_lex_env_outer_reference helper function the reduce the number of NULL pointer checks during decompressing the pointers
- Remove ecma_get_named_accessor_property_{getter,setter} helper functions for also reduce the number of NULL pointer check/decompressions
- Remove ECMA_PROPERTY_SEARCH_DEPTH_LIMIT since in ES5 there is no way to create circular prototype chain, and the ES2015 setPrototypeOf method can resolve this error so this check during the property lookup can be eliminated.

JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
2019-08-26 17:42:02 +02:00

202 lines
5.8 KiB
C

/* 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 */
/**
* @}
* @}
*/