Renaming core -> jerry-core.

This commit is contained in:
Ruben Ayrapetyan
2015-02-17 19:00:34 +03:00
parent b6d018d019
commit 88353e93cf
183 changed files with 14 additions and 14 deletions
+95
View File
@@ -0,0 +1,95 @@
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
*
* 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-gc.h"
#include "ecma-lcache.h"
#include "jrt.h"
#include "mem-poolman.h"
JERRY_STATIC_ASSERT (sizeof (ecma_value_t) <= sizeof (uint16_t));
JERRY_STATIC_ASSERT (sizeof (ecma_property_t) <= sizeof (uint64_t));
JERRY_STATIC_ASSERT (sizeof (ecma_object_t) <= sizeof (uint64_t));
JERRY_STATIC_ASSERT (ECMA_OBJECT_OBJ_TYPE_SIZE <= sizeof (uint64_t) * JERRY_BITSINBYTE);
JERRY_STATIC_ASSERT (ECMA_OBJECT_LEX_ENV_TYPE_SIZE <= sizeof (uint64_t) * JERRY_BITSINBYTE);
JERRY_STATIC_ASSERT (sizeof (ecma_collection_header_t) == sizeof (uint64_t));
JERRY_STATIC_ASSERT (sizeof (ecma_collection_chunk_t) == sizeof (uint64_t));
JERRY_STATIC_ASSERT (sizeof (ecma_string_t) == sizeof (uint64_t));
JERRY_STATIC_ASSERT (sizeof (ecma_completion_value_t) == sizeof (uint32_t));
JERRY_STATIC_ASSERT (sizeof (ecma_label_descriptor_t) == sizeof (uint64_t));
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmaalloc Routines for allocation/freeing memory for ECMA data types
* @{
*/
/**
* Implementation of routines for allocation/freeing memory for ECMA data types.
*
* All allocation routines from this module have the same structure:
* 1. Try to allocate memory.
* 2. If allocation was successful, return pointer to the allocated block.
* 3. Run garbage collection.
* 4. Try to allocate memory.
* 5. If allocation was successful, return pointer to the allocated block;
* else - shutdown engine.
*/
/**
* Template of an allocation routine.
*/
#define ALLOC(ecma_type) ecma_ ## ecma_type ## _t * \
ecma_alloc_ ## ecma_type (void) \
{ \
ecma_ ## ecma_type ## _t *p ## ecma_type = (ecma_ ## ecma_type ## _t *) mem_pools_alloc (); \
\
JERRY_ASSERT (p ## ecma_type != NULL); \
\
return p ## ecma_type; \
}
/**
* Deallocation routine template
*/
#define DEALLOC(ecma_type) void \
ecma_dealloc_ ## ecma_type (ecma_ ## ecma_type ## _t *p ## ecma_type) \
{ \
mem_pools_free ((uint8_t*) p ## ecma_type); \
}
/**
* Declaration of alloc/free routine for specified ecma-type.
*/
#define DECLARE_ROUTINES_FOR(ecma_type) \
ALLOC(ecma_type) \
DEALLOC(ecma_type)
DECLARE_ROUTINES_FOR (object)
DECLARE_ROUTINES_FOR (property)
DECLARE_ROUTINES_FOR (number)
DECLARE_ROUTINES_FOR (collection_header)
DECLARE_ROUTINES_FOR (collection_chunk)
DECLARE_ROUTINES_FOR (string)
DECLARE_ROUTINES_FOR (label_descriptor)
/**
* @}
* @}
*/
+117
View File
@@ -0,0 +1,117 @@
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
*
* 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.
*/
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmaalloc Routines for allocation/freeing memory for ECMA data types
* @{
*/
#ifndef JERRY_ECMA_ALLOC_H
#define JERRY_ECMA_ALLOC_H
#include "ecma-globals.h"
/**
* Allocate memory for ecma-object
*
* @return pointer to allocated memory
*/
extern ecma_object_t *ecma_alloc_object (void);
/**
* Dealloc memory from an ecma-object
*/
extern void ecma_dealloc_object (ecma_object_t *object_p);
/**
* Allocate memory for ecma-property
*
* @return pointer to allocated memory
*/
extern ecma_property_t *ecma_alloc_property (void);
/**
* Dealloc memory from an ecma-property
*/
extern void ecma_dealloc_property (ecma_property_t *property_p);
/**
* Allocate memory for ecma-number
*
* @return pointer to allocated memory
*/
extern ecma_number_t *ecma_alloc_number (void);
/**
* Dealloc memory from an ecma-number
*/
extern void ecma_dealloc_number (ecma_number_t *number_p);
/**
* Allocate memory for header of a collection
*
* @return pointer to allocated memory
*/
extern ecma_collection_header_t *ecma_alloc_collection_header (void);
/**
* Dealloc memory from the collection's header
*/
extern void ecma_dealloc_collection_header (ecma_collection_header_t *collection_header_p);
/**
* Allocate memory for non-first chunk of a collection
*
* @return pointer to allocated memory
*/
extern ecma_collection_chunk_t* ecma_alloc_collection_chunk (void);
/**
* Dealloc memory from non-first chunk of a collection
*/
extern void ecma_dealloc_collection_chunk (ecma_collection_chunk_t *non_first_chunk_p);
/**
* Allocate memory for ecma-string descriptor
*
* @return pointer to allocated memory
*/
extern ecma_string_t *ecma_alloc_string (void);
/**
* Dealloc memory from ecma-string descriptor
*/
extern void ecma_dealloc_string (ecma_string_t *string_p);
/**
* Allocate memory for label descriptor
*
* @return pointer to allocated memory
*/
extern ecma_label_descriptor_t *ecma_alloc_label_descriptor (void);
/**
* Dealloc memory from label descriptor
*/
extern void ecma_dealloc_label_descriptor (ecma_label_descriptor_t *label_desc_p);
#endif /* JERRY_ECMA_ALLOC_H */
/**
* @}
* @}
*/
+730
View File
@@ -0,0 +1,730 @@
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
*
* 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.
*/
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmagc Garbage collector
* @{
*/
/**
* Garbage collector implementation
*/
#include "ecma-alloc.h"
#include "ecma-globals.h"
#include "ecma-gc.h"
#include "ecma-helpers.h"
#include "ecma-lcache.h"
#include "ecma-stack.h"
#include "jrt.h"
#include "jrt-libc-includes.h"
#include "jrt-bit-fields.h"
/**
* Global lists of objects sorted by generation identifier.
*/
static ecma_object_t *ecma_gc_objects_lists[ ECMA_GC_GEN_COUNT ];
static void ecma_gc_mark (ecma_object_t *object_p, ecma_gc_gen_t maximum_gen_to_traverse);
static void ecma_gc_sweep (ecma_object_t *object_p);
/**
* Get GC reference counter of the object.
*/
static uint32_t
ecma_gc_get_object_refs (ecma_object_t *object_p) /**< object */
{
JERRY_ASSERT (object_p != NULL);
return (uint32_t) jrt_extract_bit_field (object_p->container,
ECMA_OBJECT_GC_REFS_POS,
ECMA_OBJECT_GC_REFS_WIDTH);
} /* ecma_gc_get_object_refs */
/**
* Set GC reference counter of the object.
*/
static void
ecma_gc_set_object_refs (ecma_object_t *object_p, /**< object */
uint32_t refs) /**< new reference counter */
{
JERRY_ASSERT (object_p != NULL);
object_p->container = jrt_set_bit_field_value (object_p->container,
refs,
ECMA_OBJECT_GC_REFS_POS,
ECMA_OBJECT_GC_REFS_WIDTH);
} /* ecma_gc_set_object_refs */
/**
* Get GC generation of the object.
*/
static ecma_gc_gen_t
ecma_gc_get_object_generation (ecma_object_t *object_p) /**< object */
{
JERRY_ASSERT (object_p != NULL);
ecma_gc_gen_t ret = (ecma_gc_gen_t) jrt_extract_bit_field (object_p->container,
ECMA_OBJECT_GC_GENERATION_POS,
ECMA_OBJECT_GC_GENERATION_WIDTH);
JERRY_ASSERT (ret < ECMA_GC_GEN_COUNT);
return ret;
} /* ecma_gc_get_object_generation */
/**
* Set GC generation of the object.
*/
static void
ecma_gc_set_object_generation (ecma_object_t *object_p, /**< object */
ecma_gc_gen_t generation) /**< generation */
{
JERRY_ASSERT (object_p != NULL);
JERRY_ASSERT (generation < ECMA_GC_GEN_COUNT);
object_p->container = jrt_set_bit_field_value (object_p->container,
generation,
ECMA_OBJECT_GC_GENERATION_POS,
ECMA_OBJECT_GC_GENERATION_WIDTH);
} /* ecma_gc_set_object_generation */
/**
* Get next object in list of objects with same generation.
*/
static ecma_object_t*
ecma_gc_get_object_next (ecma_object_t *object_p) /**< object */
{
JERRY_ASSERT (object_p != NULL);
JERRY_ASSERT (sizeof (uintptr_t) * JERRY_BITSINBYTE >= ECMA_OBJECT_GC_NEXT_CP_WIDTH);
uintptr_t next_cp = (uintptr_t) jrt_extract_bit_field (object_p->container,
ECMA_OBJECT_GC_NEXT_CP_POS,
ECMA_OBJECT_GC_NEXT_CP_WIDTH);
return ECMA_GET_POINTER (ecma_object_t,
next_cp);
} /* ecma_gc_get_object_next */
/**
* Set next object in list of objects with same generation.
*/
static void
ecma_gc_set_object_next (ecma_object_t *object_p, /**< object */
ecma_object_t *next_object_p) /**< next object */
{
JERRY_ASSERT (object_p != NULL);
uintptr_t next_cp;
ECMA_SET_POINTER (next_cp, next_object_p);
JERRY_ASSERT (sizeof (uintptr_t) * JERRY_BITSINBYTE >= ECMA_OBJECT_GC_NEXT_CP_WIDTH);
object_p->container = jrt_set_bit_field_value (object_p->container,
next_cp,
ECMA_OBJECT_GC_NEXT_CP_POS,
ECMA_OBJECT_GC_NEXT_CP_WIDTH);
} /* ecma_gc_set_object_next */
/**
* Get visited flag of the object.
*/
static bool
ecma_gc_is_object_visited (ecma_object_t *object_p) /**< object */
{
JERRY_ASSERT (object_p != NULL);
return jrt_extract_bit_field (object_p->container,
ECMA_OBJECT_GC_VISITED_POS,
ECMA_OBJECT_GC_VISITED_WIDTH);
} /* ecma_gc_is_object_visited */
/**
* Set visited flag of the object.
*/
static void
ecma_gc_set_object_visited (ecma_object_t *object_p, /**< object */
bool is_visited) /**< flag value */
{
JERRY_ASSERT (object_p != NULL);
object_p->container = jrt_set_bit_field_value (object_p->container,
is_visited,
ECMA_OBJECT_GC_VISITED_POS,
ECMA_OBJECT_GC_VISITED_WIDTH);
} /* ecma_gc_set_object_visited */
/**
* Get may_ref_younger_objects flag of the object.
*/
static bool
ecma_gc_is_object_may_ref_younger_objects (ecma_object_t *object_p) /**< object */
{
JERRY_ASSERT (object_p != NULL);
return jrt_extract_bit_field (object_p->container,
ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_POS,
ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_WIDTH);
} /* ecma_gc_is_object_may_ref_younger_objects */
/**
* Set may_ref_younger_objects flag of the object.
*/
static void
ecma_gc_set_object_may_ref_younger_objects (ecma_object_t *object_p, /**< object */
bool is_may_ref_younger_objects) /**< flag value */
{
JERRY_ASSERT (object_p != NULL);
object_p->container = jrt_set_bit_field_value (object_p->container,
is_may_ref_younger_objects,
ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_POS,
ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_WIDTH);
} /* ecma_gc_set_object_may_ref_younger_objects */
/**
* Initialize GC information for the object
*/
void
ecma_init_gc_info (ecma_object_t *object_p) /**< object */
{
ecma_gc_set_object_refs (object_p, 1);
ecma_gc_set_object_generation (object_p, ECMA_GC_GEN_0);
ecma_gc_set_object_next (object_p, ecma_gc_objects_lists[ ECMA_GC_GEN_0 ]);
ecma_gc_objects_lists[ ECMA_GC_GEN_0 ] = object_p;
/* Should be set to false at the beginning of garbage collection */
ecma_gc_set_object_visited (object_p, true);
ecma_gc_set_object_may_ref_younger_objects (object_p, false);
} /* ecma_init_gc_info */
/**
* Increase reference counter of an object
*/
void
ecma_ref_object (ecma_object_t *object_p) /**< object */
{
ecma_gc_set_object_refs (object_p, ecma_gc_get_object_refs (object_p) + 1);
} /* ecma_ref_object */
/**
* Decrease reference counter of an object
*/
void
ecma_deref_object (ecma_object_t *object_p) /**< object */
{
JERRY_ASSERT(ecma_gc_get_object_refs (object_p) > 0);
ecma_gc_set_object_refs (object_p, ecma_gc_get_object_refs (object_p) - 1);
} /* ecma_deref_object */
/**
* Set may_ref_younger_objects of specified object to true,
* if value is object-value and it's object's generation
* is less than generation of object specified by obj_p.
*/
void
ecma_gc_update_may_ref_younger_object_flag_by_value (ecma_object_t *obj_p, /**< object */
const ecma_value_t& value) /**< value */
{
if (!ecma_is_value_object (value))
{
return;
}
ecma_object_t *ref_obj_p = ecma_get_object_from_value (value);
JERRY_ASSERT(ref_obj_p != NULL);
ecma_gc_update_may_ref_younger_object_flag_by_object (obj_p, ref_obj_p);
} /* ecma_gc_update_may_ref_younger_object_flag_by_value */
void
ecma_gc_update_may_ref_younger_object_flag_by_object (ecma_object_t *obj_p, /**< object */
ecma_object_t *ref_obj_p) /**< referenced object
or NULL */
{
if (ref_obj_p == NULL)
{
return;
}
if (ecma_gc_get_object_generation (ref_obj_p) < ecma_gc_get_object_generation (obj_p))
{
ecma_gc_set_object_may_ref_younger_objects (obj_p, true);
}
} /* ecma_gc_update_may_ref_younger_object_flag_by_object */
/**
* Initialize garbage collector
*/
void
ecma_gc_init (void)
{
memset (ecma_gc_objects_lists, 0, sizeof (ecma_gc_objects_lists));
} /* ecma_gc_init */
/**
* Mark objects as visited starting from specified object as root
* if referenced object's generation is less or equal to maximum_gen_to_traverse.
*/
void
ecma_gc_mark (ecma_object_t *object_p, /**< start object */
ecma_gc_gen_t maximum_gen_to_traverse) /**< start recursive traverse
if referenced object generation
is less or equal to maximum_gen_to_traverse */
{
JERRY_ASSERT(object_p != NULL);
ecma_gc_set_object_visited (object_p, true);
bool does_ref_a_younger_object = false;
bool traverse_properties = true;
if (ecma_is_lexical_environment (object_p))
{
ecma_object_t *lex_env_p = ecma_get_lex_env_outer_reference (object_p);
if (lex_env_p != NULL)
{
if (ecma_gc_get_object_generation (lex_env_p) <= maximum_gen_to_traverse)
{
if (!ecma_gc_is_object_visited (lex_env_p))
{
ecma_gc_mark (lex_env_p, ECMA_GC_GEN_COUNT);
}
}
if (ecma_gc_get_object_generation (lex_env_p) < ecma_gc_get_object_generation (object_p))
{
does_ref_a_younger_object = true;
}
}
if (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND)
{
ecma_object_t *binding_object_p = ecma_get_lex_env_binding_object (object_p);
if (ecma_gc_get_object_generation (binding_object_p) <= maximum_gen_to_traverse)
{
if (!ecma_gc_is_object_visited (binding_object_p))
{
ecma_gc_mark (binding_object_p, ECMA_GC_GEN_COUNT);
}
}
if (ecma_gc_get_object_generation (binding_object_p) < ecma_gc_get_object_generation (object_p))
{
does_ref_a_younger_object = true;
}
traverse_properties = false;
}
}
else
{
ecma_object_t *proto_p = ecma_get_object_prototype (object_p);
if (proto_p != NULL)
{
if (ecma_gc_get_object_generation (proto_p) <= maximum_gen_to_traverse)
{
if (!ecma_gc_is_object_visited (proto_p))
{
ecma_gc_mark (proto_p, ECMA_GC_GEN_COUNT);
}
}
if (ecma_gc_get_object_generation (proto_p) < ecma_gc_get_object_generation (object_p))
{
does_ref_a_younger_object = true;
}
}
}
if (traverse_properties)
{
for (ecma_property_t *property_p = ecma_get_property_list (object_p), *next_property_p;
property_p != NULL;
property_p = next_property_p)
{
next_property_p = ECMA_GET_POINTER (ecma_property_t,
property_p->next_property_p);
switch ((ecma_property_type_t) property_p->type)
{
case ECMA_PROPERTY_NAMEDDATA:
{
ecma_value_t value = ecma_get_named_data_property_value (property_p);
if (ecma_is_value_object (value))
{
ecma_object_t *value_obj_p = ecma_get_object_from_value (value);
if (ecma_gc_get_object_generation (value_obj_p) <= maximum_gen_to_traverse)
{
if (!ecma_gc_is_object_visited (value_obj_p))
{
ecma_gc_mark (value_obj_p, ECMA_GC_GEN_COUNT);
}
}
if (ecma_gc_get_object_generation (value_obj_p) < ecma_gc_get_object_generation (object_p))
{
does_ref_a_younger_object = true;
}
}
break;
}
case ECMA_PROPERTY_NAMEDACCESSOR:
{
ecma_object_t *getter_obj_p = ECMA_GET_POINTER (ecma_object_t,
property_p->u.named_accessor_property.get_p);
ecma_object_t *setter_obj_p = ECMA_GET_POINTER (ecma_object_t,
property_p->u.named_accessor_property.set_p);
if (getter_obj_p != NULL)
{
if (ecma_gc_get_object_generation (getter_obj_p) <= maximum_gen_to_traverse)
{
if (!ecma_gc_is_object_visited (getter_obj_p))
{
ecma_gc_mark (getter_obj_p, ECMA_GC_GEN_COUNT);
}
}
if (ecma_gc_get_object_generation (getter_obj_p) < ecma_gc_get_object_generation (object_p))
{
does_ref_a_younger_object = true;
}
}
if (setter_obj_p != NULL)
{
if (ecma_gc_get_object_generation (setter_obj_p) <= maximum_gen_to_traverse)
{
if (!ecma_gc_is_object_visited (setter_obj_p))
{
ecma_gc_mark (setter_obj_p, ECMA_GC_GEN_COUNT);
}
}
if (ecma_gc_get_object_generation (setter_obj_p) < ecma_gc_get_object_generation (object_p))
{
does_ref_a_younger_object = true;
}
}
break;
}
case ECMA_PROPERTY_INTERNAL:
{
ecma_internal_property_id_t property_id = (ecma_internal_property_id_t) property_p->u.internal_property.type;
uint32_t property_value = property_p->u.internal_property.value;
switch (property_id)
{
case ECMA_INTERNAL_PROPERTY_NUMBER_INDEXED_ARRAY_VALUES: /* a collection of ecma-values */
case ECMA_INTERNAL_PROPERTY_STRING_INDEXED_ARRAY_VALUES: /* a collection of ecma-values */
{
JERRY_UNIMPLEMENTED("Indexed array storage is not implemented yet.");
}
case ECMA_INTERNAL_PROPERTY_PROTOTYPE: /* the property's value is located in ecma_object_t
(see above in the routine) */
case ECMA_INTERNAL_PROPERTY_EXTENSIBLE: /* the property's value is located in ecma_object_t
(see above in the routine) */
case ECMA_INTERNAL_PROPERTY__COUNT: /* not a real internal property type,
* but number of the real internal property types */
{
JERRY_UNREACHABLE();
}
case ECMA_INTERNAL_PROPERTY_FORMAL_PARAMETERS: /* a collection of strings */
case ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE: /* compressed pointer to a ecma_string_t */
case ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE: /* compressed pointer to a ecma_number_t */
case ECMA_INTERNAL_PROPERTY_PRIMITIVE_BOOLEAN_VALUE: /* a simple boolean value */
case ECMA_INTERNAL_PROPERTY_CLASS: /* an enum */
case ECMA_INTERNAL_PROPERTY_CODE: /* an integer */
case ECMA_INTERNAL_PROPERTY_BUILT_IN_ID: /* an integer */
case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_ID: /* an integer */
case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_0_31: /* an integer (bit-mask) */
case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_32_63: /* an integer (bit-mask) */
{
break;
}
case ECMA_INTERNAL_PROPERTY_SCOPE: /* a lexical environment */
case ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP: /* an object */
{
ecma_object_t *obj_p = ECMA_GET_NON_NULL_POINTER(ecma_object_t, property_value);
if (ecma_gc_get_object_generation (obj_p) <= maximum_gen_to_traverse)
{
if (!ecma_gc_is_object_visited (obj_p))
{
ecma_gc_mark (obj_p, ECMA_GC_GEN_COUNT);
}
}
if (ecma_gc_get_object_generation (obj_p) < ecma_gc_get_object_generation (object_p))
{
does_ref_a_younger_object = true;
}
break;
}
}
break;
}
}
}
}
if (!does_ref_a_younger_object)
{
ecma_gc_set_object_may_ref_younger_objects (object_p, false);
}
} /* ecma_gc_mark */
/**
* Free specified object
*/
void
ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
{
JERRY_ASSERT(object_p != NULL
&& !ecma_gc_is_object_visited (object_p)
&& ecma_gc_get_object_refs (object_p) == 0);
if (!ecma_is_lexical_environment (object_p) ||
ecma_get_lex_env_type (object_p) != ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND)
{
for (ecma_property_t *property = ecma_get_property_list (object_p), *next_property_p;
property != NULL;
property = next_property_p)
{
next_property_p = ECMA_GET_POINTER (ecma_property_t,
property->next_property_p);
ecma_free_property (object_p, property);
}
}
ecma_dealloc_object (object_p);
} /* ecma_gc_sweep */
/**
* Run garbage collecting
*/
void
ecma_gc_run (ecma_gc_gen_t max_gen_to_collect) /**< maximum generation to run collection on */
{
JERRY_ASSERT(max_gen_to_collect < ECMA_GC_GEN_COUNT);
/* clearing visited flags for all objects of generations to be processed */
for (ecma_gc_gen_t gen_id = ECMA_GC_GEN_0; gen_id <= max_gen_to_collect; gen_id = (ecma_gc_gen_t) (gen_id + 1))
{
for (ecma_object_t *obj_iter_p = ecma_gc_objects_lists[ gen_id ];
obj_iter_p != NULL;
obj_iter_p = ecma_gc_get_object_next (obj_iter_p))
{
ecma_gc_set_object_visited (obj_iter_p, false);
}
}
/* if some object is referenced from stack or globals (i.e. it is root),
* start recursive marking traverse from the object */
for (ecma_gc_gen_t gen_id = ECMA_GC_GEN_0; gen_id <= max_gen_to_collect; gen_id = (ecma_gc_gen_t) (gen_id + 1))
{
for (ecma_object_t *obj_iter_p = ecma_gc_objects_lists[ gen_id ];
obj_iter_p != NULL;
obj_iter_p = ecma_gc_get_object_next (obj_iter_p))
{
if (ecma_gc_get_object_refs (obj_iter_p) > 0
&& !ecma_gc_is_object_visited (obj_iter_p))
{
ecma_gc_mark (obj_iter_p, ECMA_GC_GEN_COUNT);
}
}
}
/* if some object is referenced from a register variable (i.e. it is root),
* start recursive marking traverse from the object */
for (ecma_stack_frame_t *frame_iter_p = ecma_stack_get_top_frame ();
frame_iter_p != NULL;
frame_iter_p = frame_iter_p->prev_frame_p)
{
for (int32_t reg_index = 0; reg_index < frame_iter_p->regs_number; reg_index++)
{
ecma_value_t reg_value = ecma_stack_frame_get_reg_value (frame_iter_p, reg_index);
if (ecma_is_value_object (reg_value))
{
ecma_object_t *obj_p = ecma_get_object_from_value (reg_value);
if (!ecma_gc_is_object_visited (obj_p))
{
ecma_gc_mark (obj_p, ECMA_GC_GEN_COUNT);
}
}
}
}
/* if some object from generations that are not processed during current session may reference
* younger generations, start recursive marking traverse from the object, but one the first level
* consider only references to object of at most max_gen_to_collect generation */
for (ecma_gc_gen_t gen_id = (ecma_gc_gen_t) (max_gen_to_collect + 1);
gen_id < ECMA_GC_GEN_COUNT;
gen_id = (ecma_gc_gen_t) (gen_id + 1))
{
for (ecma_object_t *obj_iter_p = ecma_gc_objects_lists[ gen_id ];
obj_iter_p != NULL;
obj_iter_p = ecma_gc_get_object_next (obj_iter_p))
{
if (ecma_gc_is_object_may_ref_younger_objects (obj_iter_p))
{
ecma_gc_mark (obj_iter_p, max_gen_to_collect);
}
#ifndef JERRY_NDEBUG
else if (gen_id > ECMA_GC_GEN_0)
{
ecma_gc_set_object_may_ref_younger_objects (obj_iter_p, true);
ecma_gc_mark (obj_iter_p, (ecma_gc_gen_t) (gen_id - 1));
JERRY_ASSERT (!ecma_gc_is_object_may_ref_younger_objects (obj_iter_p));
}
#endif /* !JERRY_NDEBUG */
}
}
JERRY_ASSERT (max_gen_to_collect <= ECMA_GC_GEN_COUNT);
ecma_object_t *gen_last_obj_p[ ECMA_GC_GEN_COUNT ];
#ifndef JERRY_NDEBUG
memset (gen_last_obj_p, 0, sizeof (gen_last_obj_p));
#endif /* !JERRY_NDEBUG */
for (ecma_gc_gen_t gen_id = ECMA_GC_GEN_0; gen_id <= max_gen_to_collect; gen_id = (ecma_gc_gen_t) (gen_id + 1))
{
ecma_object_t *obj_prev_p = NULL;
for (ecma_object_t *obj_iter_p = ecma_gc_objects_lists[ gen_id ],
*obj_next_p;
obj_iter_p != NULL;
obj_iter_p = obj_next_p)
{
obj_next_p = ecma_gc_get_object_next (obj_iter_p);
if (!ecma_gc_is_object_visited (obj_iter_p))
{
ecma_gc_sweep (obj_iter_p);
if (likely (obj_prev_p != NULL))
{
ecma_gc_set_object_next (obj_prev_p, obj_next_p);
}
else
{
ecma_gc_objects_lists[ gen_id ] = obj_next_p;
}
}
else
{
obj_prev_p = obj_iter_p;
if (ecma_gc_get_object_generation (obj_iter_p) != ECMA_GC_GEN_COUNT - 1)
{
/* the object will be promoted to next generation */
ecma_gc_set_object_generation (obj_iter_p, (ecma_gc_gen_t) (ecma_gc_get_object_generation (obj_iter_p) + 1));
}
}
}
gen_last_obj_p[ gen_id ] = obj_prev_p;
}
ecma_gc_gen_t gen_to_promote = max_gen_to_collect;
if (unlikely (gen_to_promote == ECMA_GC_GEN_COUNT - 1))
{
/* not promoting last generation */
gen_to_promote = (ecma_gc_gen_t) (gen_to_promote - 1);
}
/* promoting to next generation */
if (gen_last_obj_p[ gen_to_promote ] != NULL)
{
ecma_gc_set_object_next (gen_last_obj_p [gen_to_promote], ecma_gc_objects_lists[ gen_to_promote + 1 ]);
ecma_gc_objects_lists[ gen_to_promote + 1 ] = ecma_gc_objects_lists[ gen_to_promote ];
ecma_gc_objects_lists[ gen_to_promote ] = NULL;
}
for (int32_t gen_id = (int32_t)gen_to_promote - 1;
gen_id >= 0;
gen_id--)
{
ecma_gc_objects_lists[ gen_id + 1 ] = ecma_gc_objects_lists[ gen_id ];
ecma_gc_objects_lists[ gen_id ] = NULL;
}
#ifndef JERRY_NDEBUG
for (ecma_gc_gen_t gen_id = ECMA_GC_GEN_0;
gen_id < ECMA_GC_GEN_COUNT;
gen_id = (ecma_gc_gen_t) (gen_id + 1))
{
for (ecma_object_t *obj_iter_p = ecma_gc_objects_lists[ gen_id ];
obj_iter_p != NULL;
obj_iter_p = ecma_gc_get_object_next (obj_iter_p))
{
JERRY_ASSERT(ecma_gc_get_object_generation (obj_iter_p) == gen_id);
}
}
#endif /* !JERRY_NDEBUG */
} /* ecma_gc_run */
/**
* Try to free some memory (depending on severity).
*/
void
ecma_try_to_give_back_some_memory (mem_try_give_memory_back_severity_t severity) /**< severity of
* the request */
{
if (severity == MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_LOW)
{
ecma_gc_run (ECMA_GC_GEN_0);
}
else if (severity == MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_MEDIUM)
{
ecma_gc_run (ECMA_GC_GEN_1);
}
else if (severity == MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_HIGH)
{
ecma_gc_run (ECMA_GC_GEN_2);
}
else
{
JERRY_ASSERT (severity == MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_CRITICAL);
/* Freeing as much memory as we currently can */
ecma_lcache_invalidate_all ();
ecma_gc_run ((ecma_gc_gen_t) (ECMA_GC_GEN_COUNT - 1));
}
} /* ecma_try_to_give_back_some_memory */
/**
* @}
* @}
*/
+54
View File
@@ -0,0 +1,54 @@
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
*
* 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.
*/
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmagc Garbage collector
* @{
*/
#ifndef ECMA_GC_H
#define ECMA_GC_H
#include "ecma-globals.h"
#include "mem-allocator.h"
/**
* GC generation identifier
*/
typedef enum
{
ECMA_GC_GEN_0, /**< generation 0 */
ECMA_GC_GEN_1, /**< generation 1 */
ECMA_GC_GEN_2, /**< generation 2 */
ECMA_GC_GEN_COUNT /**< generations' number */
} ecma_gc_gen_t;
extern void ecma_gc_init (void);
extern void ecma_init_gc_info (ecma_object_t *object_p);
extern void ecma_ref_object (ecma_object_t *object_p);
extern void ecma_deref_object (ecma_object_t *object_p);
extern void ecma_gc_update_may_ref_younger_object_flag_by_value (ecma_object_t *obj_p, const ecma_value_t& value);
extern void ecma_gc_update_may_ref_younger_object_flag_by_object (ecma_object_t *obj_p, ecma_object_t *ref_obj_p);
extern void ecma_gc_run (ecma_gc_gen_t max_gen_to_collect);
extern void ecma_try_to_give_back_some_memory (mem_try_give_memory_back_severity_t severity);
#endif /* !ECMA_GC_H */
/**
* @}
* @}
*/
+823
View File
@@ -0,0 +1,823 @@
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
*
* 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.
*/
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmatypes ECMA types
* @{
*/
#ifndef JERRY_ECMA_GLOBALS_H
#define JERRY_ECMA_GLOBALS_H
#include "config.h"
#include "jrt.h"
#include "mem-allocator.h"
/** \addtogroup compressedpointer Compressed pointer
* @{
*/
/**
* Ecma-pointer field is used to calculate ecma-value's address.
*
* Ecma-pointer contains value's shifted offset from common Ecma-pointers' base.
* The offset is shifted right by MEM_ALIGNMENT_LOG.
* Least significant MEM_ALIGNMENT_LOG bits of non-shifted offset are zeroes.
*/
#define ECMA_POINTER_FIELD_WIDTH MEM_COMPRESSED_POINTER_WIDTH
/**
* The NULL value for compressed pointers
*/
#define ECMA_NULL_POINTER MEM_COMPRESSED_POINTER_NULL
/**
* @}
*/
/**
* Type of ecma-value
*/
typedef enum
{
ECMA_TYPE_SIMPLE, /**< simple value */
ECMA_TYPE_NUMBER, /**< 64-bit integer */
ECMA_TYPE_STRING, /**< pointer to description of a string */
ECMA_TYPE_OBJECT /**< pointer to description of an object */
} ecma_type_t;
/**
* Simple ecma-values
*/
typedef enum
{
/**
* Empty value is implementation defined value, used for:
* - representing empty value in completion values (see also: ECMA-262 v5, 8.9 Completion specification type);
* - values of uninitialized immutable bindings;
* - values of empty register variables.
*/
ECMA_SIMPLE_VALUE_EMPTY,
ECMA_SIMPLE_VALUE_UNDEFINED, /**< undefined value */
ECMA_SIMPLE_VALUE_NULL, /**< null value */
ECMA_SIMPLE_VALUE_FALSE, /**< boolean false */
ECMA_SIMPLE_VALUE_TRUE, /**< boolean true */
ECMA_SIMPLE_VALUE_ARRAY_REDIRECT, /**< implementation defined value for an array's elements that exist,
but are stored directly in the array's property list
(used for array elements with non-default attribute values) */
ECMA_SIMPLE_VALUE__COUNT /** count of simple ecma-values */
} ecma_simple_value_t;
/**
* Type of ecma-property
*/
typedef enum
{
ECMA_PROPERTY_NAMEDDATA, /**< named data property */
ECMA_PROPERTY_NAMEDACCESSOR, /**< named accessor property */
ECMA_PROPERTY_INTERNAL /**< internal property */
} ecma_property_type_t;
/**
* Type of block evaluation (completion) result.
*
* See also: ECMA-262 v5, 8.9.
*/
typedef enum
{
ECMA_COMPLETION_TYPE_NORMAL, /**< default block completion */
ECMA_COMPLETION_TYPE_RETURN, /**< block completed with return */
ECMA_COMPLETION_TYPE_BREAK, /**< block completed with break */
ECMA_COMPLETION_TYPE_CONTINUE, /**< block completed with continue */
ECMA_COMPLETION_TYPE_THROW, /**< block completed with throw */
ECMA_COMPLETION_TYPE_EXIT, /**< implementation-defined completion type
for finishing script execution */
ECMA_COMPLETION_TYPE_META /**< implementation-defined completion type
for meta opcode */
} ecma_completion_type_t;
/**
* Description of an ecma-value
*
* Bit-field structure: type (2) | value (ECMA_POINTER_FIELD_WIDTH)
*/
typedef uint16_t ecma_value_t;
/**
* Value type (ecma_type_t)
*/
#define ECMA_VALUE_TYPE_POS (0)
#define ECMA_VALUE_TYPE_WIDTH (2)
/**
* Simple value (ecma_simple_value_t) or compressed pointer to value (depending on value_type)
*/
#define ECMA_VALUE_VALUE_POS (ECMA_VALUE_TYPE_POS + \
ECMA_VALUE_TYPE_WIDTH)
#define ECMA_VALUE_VALUE_WIDTH (ECMA_POINTER_FIELD_WIDTH)
/**
* ecma_value_t size
*/
#define ECMA_VALUE_SIZE (ECMA_VALUE_VALUE_POS + ECMA_VALUE_VALUE_WIDTH)
/**
* Description of a block completion value
*
* See also: ECMA-262 v5, 8.9.
*
* value (16)
* Bit-field structure: type (8) | padding (8) <
* label_desc_cp (16)
*/
typedef uint32_t ecma_completion_value_t;
/**
* Type (ecma_completion_type_t)
*/
#define ECMA_COMPLETION_VALUE_TYPE_POS (0)
#define ECMA_COMPLETION_VALUE_TYPE_WIDTH (8)
/**
* Padding (1 byte)
*/
#define ECMA_COMPLETION_VALUE_PADDING_WIDTH (8)
/**
* Value
*
* Used for normal, return, throw and exit completion types.
*/
#define ECMA_COMPLETION_VALUE_VALUE_POS (ECMA_COMPLETION_VALUE_TYPE_POS + \
ECMA_COMPLETION_VALUE_TYPE_WIDTH + \
ECMA_COMPLETION_VALUE_PADDING_WIDTH)
#define ECMA_COMPLETION_VALUE_VALUE_WIDTH (ECMA_VALUE_SIZE)
/**
* Label
*
* Used for break and continue completion types.
*/
#define ECMA_COMPLETION_VALUE_LABEL_DESC_CP_POS (ECMA_COMPLETION_VALUE_TYPE_POS + \
ECMA_COMPLETION_VALUE_TYPE_WIDTH + \
ECMA_COMPLETION_VALUE_PADDING_WIDTH)
#define ECMA_COMPLETION_VALUE_LABEL_DESC_CP_WIDTH (ECMA_POINTER_FIELD_WIDTH)
/**
* Label
*
* Used for break and continue completion types.
*/
typedef struct
{
/** Target's offset */
uint32_t offset;
/** Levels to label left */
uint32_t depth;
} ecma_label_descriptor_t;
/**
* Internal properties' identifiers.
*/
typedef enum
{
ECMA_INTERNAL_PROPERTY_CLASS, /**< [[Class]] */
ECMA_INTERNAL_PROPERTY_PROTOTYPE, /**< [[Prototype]] */
ECMA_INTERNAL_PROPERTY_EXTENSIBLE, /**< [[Extensible]] */
ECMA_INTERNAL_PROPERTY_SCOPE, /**< [[Scope]] */
ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP, /**< [[ParametersMap]] */
ECMA_INTERNAL_PROPERTY_CODE, /**< [[Code]] */
ECMA_INTERNAL_PROPERTY_FORMAL_PARAMETERS, /**< [[FormalParameters]] */
ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE, /**< [[Primitive value]] for String objects */
ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE, /**< [[Primitive value]] for Number objects */
ECMA_INTERNAL_PROPERTY_PRIMITIVE_BOOLEAN_VALUE, /**< [[Primitive value]] for Boolean objects */
/** Part of an array, that is indexed by numbers */
ECMA_INTERNAL_PROPERTY_NUMBER_INDEXED_ARRAY_VALUES,
/** Part of an array, that is indexed by strings */
ECMA_INTERNAL_PROPERTY_STRING_INDEXED_ARRAY_VALUES,
/** Implementation-defined identifier of built-in object */
ECMA_INTERNAL_PROPERTY_BUILT_IN_ID,
/** Implementation-defined identifier of built-in routine
that corresponds to a built-in function object
([[Built-in routine ID]]) */
ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_ID,
/**
* Bit-mask of non-instantiated built-in's properties (bits 0-31)
*/
ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_0_31,
/**
* Bit-mask of non-instantiated built-in's properties (bits 32-63)
*/
ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_32_63,
/**
* Number of internal properties' types
*/
ECMA_INTERNAL_PROPERTY__COUNT
} ecma_internal_property_id_t;
/**
* Property's 'Writable' attribute's values description.
*/
typedef enum
{
ECMA_PROPERTY_NOT_WRITABLE, /**< property's 'Writable' attribute is false */
ECMA_PROPERTY_WRITABLE /**< property's 'Writable' attribute is true */
} ecma_property_writable_value_t;
/**
* Property's 'Enumerable' attribute's values description.
*/
typedef enum
{
ECMA_PROPERTY_NOT_ENUMERABLE, /**< property's 'Enumerable' attribute is false */
ECMA_PROPERTY_ENUMERABLE /**< property's 'Enumerable' attribute is true */
} ecma_property_enumerable_value_t;
/**
* Property's 'Configurable' attribute's values description.
*/
typedef enum
{
ECMA_PROPERTY_NOT_CONFIGURABLE, /**< property's 'Configurable' attribute is false */
ECMA_PROPERTY_CONFIGURABLE /**< property's 'Configurable' attribute is true */
} ecma_property_configurable_value_t;
/**
* Width of internal property type field's width
*/
#define ECMA_PROPERTY_INTERNAL_PROPERTY_TYPE_WIDTH (5)
/**
* Description of ecma-property
*/
typedef struct ecma_property_t
{
/** Property's type (ecma_property_type_t) */
unsigned int type : 2;
/** Compressed pointer to next property */
unsigned int next_property_p : ECMA_POINTER_FIELD_WIDTH;
/** Property's details (depending on Type) */
union
{
/** Description of named data property */
struct __attr_packed___ ecma_named_data_property_t
{
/** Compressed pointer to property's name (pointer to String) */
unsigned int name_p : ECMA_POINTER_FIELD_WIDTH;
/** Attribute 'Writable' (ecma_property_writable_value_t) */
unsigned int writable : 1;
/** Attribute 'Enumerable' (ecma_property_enumerable_value_t) */
unsigned int enumerable : 1;
/** Attribute 'Configurable' (ecma_property_configurable_value_t) */
unsigned int configurable : 1;
/** Flag indicating whether the property is registered in LCache */
unsigned int is_lcached : 1;
/** Value */
ecma_value_t value;
} named_data_property;
/** Description of named accessor property */
struct __attr_packed___ ecma_named_accessor_property_t
{
/** Compressed pointer to property's name (pointer to String) */
unsigned int name_p : ECMA_POINTER_FIELD_WIDTH;
/** Attribute 'Enumerable' (ecma_property_enumerable_value_t) */
unsigned int enumerable : 1;
/** Attribute 'Configurable' (ecma_property_configurable_value_t) */
unsigned int configurable : 1;
/** Flag indicating whether the property is registered in LCache */
unsigned int is_lcached : 1;
/** Compressed pointer to property's getter */
unsigned int get_p : ECMA_POINTER_FIELD_WIDTH;
/** Compressed pointer to property's setter */
unsigned int set_p : ECMA_POINTER_FIELD_WIDTH;
} named_accessor_property;
/** Description of internal property */
struct __attr_packed___ ecma_internal_property_t
{
/** Internal property's type */
unsigned int type : ECMA_PROPERTY_INTERNAL_PROPERTY_TYPE_WIDTH;
/** Value (may be a compressed pointer) */
uint32_t value;
} internal_property;
} u;
} ecma_property_t;
/**
* Types of lexical environments
*/
typedef enum
{
ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE, /**< declarative lexical environment */
ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND /**< object-bound lexical environment */
} ecma_lexical_environment_type_t;
/**
* Internal object types
*
* Warning:
* definition order is significant (see also dispatch tables in libecmaobjects/ecma-objects.c)
*/
typedef enum
{
ECMA_OBJECT_TYPE_GENERAL, /**< all objects that are not String (15.5), Function (15.3),
Arguments (10.6), Array (15.4) specification-defined objects
and not host objects */
ECMA_OBJECT_TYPE_STRING, /**< String objects (15.5) */
ECMA_OBJECT_TYPE_FUNCTION, /**< Function objects (15.3), created through 13.2 routine */
ECMA_OBJECT_TYPE_BOUND_FUNCTION, /**< Function objects (15.3), created through 15.3.4.5 routine */
ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, /** One of built-in functions described in section 15
of ECMA-262 v5 specification */
ECMA_OBJECT_TYPE_ARGUMENTS, /**< Arguments object (10.6) */
ECMA_OBJECT_TYPE_ARRAY, /**< Array object (15.4) */
// ECMA_OBJECT_TYPE_HOST, /**< Host object */
ECMA_OBJECT_TYPE__COUNT /**< number of object types */
} ecma_object_type_t;
/**
* Description of ECMA-object or lexical environment
* (depending on is_lexical_environment).
*/
typedef struct
{
/* Common part for objects and lexical environments */
/**
* Compressed pointer to property list
*/
#define ECMA_OBJECT_PROPERTIES_OR_BOUND_OBJECT_CP_POS (0)
#define ECMA_OBJECT_PROPERTIES_OR_BOUND_OBJECT_CP_WIDTH (ECMA_POINTER_FIELD_WIDTH)
/**
* Flag indicating whether it is a general object (false)
* or a lexical environment (true)
*/
#define ECMA_OBJECT_IS_LEXICAL_ENVIRONMENT_POS (ECMA_OBJECT_PROPERTIES_OR_BOUND_OBJECT_CP_POS + \
ECMA_OBJECT_PROPERTIES_OR_BOUND_OBJECT_CP_WIDTH)
#define ECMA_OBJECT_IS_LEXICAL_ENVIRONMENT_WIDTH (1)
/**
* Reference counter of the object, i.e. number of references
* to the object from stack variables.
*/
#define ECMA_OBJECT_GC_REFS_POS (ECMA_OBJECT_IS_LEXICAL_ENVIRONMENT_POS + \
ECMA_OBJECT_IS_LEXICAL_ENVIRONMENT_WIDTH)
#define ECMA_OBJECT_GC_REFS_WIDTH (CONFIG_ECMA_REFERENCE_COUNTER_WIDTH)
/**
* Identifier of GC generation.
*/
#define ECMA_OBJECT_GC_GENERATION_POS (ECMA_OBJECT_GC_REFS_POS + \
ECMA_OBJECT_GC_REFS_WIDTH)
#define ECMA_OBJECT_GC_GENERATION_WIDTH (2)
/**
* Compressed pointer to next object in the global list of objects with same generation.
*/
#define ECMA_OBJECT_GC_NEXT_CP_POS (ECMA_OBJECT_GC_GENERATION_POS + \
ECMA_OBJECT_GC_GENERATION_WIDTH)
#define ECMA_OBJECT_GC_NEXT_CP_WIDTH (ECMA_POINTER_FIELD_WIDTH)
/**
* Marker that is set if the object was visited during graph traverse.
*/
#define ECMA_OBJECT_GC_VISITED_POS (ECMA_OBJECT_GC_NEXT_CP_POS + \
ECMA_OBJECT_GC_NEXT_CP_WIDTH)
#define ECMA_OBJECT_GC_VISITED_WIDTH (1)
/**
* Flag indicating that the object may reference objects of younger generations in its properties.
*/
#define ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_POS (ECMA_OBJECT_GC_VISITED_POS + \
ECMA_OBJECT_GC_VISITED_WIDTH)
#define ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_WIDTH (1)
/* Objects' only part */
/**
* Attribute 'Extensible'
*/
#define ECMA_OBJECT_OBJ_EXTENSIBLE_POS (ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_POS + \
ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_WIDTH)
#define ECMA_OBJECT_OBJ_EXTENSIBLE_WIDTH (1)
/**
* Implementation internal object type (ecma_object_type_t)
*/
#define ECMA_OBJECT_OBJ_TYPE_POS (ECMA_OBJECT_OBJ_EXTENSIBLE_POS + \
ECMA_OBJECT_OBJ_EXTENSIBLE_WIDTH)
#define ECMA_OBJECT_OBJ_TYPE_WIDTH (3)
/**
* Compressed pointer to prototype object (ecma_object_t)
*/
#define ECMA_OBJECT_OBJ_PROTOTYPE_OBJECT_CP_POS (ECMA_OBJECT_OBJ_TYPE_POS + \
ECMA_OBJECT_OBJ_TYPE_WIDTH)
#define ECMA_OBJECT_OBJ_PROTOTYPE_OBJECT_CP_WIDTH (ECMA_POINTER_FIELD_WIDTH)
/**
* Flag indicating whether the object is a built-in object
*/
#define ECMA_OBJECT_OBJ_IS_BUILTIN_POS (ECMA_OBJECT_OBJ_PROTOTYPE_OBJECT_CP_POS + \
ECMA_OBJECT_OBJ_PROTOTYPE_OBJECT_CP_WIDTH)
#define ECMA_OBJECT_OBJ_IS_BUILTIN_WIDTH (1)
/**
* Size of structure for objects
*/
#define ECMA_OBJECT_OBJ_TYPE_SIZE (ECMA_OBJECT_OBJ_IS_BUILTIN_POS + \
ECMA_OBJECT_OBJ_IS_BUILTIN_WIDTH)
/* Lexical environments' only part */
/**
* Type of lexical environment (ecma_lexical_environment_type_t).
*/
#define ECMA_OBJECT_LEX_ENV_TYPE_POS (ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_POS + \
ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_WIDTH)
#define ECMA_OBJECT_LEX_ENV_TYPE_WIDTH (1)
/**
* Compressed pointer to outer lexical environment
*/
#define ECMA_OBJECT_LEX_ENV_OUTER_REFERENCE_CP_POS (ECMA_OBJECT_LEX_ENV_TYPE_POS + \
ECMA_OBJECT_LEX_ENV_TYPE_WIDTH)
#define ECMA_OBJECT_LEX_ENV_OUTER_REFERENCE_CP_WIDTH (ECMA_POINTER_FIELD_WIDTH)
/**
* 'provideThis' property of object-bound lexical environments
*/
#define ECMA_OBJECT_LEX_ENV_PROVIDE_THIS_POS (ECMA_OBJECT_LEX_ENV_OUTER_REFERENCE_CP_POS + \
ECMA_OBJECT_LEX_ENV_OUTER_REFERENCE_CP_WIDTH)
#define ECMA_OBJECT_LEX_ENV_PROVIDE_THIS_WIDTH (1)
/**
* Size of structure for lexical environments
*/
#define ECMA_OBJECT_LEX_ENV_TYPE_SIZE (ECMA_OBJECT_LEX_ENV_PROVIDE_THIS_POS + \
ECMA_OBJECT_LEX_ENV_PROVIDE_THIS_WIDTH)
uint64_t container; /**< container for fields described above */
} ecma_object_t;
/**
* Description of ECMA property descriptor
*
* See also: ECMA-262 v5, 8.10.
*
* Note:
* If a component of descriptor is undefined then corresponding
* field should contain it's default value.
*/
typedef struct
{
/** Is [[Value]] defined? */
unsigned int is_value_defined : 1;
/** Is [[Get]] defined? */
unsigned int is_get_defined : 1;
/** Is [[Set]] defined? */
unsigned int is_set_defined : 1;
/** Is [[Writable]] defined? */
unsigned int is_writable_defined : 1;
/** Is [[Enumerable]] defined? */
unsigned int is_enumerable_defined : 1;
/** Is [[Configurable]] defined? */
unsigned int is_configurable_defined : 1;
/** [[Value]] */
ecma_value_t value;
/** [[Get]] */
ecma_object_t* get_p;
/** [[Set]] */
ecma_object_t* set_p;
/** [[Writable]] */
bool is_writable;
/** [[Enumerable]] */
bool is_enumerable;
/** [[Configurable]] */
bool is_configurable;
} ecma_property_descriptor_t;
#if CONFIG_ECMA_CHAR_ENCODING == CONFIG_ECMA_CHAR_ASCII
/**
* Description of an ecma-character
*/
typedef uint8_t ecma_char_t;
#elif CONFIG_ECMA_CHAR_ENCODING == CONFIG_ECMA_CHAR_UTF16
/**
* Description of an ecma-character
*/
typedef uint16_t ecma_char_t;
#endif /* CONFIG_ECMA_CHAR_ENCODING == CONFIG_ECMA_CHAR_UTF16 */
#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32
/**
* Description of an ecma-number
*/
typedef float ecma_number_t;
/**
* Maximum number of significant digits that ecma-number can store
*/
#define ECMA_NUMBER_MAX_DIGITS (9)
#elif CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64
/**
* Description of an ecma-number
*/
typedef double ecma_number_t;
/**
* Maximum number of significant digits that ecma-number can store
*/
#define ECMA_NUMBER_MAX_DIGITS (18)
#endif /* CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64 */
/**
* Value '0' of ecma_number_t
*/
#define ECMA_NUMBER_ZERO ((ecma_number_t) 0)
/**
* Value '1' of ecma_number_t
*/
#define ECMA_NUMBER_ONE ((ecma_number_t) 1)
/**
* Value '2' of ecma_number_t
*/
#define ECMA_NUMBER_TWO ((ecma_number_t) 2)
/**
* Value '0.5' of ecma_number_t
*/
#define ECMA_NUMBER_HALF ((ecma_number_t) 0.5f)
/**
* Minimum positive and maximum value of ecma-number
*/
#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32
# define ECMA_NUMBER_MIN_VALUE (FLT_MIN)
# define ECMA_NUMBER_MAX_VALUE (FLT_MAX)
#elif CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64
/**
* Number.MAX_VALUE
*
* See also: ECMA_262 v5, 15.7.3.2
*/
# define ECMA_NUMBER_MAX_VALUE ((ecma_number_t)1.7976931348623157e+308)
/**
* Number.MIN_VALUE
*
* See also: ECMA_262 v5, 15.7.3.3
*/
# define ECMA_NUMBER_MIN_VALUE ((ecma_number_t)5e-324)
#endif /* CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64 */
/**
* Euler number
*/
#define ECMA_NUMBER_E ((ecma_number_t)2.7182818284590452354)
/**
* Natural logarithm of 10
*/
#define ECMA_NUMBER_LN10 ((ecma_number_t)2.302585092994046)
/**
* Natural logarithm of 2
*/
#define ECMA_NUMBER_LN2 ((ecma_number_t)0.6931471805599453)
/**
* Logarithm base 2 of the Euler number
*/
#define ECMA_NUMBER_LOG2E ((ecma_number_t)1.4426950408889634)
/**
* Logarithm base 10 of the Euler number
*/
#define ECMA_NUMBER_LOG10E ((ecma_number_t)0.4342944819032518)
/**
* Pi number
*/
#define ECMA_NUMBER_PI ((ecma_number_t)3.1415926535897932)
/**
* Square root of 0.5
*/
#define ECMA_NUMBER_SQRT_1_2 ((ecma_number_t)0.7071067811865476)
/**
* Square root of 2
*/
#define ECMA_NUMBER_SQRT2 ((ecma_number_t)1.4142135623730951)
/**
* Null character (zt-string end marker)
*/
#define ECMA_CHAR_NULL ((ecma_char_t) '\0')
/**
* Maximum number of characters in string representation of ecma-number
*/
#define ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER 64
/**
* Maximum number of characters in string representation of ecma-uint32
*/
#define ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32 32
/**
* Maximum value of valid array index
*
* See also:
* ECMA-262 v5, 15.4
*/
#define ECMA_MAX_VALUE_OF_VALID_ARRAY_INDEX ((uint32_t) (-1))
/**
* Description of a collection's/string's length
*/
typedef uint16_t ecma_length_t;
/**
* Description of a collection's header.
*/
typedef struct
{
/** Compressed pointer to next chunk with collection's data */
uint16_t next_chunk_cp;
/** Number of elements in the collection */
ecma_length_t unit_number;
/** Place for the collection's data */
uint8_t data[ sizeof (uint64_t) - sizeof (uint32_t) ];
} ecma_collection_header_t;
/**
* Description of non-first chunk in a collection's chain of chunks
*/
typedef struct
{
/** Compressed pointer to next chunk */
uint16_t next_chunk_cp;
/** Characters */
uint8_t data[ sizeof (uint64_t) - sizeof (uint16_t) ];
} ecma_collection_chunk_t;
/**
* Identifier for ecma-string's actual data container
*/
typedef enum
{
ECMA_STRING_CONTAINER_LIT_TABLE, /**< actual data is in literal table */
ECMA_STRING_CONTAINER_HEAP_CHUNKS, /**< actual data is on the heap
in a ecma_collection_chunk_t chain */
ECMA_STRING_CONTAINER_HEAP_NUMBER, /**< actual data is on the heap as a ecma_number_t */
ECMA_STRING_CONTAINER_UINT32_IN_DESC, /**< actual data is UInt32-represeneted Number
stored locally in the string's descriptor */
ECMA_STRING_CONTAINER_CONCATENATION, /**< the ecma-string is concatenation of two specified ecma-strings */
ECMA_STRING_CONTAINER_MAGIC_STRING /**< the ecma-string is equal to one of ECMA magic strings */
} ecma_string_container_t;
FIXME (Move to library that should define the type (literal.h /* ? */))
/**
* Index in literal table
*/
typedef uint32_t literal_index_t;
/**
* Identifiers of ECMA magic string constants
*/
typedef enum
{
#define ECMA_MAGIC_STRING_DEF(id, ascii_zt_string) \
id,
#include "ecma-magic-strings.inc.h"
#undef ECMA_MAGIC_STRING_DEF
ECMA_MAGIC_STRING__COUNT /**< number of magic strings */
} ecma_magic_string_id_t;
/**
* ECMA string hash
*/
typedef uint8_t ecma_string_hash_t;
/**
* Number of string's last characters to use for hash calculation
*/
#define ECMA_STRING_HASH_LAST_CHARS_COUNT (2)
/**
* ECMA string-value descriptor
*/
typedef struct
{
/** Reference counter for the string */
unsigned int refs : CONFIG_ECMA_REFERENCE_COUNTER_WIDTH;
/** Flag indicating whether the string descriptor is placed
* in a stack variable (not in the heap) */
unsigned int is_stack_var : 1;
/** Where the string's data is placed (ecma_string_container_t) */
uint8_t container;
/** Hash of the string (calculated from two last characters of the string) */
ecma_string_hash_t hash;
/**
* Actual data or identifier of it's place in container (depending on 'container' field)
*/
union
{
/** Index of string in literal table */
literal_index_t lit_index;
/** Compressed pointer to an ecma_collection_header_t */
unsigned int collection_cp : ECMA_POINTER_FIELD_WIDTH;
/** Compressed pointer to an ecma_number_t */
unsigned int number_cp : ECMA_POINTER_FIELD_WIDTH;
/** UInt32-represented number placed locally in the descriptor */
uint32_t uint32_number;
/** Representation of concatenation */
struct
{
unsigned int string1_cp : ECMA_POINTER_FIELD_WIDTH;
unsigned int string2_cp : ECMA_POINTER_FIELD_WIDTH;
} concatenation;
/** Identifier of magic string */
ecma_magic_string_id_t magic_string_id;
/** For zeroing and comparison in some cases */
uint32_t common_field;
} u;
} ecma_string_t;
/**
* @}
*/
#endif /* JERRY_ECMA_GLOBALS_H */
/**
* @}
* @}
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,934 @@
/* Copyright 2014 Samsung Electronics Co., Ltd.
*
* 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.
*/
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmahelpers Helpers for operations with ECMA data types
* @{
*/
#include "ecma-globals.h"
#include "ecma-helpers.h"
#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32
JERRY_STATIC_ASSERT (sizeof (ecma_number_t) == sizeof (uint32_t));
/**
* Width of sign field
*
* See also:
* IEEE-754 2008, 3.6, Table 3.5
*/
#define ECMA_NUMBER_SIGN_WIDTH (1)
/**
* Width of biased exponent field
*
* See also:
* IEEE-754 2008, 3.6, Table 3.5
*/
#define ECMA_NUMBER_BIASED_EXP_WIDTH (8)
/**
* Width of fraction field
*
* See also:
* IEEE-754 2008, 3.6, Table 3.5
*/
#define ECMA_NUMBER_FRACTION_WIDTH (23)
/**
* Packing sign, fraction and biased exponent to ecma-number
*
* @return ecma-number with specified sign, biased_exponent and fraction
*/
static ecma_number_t
ecma_number_pack (bool sign, /**< sign */
uint32_t biased_exp, /**< biased exponent */
uint64_t fraction) /**< fraction */
{
const uint32_t fraction_pos = 0;
const uint32_t biased_exp_pos = fraction_pos + ECMA_NUMBER_FRACTION_WIDTH;
const uint32_t sign_pos = biased_exp_pos + ECMA_NUMBER_BIASED_EXP_WIDTH;
JERRY_ASSERT ((biased_exp & ~((1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1)) == 0);
JERRY_ASSERT ((fraction & ~((1ull << ECMA_NUMBER_FRACTION_WIDTH) - 1)) == 0);
uint32_t packed_value = (((sign ? 1u : 0u) << sign_pos) |
(biased_exp << biased_exp_pos) |
(((uint32_t) fraction) << fraction_pos));
union
{
uint32_t u32_value;
ecma_number_t float_value;
} u;
u.u32_value = packed_value;
return u.float_value;
} /* ecma_number_pack */
/**
* Unpacking sign, fraction and biased exponent from ecma-number
*/
static void
ecma_number_unpack (ecma_number_t num, /**< ecma-number */
bool *sign_p, /**< optional out: sign */
uint32_t *biased_exp_p, /**< optional out: biased exponent */
uint64_t *fraction_p) /**< optional out: fraction */
{
const uint32_t fraction_pos = 0;
const uint32_t biased_exp_pos = fraction_pos + ECMA_NUMBER_FRACTION_WIDTH;
const uint32_t sign_pos = biased_exp_pos + ECMA_NUMBER_BIASED_EXP_WIDTH;
union
{
uint32_t u32_value;
ecma_number_t float_value;
} u;
u.float_value = num;
uint32_t packed_value = u.u32_value;
if (sign_p != NULL)
{
*sign_p = ((packed_value >> sign_pos) != 0);
}
if (biased_exp_p != NULL)
{
*biased_exp_p = (((packed_value) & ~(1u << sign_pos)) >> biased_exp_pos);
}
if (fraction_p != NULL)
{
*fraction_p = (packed_value & ((1u << ECMA_NUMBER_FRACTION_WIDTH) - 1));
}
} /* ecma_number_unpack */
/**
* Value used to calculate exponent from biased exponent
*
* See also:
* IEEE-754 2008, 3.6, Table 3.5
*/
const int32_t ecma_number_exponent_bias = 127;
/**
* Relative precision used in calculation with ecma-numbers
*/
const ecma_number_t ecma_number_relative_eps = 1.0e-10f;
#elif CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64
JERRY_STATIC_ASSERT (sizeof (ecma_number_t) == sizeof (uint64_t));
/**
* Width of sign field
*
* See also:
* IEEE-754 2008, 3.6, Table 3.5
*/
#define ECMA_NUMBER_SIGN_WIDTH (1)
/**
* Width of biased exponent field
*
* See also:
* IEEE-754 2008, 3.6, Table 3.5
*/
#define ECMA_NUMBER_BIASED_EXP_WIDTH (11)
/**
* Width of fraction field
*
* See also:
* IEEE-754 2008, 3.6, Table 3.5
*/
#define ECMA_NUMBER_FRACTION_WIDTH (52)
/**
* Packing sign, fraction and biased exponent to ecma-number
*
* @return ecma-number with specified sign, biased_exponent and fraction
*/
static ecma_number_t
ecma_number_pack (bool sign, /**< sign */
uint32_t biased_exp, /**< biased exponent */
uint64_t fraction) /**< fraction */
{
const uint32_t fraction_pos = 0;
const uint32_t biased_exp_pos = fraction_pos + ECMA_NUMBER_FRACTION_WIDTH;
const uint32_t sign_pos = biased_exp_pos + ECMA_NUMBER_BIASED_EXP_WIDTH;
uint64_t packed_value = (((sign ? 1ull : 0ull) << sign_pos) |
(((uint64_t) biased_exp) << biased_exp_pos) |
(fraction << fraction_pos));
JERRY_ASSERT ((biased_exp & ~((1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1)) == 0);
JERRY_ASSERT ((fraction & ~((1ull << ECMA_NUMBER_FRACTION_WIDTH) - 1)) == 0);
union
{
uint64_t u64_value;
ecma_number_t float_value;
} u;
u.u64_value = packed_value;
return u.float_value;
} /* ecma_number_pack */
/**
* Unpacking sign, fraction and biased exponent from ecma-number
*/
static void
ecma_number_unpack (ecma_number_t num, /**< ecma-number */
bool *sign_p, /**< optional out: sign */
uint32_t *biased_exp_p, /**< optional out: biased exponent */
uint64_t *fraction_p) /**< optional out: fraction */
{
const uint32_t fraction_pos = 0;
const uint32_t biased_exp_pos = fraction_pos + ECMA_NUMBER_FRACTION_WIDTH;
const uint32_t sign_pos = biased_exp_pos + ECMA_NUMBER_BIASED_EXP_WIDTH;
union
{
uint64_t u64_value;
ecma_number_t float_value;
} u;
u.float_value = num;
uint64_t packed_value = u.u64_value;
if (sign_p != NULL)
{
*sign_p = ((packed_value >> sign_pos) != 0);
}
if (biased_exp_p != NULL)
{
*biased_exp_p = (uint32_t) (((packed_value) & ~(1ull << sign_pos)) >> biased_exp_pos);
}
if (fraction_p != NULL)
{
*fraction_p = (packed_value & ((1ull << ECMA_NUMBER_FRACTION_WIDTH) - 1));
}
} /* ecma_number_unpack */
/**
* Value used to calculate exponent from biased exponent
*
* See also:
* IEEE-754 2008, 3.6, Table 3.5
*/
const int32_t ecma_number_exponent_bias = 1023;
/**
* Relative precision used in calculation with ecma-numbers
*/
const ecma_number_t ecma_number_relative_eps = 1.0e-16;
#endif /* CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64 */
/**
* Get fraction of number
*
* @return normalized fraction field of number
*/
static uint64_t
ecma_number_get_fraction_field (ecma_number_t num) /**< ecma-number */
{
uint64_t fraction;
ecma_number_unpack (num, NULL, NULL, &fraction);
return fraction;
} /* ecma_number_get_fraction_field */
/**
* Get exponent of number
*
* @return exponent corresponding to normalized fraction of number
*/
static uint32_t
ecma_number_get_biased_exponent_field (ecma_number_t num) /**< ecma-number */
{
uint32_t biased_exp;
ecma_number_unpack (num, NULL, &biased_exp, NULL);
return biased_exp;
} /* ecma_number_get_biased_exponent_field */
/**
* Get sign bit of number
*
* @return 0 or 1 - value of sign bit
*/
static uint32_t
ecma_number_get_sign_field (ecma_number_t num) /**< ecma-number */
{
bool sign;
ecma_number_unpack (num, &sign, NULL, NULL);
return sign;
} /* ecma_number_get_sign_field */
/**
* Check if ecma-number is NaN
*
* @return true - if biased exponent is filled with 1 bits and
fraction is filled with anything but not all zero bits,
* false - otherwise
*/
bool
ecma_number_is_nan (ecma_number_t num) /**< ecma-number */
{
bool is_nan = (num != num);
#ifndef JERRY_NDEBUG
uint32_t biased_exp = ecma_number_get_biased_exponent_field (num);
uint64_t fraction = ecma_number_get_fraction_field (num);
/* IEEE-754 2008, 3.4, a */
bool is_nan_ieee754 = ((biased_exp == (1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1)
&& (fraction != 0));
JERRY_ASSERT (is_nan == is_nan_ieee754);
#endif /* !JERRY_NDEBUG */
return is_nan;
} /* ecma_number_is_nan */
/**
* Make a NaN.
*
* @return NaN value
*/
ecma_number_t
ecma_number_make_nan (void)
{
return ecma_number_pack (false,
(1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1u,
1u);
} /* ecma_number_make_nan */
/**
* Make an Infinity.
*
* @return if !sign - +Infinity value,
* else - -Infinity value.
*/
ecma_number_t
ecma_number_make_infinity (bool sign) /**< true - for negative Infinity,
false - for positive Infinity */
{
return ecma_number_pack (sign,
(1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1u,
0u);
} /* ecma_number_make_infinity */
/**
* Check if ecma-number is negative
*
* @return true - if sign bit of ecma-number is set
* false - otherwise
*/
bool
ecma_number_is_negative (ecma_number_t num) /**< ecma-number */
{
JERRY_ASSERT (!ecma_number_is_nan (num));
/* IEEE-754 2008, 3.4 */
return (ecma_number_get_sign_field (num) != 0);
} /* ecma_number_is_negative */
/**
* Check if ecma-number is zero
*
* @return true - if fraction is zero and biased exponent is zero,
* false - otherwise
*/
bool
ecma_number_is_zero (ecma_number_t num) /**< ecma-number */
{
JERRY_ASSERT (!ecma_number_is_nan (num));
bool is_zero = (num == ECMA_NUMBER_ZERO);
#ifndef JERRY_NDEBUG
/* IEEE-754 2008, 3.4, e */
bool is_zero_ieee754 = (ecma_number_get_fraction_field (num) == 0
&& ecma_number_get_biased_exponent_field (num) == 0);
JERRY_ASSERT (is_zero == is_zero_ieee754);
#endif /* !JERRY_NDEBUG */
return is_zero;
} /* ecma_number_is_zero */
/**
* Check if number is infinity
*
* @return true - if biased exponent is filled with 1 bits and
* fraction is filled with zero bits,
* false - otherwise.
*/
bool
ecma_number_is_infinity (ecma_number_t num) /**< ecma-number */
{
JERRY_ASSERT (!ecma_number_is_nan (num));
uint32_t biased_exp = ecma_number_get_biased_exponent_field (num);
uint64_t fraction = ecma_number_get_fraction_field (num);
/* IEEE-754 2008, 3.4, b */
return ((biased_exp == (1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1)
&& (fraction == 0));
} /* ecma_number_is_infinity */
/**
* Get fraction and exponent of the number
*
* @return shift of dot in the fraction
*/
int32_t
ecma_number_get_fraction_and_exponent (ecma_number_t num, /**< ecma-number */
uint64_t *out_fraction_p, /**< out: fraction of the number */
int32_t *out_exponent_p) /**< out: exponent of the number */
{
JERRY_ASSERT (!ecma_number_is_nan (num));
uint32_t biased_exp = ecma_number_get_biased_exponent_field (num);
uint64_t fraction = ecma_number_get_fraction_field (num);
int32_t exponent;
if (unlikely (biased_exp == 0))
{
/* IEEE-754 2008, 3.4, d */
if (ecma_number_is_zero (num))
{
exponent = -ecma_number_exponent_bias;
}
else
{
exponent = 1 - ecma_number_exponent_bias;
while (!(fraction & (1ull << ECMA_NUMBER_FRACTION_WIDTH)))
{
JERRY_ASSERT (fraction != 0);
fraction <<= 1;
exponent--;
}
}
}
else if (ecma_number_is_infinity (num))
{
/* The fraction and exponent should round to infinity */
exponent = (int32_t) biased_exp - ecma_number_exponent_bias;
JERRY_ASSERT ((fraction & (1ull << ECMA_NUMBER_FRACTION_WIDTH)) == 0);
fraction |= 1ull << ECMA_NUMBER_FRACTION_WIDTH;
}
else
{
/* IEEE-754 2008, 3.4, c */
exponent = (int32_t) biased_exp - ecma_number_exponent_bias;
JERRY_ASSERT (biased_exp > 0 && biased_exp < (1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1);
JERRY_ASSERT ((fraction & (1ull << ECMA_NUMBER_FRACTION_WIDTH)) == 0);
fraction |= 1ull << ECMA_NUMBER_FRACTION_WIDTH;
}
*out_fraction_p = fraction;
*out_exponent_p = exponent;
return ECMA_NUMBER_FRACTION_WIDTH;
} /* ecma_number_get_fraction_and_exponent */
/**
* Make normalised positive Number from given fraction and exponent
*
* @return ecma-number
*/
ecma_number_t
ecma_number_make_normal_positive_from_fraction_and_exponent (uint64_t fraction, /**< fraction */
int32_t exponent) /**< exponent */
{
uint32_t biased_exp = (uint32_t) (exponent + ecma_number_exponent_bias);
JERRY_ASSERT (biased_exp > 0 && biased_exp < (1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1);
JERRY_ASSERT ((fraction & ~((1ull << (ECMA_NUMBER_FRACTION_WIDTH + 1)) - 1)) == 0);
JERRY_ASSERT ((fraction & (1ull << ECMA_NUMBER_FRACTION_WIDTH)) != 0);
return ecma_number_pack (false,
biased_exp,
fraction & ~(1ull << ECMA_NUMBER_FRACTION_WIDTH));
} /* ecma_number_make_normal_positive_from_fraction_and_exponent */
/**
* Make Number of given sign from given mantissa value and binary exponent
*
* @return ecma-number (possibly Infinity of specified sign)
*/
ecma_number_t
ecma_number_make_from_sign_mantissa_and_exponent (bool sign, /**< true - for negative sign,
false - for positive sign */
uint64_t mantissa, /**< mantissa */
int32_t exponent) /**< binary exponent */
{
/* Rounding mantissa to fit into fraction field width */
if (mantissa & ~((1ull << (ECMA_NUMBER_FRACTION_WIDTH + 1)) - 1))
{
/* Rounded mantissa looks like the following: |00...0|1|fraction_width mantissa bits| */
while ((mantissa & ~((1ull << (ECMA_NUMBER_FRACTION_WIDTH + 1)) - 1)) != 0)
{
uint64_t rightmost_bit = (mantissa & 1);
exponent++;
mantissa >>= 1;
if ((mantissa & ~((1ull << (ECMA_NUMBER_FRACTION_WIDTH + 1)) - 1)) == 0)
{
/* Rounding to nearest value */
mantissa += rightmost_bit;
/* In the first case loop is finished,
and in the second - just one shift follows and then loop finishes */
JERRY_ASSERT (((mantissa & ~((1ull << (ECMA_NUMBER_FRACTION_WIDTH + 1)) - 1)) == 0)
|| (mantissa == (1ull << (ECMA_NUMBER_FRACTION_WIDTH + 1))));
}
}
}
/* Normalizing mantissa */
while (mantissa != 0
&& ((mantissa & (1ull << ECMA_NUMBER_FRACTION_WIDTH)) == 0))
{
exponent--;
mantissa <<= 1;
}
/* Moving floating point */
exponent += ECMA_NUMBER_FRACTION_WIDTH - 1;
int32_t biased_exp_signed = exponent + ecma_number_exponent_bias;
if (biased_exp_signed < 1)
{
/* Denormalizing mantissa if biased_exponent is less than zero */
while (biased_exp_signed < 0)
{
biased_exp_signed++;
mantissa >>= 1;
}
/* Rounding to nearest value */
mantissa += 1;
mantissa >>= 1;
/* Encoding denormalized exponent */
biased_exp_signed = 0;
}
else
{
/* Clearing highest mantissa bit that should have been non-zero if mantissa is non-zero */
mantissa &= ~(1ull << ECMA_NUMBER_FRACTION_WIDTH);
}
uint32_t biased_exp = (uint32_t) biased_exp_signed;
if (biased_exp >= ((1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1))
{
return ecma_number_make_infinity (sign);
}
JERRY_ASSERT (biased_exp < (1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1);
JERRY_ASSERT ((mantissa & ~((1ull << ECMA_NUMBER_FRACTION_WIDTH) - 1)) == 0);
return ecma_number_pack (sign,
biased_exp,
mantissa);
} /* ecma_number_make_from_sign_mantissa_and_exponent */
/**
* Get previous representable ecma-number
*
* @return maximum ecma-number that is less compared to passed argument
*/
ecma_number_t
ecma_number_get_prev (ecma_number_t num) /**< ecma-number */
{
JERRY_ASSERT (!ecma_number_is_nan (num));
JERRY_ASSERT (!ecma_number_is_zero (num));
if (ecma_number_is_negative (num))
{
return ecma_number_negate (ecma_number_get_next (num));
}
uint32_t biased_exp = ecma_number_get_biased_exponent_field (num);
uint64_t fraction = ecma_number_get_fraction_field (num);
if (fraction == 0 && biased_exp != 0)
{
fraction = (1ull << ECMA_NUMBER_FRACTION_WIDTH) - 1;
biased_exp--;
}
else
{
fraction--;
}
return ecma_number_pack (false,
biased_exp,
fraction);
} /* ecma_number_get_prev */
/**
* Get next representable ecma-number
*
* @return minimum ecma-number that is greater compared to passed argument
*/
ecma_number_t
ecma_number_get_next (ecma_number_t num) /**< ecma-number */
{
JERRY_ASSERT (!ecma_number_is_nan (num));
JERRY_ASSERT (!ecma_number_is_infinity (num));
if (ecma_number_is_negative (num))
{
return ecma_number_negate (ecma_number_get_prev (num));
}
uint32_t biased_exp = ecma_number_get_biased_exponent_field (num);
uint64_t fraction = ecma_number_get_fraction_field (num);
fraction |= (1ull << ECMA_NUMBER_FRACTION_WIDTH);
fraction++;
if ((fraction & (1ull << ECMA_NUMBER_FRACTION_WIDTH)) == 0)
{
fraction >>= 1;
biased_exp++;
}
JERRY_ASSERT (fraction & (1ull << ECMA_NUMBER_FRACTION_WIDTH));
fraction &= ~(1ull << ECMA_NUMBER_FRACTION_WIDTH);
return ecma_number_pack (false,
biased_exp,
fraction);
} /* ecma_number_get_next */
/**
* Negate ecma-number
*
* @return negated number
*/
ecma_number_t
ecma_number_negate (ecma_number_t num) /**< ecma-number */
{
ecma_number_t negated = -num;
#ifndef JERRY_NDEBUG
bool sign;
uint32_t biased_exp;
uint64_t fraction;
ecma_number_unpack (num, &sign, &biased_exp, &fraction);
sign = !sign;
ecma_number_t negated_ieee754 = ecma_number_pack (sign, biased_exp, fraction);
JERRY_ASSERT (negated == negated_ieee754
|| (ecma_number_is_nan (negated)
&& ecma_number_is_nan (negated_ieee754)));
#endif /* !JERRY_NDEBUG */
return negated;
} /* ecma_number_negate */
/**
* Truncate fractional part of the number
*
* @return integer part of the number
*/
ecma_number_t
ecma_number_trunc (ecma_number_t num) /**< ecma-number */
{
uint64_t fraction;
int32_t exponent;
const int32_t dot_shift = ecma_number_get_fraction_and_exponent (num, &fraction, &exponent);
const bool sign = ecma_number_is_negative (num);
if (exponent < 0)
{
return 0;
}
else if (exponent < dot_shift)
{
fraction &= ~((1ull << (dot_shift - exponent)) - 1);
ecma_number_t tmp = ecma_number_make_normal_positive_from_fraction_and_exponent (fraction,
exponent);
if (sign)
{
return ecma_number_negate (tmp);
}
else
{
return tmp;
}
}
else
{
return num;
}
} /* ecma_number_trunc */
/**
* ECMA-number addition.
*
* @return number - result of addition.
*/
ecma_number_t
ecma_number_add (ecma_number_t left_num, /**< left operand */
ecma_number_t right_num) /**< right operand */
{
return left_num + right_num;
} /* ecma_number_add */
/**
* ECMA-number substraction.
*
* @return number - result of substraction.
*/
ecma_number_t
ecma_number_substract (ecma_number_t left_num, /**< left operand */
ecma_number_t right_num) /**< right operand */
{
return ecma_number_add (left_num, ecma_number_negate (right_num));
} /* ecma_number_substract */
/**
* ECMA-number multiplication.
*
* @return number - result of multiplication.
*/
ecma_number_t
ecma_number_multiply (ecma_number_t left_num, /**< left operand */
ecma_number_t right_num) /**< right operand */
{
return left_num * right_num;
} /* ecma_number_multiply */
/**
* ECMA-number division.
*
* @return number - result of division.
*/
ecma_number_t
ecma_number_divide (ecma_number_t left_num, /**< left operand */
ecma_number_t right_num) /**< right operand */
{
return left_num / right_num;
} /* ecma_number_divide */
/**
* Helper for calculating absolute value
*
* Warning:
* argument should be valid number
*
* @return absolute value of the argument
*/
ecma_number_t
ecma_number_abs (ecma_number_t num) /**< valid number */
{
JERRY_ASSERT (!ecma_number_is_nan (num));
if (num < 0)
{
return ecma_number_negate (num);
}
else
{
return num;
}
} /* ecma_number_abs */
/**
* Helper for calculating square root using Newton's method.
*
* @return square root of specified number
*/
ecma_number_t
ecma_number_sqrt (ecma_number_t num) /**< valid finite
positive number */
{
JERRY_ASSERT (!ecma_number_is_nan (num));
JERRY_ASSERT (!ecma_number_is_infinity (num));
JERRY_ASSERT (!ecma_number_is_negative (num));
ecma_number_t x = ECMA_NUMBER_ONE;
ecma_number_t diff = ecma_number_make_infinity (false);
while (ecma_number_divide (diff, x) > ecma_number_relative_eps)
{
ecma_number_t x_next = ecma_number_multiply (ECMA_NUMBER_HALF,
(ecma_number_add (x,
ecma_number_divide (num, x))));
diff = ecma_number_substract (x, x_next);
if (diff < 0)
{
diff = ecma_number_negate (diff);
}
x = x_next;
}
return x;
} /* ecma_number_sqrt */
/**
* Helper for calculating natural logarithm.
*
* @return natural logarithm of specified number
*/
ecma_number_t
ecma_number_ln (ecma_number_t num) /**< valid finite
positive number */
{
JERRY_ASSERT (!ecma_number_is_nan (num));
JERRY_ASSERT (!ecma_number_is_infinity (num));
JERRY_ASSERT (!ecma_number_is_negative (num));
if (num == ECMA_NUMBER_ONE)
{
return ECMA_NUMBER_ZERO;
}
/* Taylor series of ln (1 + x) around x = 0 is x - x^2/2 + x^3/3 - x^4/4 + ... */
ecma_number_t x = num;
ecma_number_t multiplier = ECMA_NUMBER_ONE;
while (ecma_number_abs (ecma_number_substract (x,
ECMA_NUMBER_ONE)) > ECMA_NUMBER_HALF)
{
x = ecma_number_sqrt (x);
multiplier = ecma_number_multiply (multiplier, ECMA_NUMBER_TWO);
}
x = ecma_number_substract (x, ECMA_NUMBER_ONE);
ecma_number_t sum = ECMA_NUMBER_ZERO;
ecma_number_t next_power = x;
ecma_number_t next_divisor = ECMA_NUMBER_ONE;
ecma_number_t diff;
do
{
ecma_number_t next_sum = ecma_number_add (sum,
ecma_number_divide (next_power,
next_divisor));
next_divisor = ecma_number_add (next_divisor, ECMA_NUMBER_ONE);
next_power = ecma_number_multiply (next_power, x);
next_power = ecma_number_negate (next_power);
diff = ecma_number_abs (ecma_number_substract (sum, next_sum));
sum = next_sum;
}
while (ecma_number_abs (ecma_number_divide (diff,
sum)) > ecma_number_relative_eps);
sum = ecma_number_multiply (sum, multiplier);
return sum;
} /* ecma_number_ln */
/**
* Helper for calculating exponent of a number
*
* @return exponent of specified number
*/
ecma_number_t
ecma_number_exp (ecma_number_t num) /**< valid finite number */
{
JERRY_ASSERT (!ecma_number_is_nan (num));
JERRY_ASSERT (!ecma_number_is_infinity (num));
bool invert = false;
ecma_number_t pow_e;
if (ecma_number_is_negative (num))
{
invert = true;
pow_e = ecma_number_negate (num);
}
else
{
pow_e = num;
}
/* Taylor series of e^x is 1 + x/1! + x^2/2! + x^3/3! + ... + x^n/n! + ... */
ecma_number_t sum = ECMA_NUMBER_ONE;
ecma_number_t next_addendum = ecma_number_divide (pow_e, ECMA_NUMBER_ONE);
ecma_number_t next_factorial_factor = ECMA_NUMBER_ONE;
ecma_number_t diff = ecma_number_make_infinity (false);
while (ecma_number_divide (diff, sum) > ecma_number_relative_eps)
{
ecma_number_t next_sum = ecma_number_add (sum, next_addendum);
next_factorial_factor = ecma_number_add (next_factorial_factor, ECMA_NUMBER_ONE);
next_addendum = ecma_number_multiply (next_addendum, pow_e);
next_addendum = ecma_number_divide (next_addendum, next_factorial_factor);
diff = ecma_number_substract (sum, next_sum);
if (diff < 0)
{
diff = ecma_number_negate (diff);
}
sum = next_sum;
}
if (invert)
{
sum = ecma_number_divide (ECMA_NUMBER_ONE, sum);
}
return sum;
} /* ecma_number_exp */
/**
* @}
* @}
*/
File diff suppressed because it is too large Load Diff
+959
View File
@@ -0,0 +1,959 @@
/* Copyright 2015 Samsung Electronics Co., Ltd.
*
* 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.
*/
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmahelpers Helpers for operations with ECMA data types
* @{
*/
#include "ecma-alloc.h"
#include "ecma-gc.h"
#include "ecma-globals.h"
#include "ecma-helpers.h"
#include "jrt.h"
#include "jrt-bit-fields.h"
JERRY_STATIC_ASSERT (sizeof (ecma_value_t) * JERRY_BITSINBYTE == ECMA_VALUE_SIZE);
/**
* Get type field of ecma-value
*
* @return type field
*/
static ecma_type_t __attr_pure___
ecma_get_value_type_field (const ecma_value_t& value) /**< ecma-value */
{
return (ecma_type_t) jrt_extract_bit_field (value,
ECMA_VALUE_TYPE_POS,
ECMA_VALUE_TYPE_WIDTH);
} /* ecma_get_value_type_field */
/**
* Get value field of ecma-value
*
* @return value field
*/
static uintptr_t __attr_pure___
ecma_get_value_value_field (const ecma_value_t& value) /**< ecma-value */
{
return (uintptr_t) jrt_extract_bit_field (value,
ECMA_VALUE_VALUE_POS,
ECMA_VALUE_VALUE_WIDTH);
} /* ecma_get_value_value_field */
/**
* Set type field of ecma-value
*
* @return ecma-value with updated field
*/
static ecma_value_t __attr_pure___
ecma_set_value_type_field (const ecma_value_t& value, /**< ecma-value to set field in */
ecma_type_t type_field) /**< new field value */
{
return (ecma_value_t) jrt_set_bit_field_value (value,
type_field,
ECMA_VALUE_TYPE_POS,
ECMA_VALUE_TYPE_WIDTH);
} /* ecma_set_value_type_field */
/**
* Set value field of ecma-value
*
* @return ecma-value with updated field
*/
static ecma_value_t __attr_pure___
ecma_set_value_value_field (const ecma_value_t& value, /**< ecma-value to set field in */
uintptr_t value_field) /**< new field value */
{
return (ecma_value_t) jrt_set_bit_field_value (value,
value_field,
ECMA_VALUE_VALUE_POS,
ECMA_VALUE_VALUE_WIDTH);
} /* ecma_set_value_value_field */
/**
* Check if the value is empty.
*
* @return true - if the value contains implementation-defined empty simple value,
* false - otherwise.
*/
bool __attr_pure___ __attr_always_inline___
ecma_is_value_empty (const ecma_value_t& value) /**< ecma-value */
{
return (ecma_get_value_type_field (value) == ECMA_TYPE_SIMPLE
&& ecma_get_value_value_field (value) == ECMA_SIMPLE_VALUE_EMPTY);
} /* ecma_is_value_empty */
/**
* Check if the value is undefined.
*
* @return true - if the value contains ecma-undefined simple value,
* false - otherwise.
*/
bool __attr_pure___ __attr_always_inline___
ecma_is_value_undefined (const ecma_value_t& value) /**< ecma-value */
{
return (ecma_get_value_type_field (value) == ECMA_TYPE_SIMPLE
&& ecma_get_value_value_field (value) == ECMA_SIMPLE_VALUE_UNDEFINED);
} /* ecma_is_value_undefined */
/**
* Check if the value is null.
*
* @return true - if the value contains ecma-null simple value,
* false - otherwise.
*/
bool __attr_pure___ __attr_always_inline___
ecma_is_value_null (const ecma_value_t& value) /**< ecma-value */
{
return (ecma_get_value_type_field (value) == ECMA_TYPE_SIMPLE
&& ecma_get_value_value_field (value) == ECMA_SIMPLE_VALUE_NULL);
} /* ecma_is_value_null */
/**
* Check if the value is boolean.
*
* @return true - if the value contains ecma-true or ecma-false simple values,
* false - otherwise.
*/
bool __attr_pure___ __attr_always_inline___
ecma_is_value_boolean (const ecma_value_t& value) /**< ecma-value */
{
return (ecma_get_value_type_field (value) == ECMA_TYPE_SIMPLE
&& (ecma_get_value_value_field (value) == ECMA_SIMPLE_VALUE_TRUE
|| ecma_get_value_value_field (value) == ECMA_SIMPLE_VALUE_FALSE));
} /* ecma_is_value_boolean */
/**
* Check if the value is true.
*
* Warning:
* value must be boolean
*
* @return true - if the value contains ecma-true simple value,
* false - otherwise.
*/
bool __attr_pure___ __attr_always_inline___
ecma_is_value_true (const ecma_value_t& value) /**< ecma-value */
{
return (ecma_get_value_type_field (value) == ECMA_TYPE_SIMPLE
&& ecma_get_value_value_field (value) == ECMA_SIMPLE_VALUE_TRUE);
} /* ecma_is_value_true */
/**
* Check if the value is ecma-number.
*
* @return true - if the value contains ecma-number value,
* false - otherwise.
*/
bool __attr_pure___ __attr_always_inline___
ecma_is_value_number (const ecma_value_t& value) /**< ecma-value */
{
return (ecma_get_value_type_field (value) == ECMA_TYPE_NUMBER);
} /* ecma_is_value_number */
/**
* Check if the value is ecma-string.
*
* @return true - if the value contains ecma-string value,
* false - otherwise.
*/
bool __attr_pure___ __attr_always_inline___
ecma_is_value_string (const ecma_value_t& value) /**< ecma-value */
{
return (ecma_get_value_type_field (value) == ECMA_TYPE_STRING);
} /* ecma_is_value_string */
/**
* Check if the value is object.
*
* @return true - if the value contains object value,
* false - otherwise.
*/
bool __attr_pure___ __attr_always_inline___
ecma_is_value_object (const ecma_value_t& value) /**< ecma-value */
{
return (ecma_get_value_type_field (value) == ECMA_TYPE_OBJECT);
} /* ecma_is_value_object */
/**
* Debug assertion that specified value's type is one of ECMA-defined
* script-visible types, i.e.: undefined, null, boolean, number, string, object.
*/
void
ecma_check_value_type_is_spec_defined (const ecma_value_t& value) /**< ecma-value */
{
JERRY_ASSERT (ecma_is_value_undefined (value)
|| ecma_is_value_null (value)
|| ecma_is_value_boolean (value)
|| ecma_is_value_number (value)
|| ecma_is_value_string (value)
|| ecma_is_value_object (value));
} /* ecma_check_value_type_is_spec_defined */
/**
* Simple value constructor
*/
ecma_value_t __attr_const___ __attr_always_inline___
ecma_make_simple_value (ecma_simple_value_t value) /**< simple value */
{
ecma_value_t ret_value = 0;
ret_value = ecma_set_value_type_field (ret_value, ECMA_TYPE_SIMPLE);
ret_value = ecma_set_value_value_field (ret_value, value);
return ret_value;
} /* ecma_make_simple_value */
/**
* Number value constructor
*/
ecma_value_t __attr_const___
ecma_make_number_value (ecma_number_t* num_p) /**< number to reference in value */
{
JERRY_ASSERT(num_p != NULL);
uint16_t num_cp;
ECMA_SET_NON_NULL_POINTER (num_cp, num_p);
ecma_value_t ret_value = 0;
ret_value = ecma_set_value_type_field (ret_value, ECMA_TYPE_NUMBER);
ret_value = ecma_set_value_value_field (ret_value, num_cp);
return ret_value;
} /* ecma_make_number_value */
/**
* String value constructor
*/
ecma_value_t __attr_const___
ecma_make_string_value (ecma_string_t* ecma_string_p) /**< string to reference in value */
{
JERRY_ASSERT(ecma_string_p != NULL);
uint16_t string_cp;
ECMA_SET_NON_NULL_POINTER (string_cp, ecma_string_p);
ecma_value_t ret_value = 0;
ret_value = ecma_set_value_type_field (ret_value, ECMA_TYPE_STRING);
ret_value = ecma_set_value_value_field (ret_value, string_cp);
return ret_value;
} /* ecma_make_string_value */
/**
* object value constructor
*/
ecma_value_t __attr_const___
ecma_make_object_value (ecma_object_t* object_p) /**< object to reference in value */
{
JERRY_ASSERT(object_p != NULL);
uint16_t object_cp;
ECMA_SET_NON_NULL_POINTER (object_cp, object_p);
ecma_value_t ret_value = 0;
ret_value = ecma_set_value_type_field (ret_value, ECMA_TYPE_OBJECT);
ret_value = ecma_set_value_value_field (ret_value, object_cp);
return ret_value;
} /* ecma_make_object_value */
/**
* Get pointer to ecma-number from ecma-value
*
* @return the pointer
*/
ecma_number_t* __attr_pure___
ecma_get_number_from_value (const ecma_value_t& value) /**< ecma-value */
{
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_NUMBER);
return ECMA_GET_NON_NULL_POINTER (ecma_number_t,
ecma_get_value_value_field (value));
} /* ecma_get_number_from_value */
/**
* Get pointer to ecma-string from ecma-value
*
* @return the pointer
*/
ecma_string_t* __attr_pure___
ecma_get_string_from_value (const ecma_value_t& value) /**< ecma-value */
{
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_STRING);
return ECMA_GET_NON_NULL_POINTER (ecma_string_t,
ecma_get_value_value_field (value));
} /* ecma_get_string_from_value */
/**
* Get pointer to ecma-object from ecma-value
*
* @return the pointer
*/
ecma_object_t* __attr_pure___
ecma_get_object_from_value (const ecma_value_t& value) /**< ecma-value */
{
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_OBJECT);
return ECMA_GET_NON_NULL_POINTER (ecma_object_t,
ecma_get_value_value_field (value));
} /* ecma_get_object_from_value */
/**
* Copy ecma-value.
*
* Note:
* Operation algorithm.
* switch (valuetype)
* case simple:
* simply return the value as it was passed;
* case number:
* copy the number
* and return new ecma-value
* pointing to copy of the number;
* case string:
* increase reference counter of the string
* and return the value as it was passed.
* case object;
* increase reference counter of the object if do_ref_if_object is true
* and return the value as it was passed.
*
* @return See note.
*/
ecma_value_t
ecma_copy_value (const ecma_value_t& value, /**< ecma-value */
bool do_ref_if_object) /**< if the value is object value,
increment reference counter of the object */
{
ecma_value_t value_copy = 0;
switch (ecma_get_value_type_field (value))
{
case ECMA_TYPE_SIMPLE:
{
value_copy = value;
break;
}
case ECMA_TYPE_NUMBER:
{
ecma_number_t *num_p = ecma_get_number_from_value (value);
ecma_number_t *number_copy_p = ecma_alloc_number ();
*number_copy_p = *num_p;
value_copy = ecma_make_number_value (number_copy_p);
break;
}
case ECMA_TYPE_STRING:
{
ecma_string_t *string_p = ecma_get_string_from_value (value);
string_p = ecma_copy_or_ref_ecma_string (string_p);
value_copy = ecma_make_string_value (string_p);
break;
}
case ECMA_TYPE_OBJECT:
{
ecma_object_t *obj_p = ecma_get_object_from_value (value);
if (do_ref_if_object)
{
ecma_ref_object (obj_p);
}
value_copy = value;
break;
}
}
return value_copy;
} /* ecma_copy_value */
/**
* Free the ecma-value
*/
void
ecma_free_value (ecma_value_t& value, /**< value description */
bool do_deref_if_object) /**< if the value is object value,
decrement reference counter of the object */
{
switch (ecma_get_value_type_field (value))
{
case ECMA_TYPE_SIMPLE:
{
/* doesn't hold additional memory */
break;
}
case ECMA_TYPE_NUMBER:
{
ecma_number_t *number_p = ecma_get_number_from_value (value);
ecma_dealloc_number (number_p);
break;
}
case ECMA_TYPE_STRING:
{
ecma_string_t *string_p = ecma_get_string_from_value (value);
ecma_deref_ecma_string (string_p);
break;
}
case ECMA_TYPE_OBJECT:
{
if (do_deref_if_object)
{
ecma_deref_object (ecma_get_object_from_value (value));
}
break;
}
}
} /* ecma_free_value */
/**
* Get type field of completion value
*
* @return type field
*/
static ecma_completion_type_t __attr_const___
ecma_get_completion_value_type_field (ecma_completion_value_t completion_value) /**< completion value */
{
return (ecma_completion_type_t) jrt_extract_bit_field (completion_value,
ECMA_COMPLETION_VALUE_TYPE_POS,
ECMA_COMPLETION_VALUE_TYPE_WIDTH);
} /* ecma_get_completion_value_type_field */
/**
* Get value field of completion value
*
* @return value field
*/
static ecma_value_t __attr_const___
ecma_get_completion_value_value_field (ecma_completion_value_t completion_value) /**< completion value */
{
return (ecma_value_t) jrt_extract_bit_field (completion_value,
ECMA_COMPLETION_VALUE_VALUE_POS,
ECMA_COMPLETION_VALUE_VALUE_WIDTH);
} /* ecma_get_completion_value_value_field */
/**
* Get pointer to label descriptor from completion value
*
* @return pointer to label descriptor
*/
static ecma_label_descriptor_t* __attr_const___
ecma_get_completion_value_label_descriptor (ecma_completion_value_t completion_value) /**< completion value */
{
return ECMA_GET_NON_NULL_POINTER (ecma_label_descriptor_t,
(uintptr_t) jrt_extract_bit_field (completion_value,
ECMA_COMPLETION_VALUE_LABEL_DESC_CP_POS,
ECMA_COMPLETION_VALUE_LABEL_DESC_CP_WIDTH));
} /* ecma_get_completion_value_label_descriptor */
/**
* Set type field of completion value
*
* @return completion value with updated field
*/
static ecma_completion_value_t __attr_const___
ecma_set_completion_value_type_field (ecma_completion_value_t completion_value, /**< completion value
* to set field in */
ecma_completion_type_t type_field) /**< new field value */
{
return (ecma_completion_value_t) jrt_set_bit_field_value (completion_value,
type_field,
ECMA_COMPLETION_VALUE_TYPE_POS,
ECMA_COMPLETION_VALUE_TYPE_WIDTH);
} /* ecma_set_completion_value_type_field */
/**
* Set value field of completion value
*
* @return completion value with updated field
*/
static ecma_completion_value_t __attr_pure___
ecma_set_completion_value_value_field (ecma_completion_value_t completion_value, /**< completion value
* to set field in */
const ecma_value_t& value_field) /**< new field value */
{
return (ecma_completion_value_t) jrt_set_bit_field_value (completion_value,
value_field,
ECMA_COMPLETION_VALUE_VALUE_POS,
ECMA_COMPLETION_VALUE_VALUE_WIDTH);
} /* ecma_set_completion_value_value_field */
/**
* Set label descriptor of completion value
*
* @return completion value with updated field
*/
static ecma_completion_value_t __attr_const___
ecma_set_completion_value_label_descriptor (ecma_completion_value_t completion_value, /**< completion value
* to set field in */
ecma_label_descriptor_t* label_desc_p) /**< pointer to the
* label descriptor */
{
uintptr_t label_desc_cp;
ECMA_SET_NON_NULL_POINTER (label_desc_cp, label_desc_p);
return (ecma_completion_value_t) jrt_set_bit_field_value (completion_value,
label_desc_cp,
ECMA_COMPLETION_VALUE_LABEL_DESC_CP_POS,
ECMA_COMPLETION_VALUE_LABEL_DESC_CP_WIDTH);
} /* ecma_set_completion_value_label_descriptor */
/**
* Normal, throw, return, exit and meta completion values constructor
*
* @return completion value
*/
ecma_completion_value_t __attr_pure___ __attr_always_inline___
ecma_make_completion_value (ecma_completion_type_t type, /**< type */
const ecma_value_t& value) /**< value */
{
const bool is_type_ok = (type == ECMA_COMPLETION_TYPE_NORMAL
|| type == ECMA_COMPLETION_TYPE_THROW
|| type == ECMA_COMPLETION_TYPE_RETURN
|| type == ECMA_COMPLETION_TYPE_EXIT
|| (type == ECMA_COMPLETION_TYPE_META
&& ecma_is_value_empty (value)));
JERRY_ASSERT (is_type_ok);
ecma_completion_value_t completion_value = 0;
completion_value = ecma_set_completion_value_type_field (completion_value,
type);
completion_value = ecma_set_completion_value_value_field (completion_value,
value);
return completion_value;
} /* ecma_make_completion_value */
/**
* Break and continue completion values constructor
*
* @return completion value
*/
ecma_completion_value_t __attr_const___
ecma_make_label_completion_value (ecma_completion_type_t type, /**< type */
uint8_t depth_level, /**< depth level (in try constructions,
with blocks, etc.) */
uint16_t offset) /**< offset to label from end of last block */
{
JERRY_ASSERT (type == ECMA_COMPLETION_TYPE_BREAK
|| type == ECMA_COMPLETION_TYPE_CONTINUE);
ecma_label_descriptor_t *label_desc_p = ecma_alloc_label_descriptor ();
label_desc_p->offset = offset;
label_desc_p->depth = depth_level;
ecma_completion_value_t completion_value = 0;
completion_value = ecma_set_completion_value_type_field (completion_value,
type);
completion_value = ecma_set_completion_value_label_descriptor (completion_value,
label_desc_p);
return completion_value;
} /* ecma_make_label_completion_value */
/**
* Simple normal completion value constructor
*
* @return completion value
*/
ecma_completion_value_t __attr_const___ __attr_always_inline___
ecma_make_simple_completion_value (ecma_simple_value_t simple_value) /**< simple ecma-value */
{
JERRY_ASSERT(simple_value == ECMA_SIMPLE_VALUE_UNDEFINED
|| simple_value == ECMA_SIMPLE_VALUE_NULL
|| simple_value == ECMA_SIMPLE_VALUE_FALSE
|| simple_value == ECMA_SIMPLE_VALUE_TRUE);
return ecma_make_completion_value (ECMA_COMPLETION_TYPE_NORMAL,
ecma_make_simple_value (simple_value));
} /* ecma_make_simple_completion_value */
/**
* Normal completion value constructor
*
* @return completion value
*/
ecma_completion_value_t __attr_pure___ __attr_always_inline___
ecma_make_normal_completion_value (const ecma_value_t& value) /**< value */
{
return ecma_make_completion_value (ECMA_COMPLETION_TYPE_NORMAL, value);
} /* ecma_make_normal_completion_value */
/**
* Throw completion value constructor
*
* @return completion value
*/
ecma_completion_value_t __attr_pure___ __attr_always_inline___
ecma_make_throw_completion_value (const ecma_value_t& value) /**< value */
{
return ecma_make_completion_value (ECMA_COMPLETION_TYPE_THROW, value);
} /* ecma_make_throw_completion_value */
/**
* Throw completion value constructor.
*
* @return 'throw' completion value
*/
ecma_completion_value_t __attr_const___
ecma_make_throw_obj_completion_value (ecma_object_t *exception_p) /**< an object */
{
JERRY_ASSERT(exception_p != NULL
&& !ecma_is_lexical_environment (exception_p));
ecma_value_t exception = ecma_make_object_value (exception_p);
return ecma_make_throw_completion_value (exception);
} /* ecma_make_throw_obj_completion_value */
/**
* Empty completion value constructor.
*
* @return (normal, empty, reserved) completion value.
*/
ecma_completion_value_t __attr_const___ __attr_always_inline___
ecma_make_empty_completion_value (void)
{
return ecma_make_completion_value (ECMA_COMPLETION_TYPE_NORMAL,
ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY));
} /* ecma_make_empty_completion_value */
/**
* Return completion value constructor
*
* @return completion value
*/
ecma_completion_value_t __attr_pure___ __attr_always_inline___
ecma_make_return_completion_value (const ecma_value_t& value) /**< value */
{
return ecma_make_completion_value (ECMA_COMPLETION_TYPE_RETURN, value);
} /* ecma_make_return_completion_value */
/**
* Exit completion value constructor
*
* @return completion value
*/
ecma_completion_value_t __attr_const___ __attr_always_inline___
ecma_make_exit_completion_value (bool is_successful) /**< does completion value indicate
successfulness completion
of script execution (true) or not (false) */
{
return ecma_make_completion_value (ECMA_COMPLETION_TYPE_EXIT,
ecma_make_simple_value (is_successful ? ECMA_SIMPLE_VALUE_TRUE
: ECMA_SIMPLE_VALUE_FALSE));
} /* ecma_make_exit_completion_value */
/**
* Meta completion value constructor
*
* @return completion value
*/
ecma_completion_value_t __attr_const___ __attr_always_inline___
ecma_make_meta_completion_value (void)
{
return ecma_make_completion_value (ECMA_COMPLETION_TYPE_META,
ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY));
} /* ecma_make_meta_completion_value */
/**
* Get ecma-value from specified completion value
*
* @return ecma-value
*/
ecma_value_t __attr_const___ __attr_always_inline___
ecma_get_completion_value_value (ecma_completion_value_t completion_value) /**< completion value */
{
const ecma_completion_type_t type = ecma_get_completion_value_type_field (completion_value);
const bool is_type_ok = (type == ECMA_COMPLETION_TYPE_NORMAL
|| type == ECMA_COMPLETION_TYPE_THROW
|| type == ECMA_COMPLETION_TYPE_RETURN
|| type == ECMA_COMPLETION_TYPE_EXIT);
JERRY_ASSERT (is_type_ok);
return ecma_get_completion_value_value_field (completion_value);
} /* ecma_get_completion_value_value */
/**
* Get pointer to ecma-number from completion value
*
* @return pointer
*/
ecma_number_t* __attr_const___
ecma_get_number_from_completion_value (ecma_completion_value_t completion_value) /**< completion value */
{
return ecma_get_number_from_value (ecma_get_completion_value_value (completion_value));
} /* ecma_get_number_from_completion_value */
/**
* Get pointer to ecma-string from completion value
*
* @return pointer
*/
ecma_string_t* __attr_const___
ecma_get_string_from_completion_value (ecma_completion_value_t completion_value) /**< completion value */
{
return ecma_get_string_from_value (ecma_get_completion_value_value (completion_value));
} /* ecma_get_string_from_completion_value */
/**
* Get pointer to ecma-object from completion value
*
* @return pointer
*/
ecma_object_t* __attr_const___
ecma_get_object_from_completion_value (ecma_completion_value_t completion_value) /**< completion value */
{
return ecma_get_object_from_value (ecma_get_completion_value_value (completion_value));
} /* ecma_get_object_from_completion_value */
/**
* Copy ecma-completion value.
*
* @return (source.type, ecma_copy_value (source.value), source.target).
*/
ecma_completion_value_t
ecma_copy_completion_value (ecma_completion_value_t value) /**< completion value */
{
const ecma_completion_type_t type = ecma_get_completion_value_type_field (value);
const bool is_type_ok = (type == ECMA_COMPLETION_TYPE_NORMAL
|| type == ECMA_COMPLETION_TYPE_THROW
|| type == ECMA_COMPLETION_TYPE_RETURN
|| type == ECMA_COMPLETION_TYPE_EXIT);
JERRY_ASSERT (is_type_ok);
return ecma_make_completion_value (type,
ecma_copy_value (ecma_get_completion_value_value_field (value),
true));
} /* ecma_copy_completion_value */
/**
* Free the completion value.
*/
void
ecma_free_completion_value (ecma_completion_value_t completion_value) /**< completion value */
{
switch (ecma_get_completion_value_type_field (completion_value))
{
case ECMA_COMPLETION_TYPE_NORMAL:
case ECMA_COMPLETION_TYPE_THROW:
case ECMA_COMPLETION_TYPE_RETURN:
{
ecma_value_t v = ecma_get_completion_value_value_field (completion_value);
ecma_free_value (v, true);
break;
}
case ECMA_COMPLETION_TYPE_EXIT:
{
ecma_value_t v = ecma_get_completion_value_value_field (completion_value);
JERRY_ASSERT(ecma_get_value_type_field (v) == ECMA_TYPE_SIMPLE);
break;
}
case ECMA_COMPLETION_TYPE_CONTINUE:
case ECMA_COMPLETION_TYPE_BREAK:
{
ecma_dealloc_label_descriptor (ecma_get_completion_value_label_descriptor (completion_value));
break;
}
case ECMA_COMPLETION_TYPE_META:
{
JERRY_UNREACHABLE ();
}
}
} /* ecma_free_completion_value */
/**
* Check if the completion value is normal value.
*
* @return true - if the completion type is normal,
* false - otherwise.
*/
bool __attr_const___ __attr_always_inline___
ecma_is_completion_value_normal (ecma_completion_value_t value) /**< completion value */
{
return (ecma_get_completion_value_type_field (value) == ECMA_COMPLETION_TYPE_NORMAL);
} /* ecma_is_completion_value_normal */
/**
* Check if the completion value is throw value.
*
* @return true - if the completion type is throw,
* false - otherwise.
*/
bool __attr_const___ __attr_always_inline___
ecma_is_completion_value_throw (ecma_completion_value_t value) /**< completion value */
{
return (ecma_get_completion_value_type_field (value) == ECMA_COMPLETION_TYPE_THROW);
} /* ecma_is_completion_value_throw */
/**
* Check if the completion value is return value.
*
* @return true - if the completion type is return,
* false - otherwise.
*/
bool __attr_const___ __attr_always_inline___
ecma_is_completion_value_return (ecma_completion_value_t value) /**< completion value */
{
return (ecma_get_completion_value_type_field (value) == ECMA_COMPLETION_TYPE_RETURN);
} /* ecma_is_completion_value_return */
/**
* Check if the completion value is exit value.
*
* @return true - if the completion type is exit,
* false - otherwise.
*/
bool __attr_const___ __attr_always_inline___
ecma_is_completion_value_exit (ecma_completion_value_t value) /**< completion value */
{
if (ecma_get_completion_value_type_field (value) == ECMA_COMPLETION_TYPE_EXIT)
{
JERRY_ASSERT (ecma_is_value_boolean (ecma_get_completion_value_value_field (value)));
return true;
}
else
{
return false;
}
} /* ecma_is_completion_value_exit */
/**
* Check if the completion value is meta value.
*
* @return true - if the completion type is meta,
* false - otherwise.
*/
bool __attr_const___ __attr_always_inline___
ecma_is_completion_value_meta (ecma_completion_value_t value) /**< completion value */
{
if (ecma_get_completion_value_type_field (value) == ECMA_COMPLETION_TYPE_META)
{
JERRY_ASSERT (ecma_is_value_empty (ecma_get_completion_value_value_field (value)));
return true;
}
else
{
return false;
}
} /* ecma_is_completion_value_meta */
/**
* Check if the completion value is break value.
*
* @return true - if the completion type is break,
* false - otherwise.
*/
bool __attr_const___ __attr_always_inline___
ecma_is_completion_value_break (ecma_completion_value_t value) /**< completion value */
{
return (ecma_get_completion_value_type_field (value) == ECMA_COMPLETION_TYPE_BREAK);
} /* ecma_is_completion_value_break */
/**
* Check if the completion value is continue value.
*
* @return true - if the completion type is continue,
* false - otherwise.
*/
bool __attr_const___ __attr_always_inline___
ecma_is_completion_value_continue (ecma_completion_value_t value) /**< completion value */
{
return (ecma_get_completion_value_type_field (value) == ECMA_COMPLETION_TYPE_CONTINUE);
} /* ecma_is_completion_value_continue */
/**
* Check if the completion value is specified normal simple value.
*
* @return true - if the completion type is normal and
* value contains specified simple ecma-value,
* false - otherwise.
*/
bool __attr_const___ __attr_always_inline___
ecma_is_completion_value_normal_simple_value (ecma_completion_value_t value, /**< completion value */
ecma_simple_value_t simple_value) /**< simple value to check
for equality with */
{
return (value == ecma_make_simple_completion_value (simple_value));
} /* ecma_is_completion_value_normal_simple_value */
/**
* Check if the completion value is normal true.
*
* @return true - if the completion type is normal and
* value contains ecma-true simple value,
* false - otherwise.
*/
bool __attr_const___ __attr_always_inline___
ecma_is_completion_value_normal_true (ecma_completion_value_t value) /**< completion value */
{
return ecma_is_completion_value_normal_simple_value (value, ECMA_SIMPLE_VALUE_TRUE);
} /* ecma_is_completion_value_normal_true */
/**
* Check if the completion value is normal false.
*
* @return true - if the completion type is normal and
* value contains ecma-false simple value,
* false - otherwise.
*/
bool __attr_const___ __attr_always_inline___
ecma_is_completion_value_normal_false (ecma_completion_value_t value) /**< completion value */
{
return ecma_is_completion_value_normal_simple_value (value, ECMA_SIMPLE_VALUE_FALSE);
} /* ecma_is_completion_value_normal_false */
/**
* Check if the completion value is normal empty value.
*
* @return true - if the completion type is normal and
* value contains empty simple value,
* false - otherwise.
*/
bool __attr_const___ __attr_always_inline___
ecma_is_completion_value_empty (ecma_completion_value_t value) /**< completion value */
{
return (ecma_is_completion_value_normal (value)
&& ecma_is_value_empty (ecma_get_completion_value_value_field (value)));
} /* ecma_is_completion_value_empty */
/**
* @}
* @}
*/
@@ -0,0 +1,229 @@
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
*
* 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.
*/
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmahelpers Helpers for operations with ECMA data types
* @{
*/
#include "ecma-alloc.h"
#include "ecma-globals.h"
#include "ecma-helpers.h"
#include "jrt.h"
/**
* Allocate a collection of ecma-values.
*
* @return pointer to the collection's header
*/
ecma_collection_header_t*
ecma_new_values_collection (const ecma_value_t values_buffer[], /**< ecma-values */
ecma_length_t values_number, /**< number of ecma-values */
bool do_ref_if_object) /**< if the value is object value,
increase reference counter of the object */
{
JERRY_ASSERT (values_buffer != NULL);
JERRY_ASSERT (values_number > 0);
ecma_collection_header_t* header_p = ecma_alloc_collection_header ();
header_p->unit_number = values_number;
uint16_t* next_chunk_cp_p = &header_p->next_chunk_cp;
ecma_value_t* cur_value_buf_iter_p = (ecma_value_t*) header_p->data;
ecma_value_t* cur_value_buf_end_p = cur_value_buf_iter_p + sizeof (header_p->data) / sizeof (ecma_value_t);
for (ecma_length_t value_index = 0;
value_index < values_number;
value_index++)
{
if (unlikely (cur_value_buf_iter_p == cur_value_buf_end_p))
{
ecma_collection_chunk_t *chunk_p = ecma_alloc_collection_chunk ();
ECMA_SET_POINTER (*next_chunk_cp_p, chunk_p);
next_chunk_cp_p = &chunk_p->next_chunk_cp;
cur_value_buf_iter_p = (ecma_value_t*) chunk_p->data;
cur_value_buf_end_p = cur_value_buf_iter_p + sizeof (chunk_p->data) / sizeof (ecma_value_t);
}
JERRY_ASSERT (cur_value_buf_iter_p + 1 <= cur_value_buf_end_p);
*cur_value_buf_iter_p++ = ecma_copy_value (values_buffer[value_index], do_ref_if_object);
}
*next_chunk_cp_p = 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 */
bool do_deref_if_object) /**< if the value is object value,
decrement reference counter of the object */
{
JERRY_ASSERT (header_p != NULL);
ecma_value_t* cur_value_buf_iter_p = (ecma_value_t*) header_p->data;
ecma_value_t* cur_value_buf_end_p = cur_value_buf_iter_p + sizeof (header_p->data) / sizeof (ecma_value_t);
ecma_length_t string_index = 0;
while (cur_value_buf_iter_p != cur_value_buf_end_p
&& string_index < header_p->unit_number)
{
JERRY_ASSERT (cur_value_buf_iter_p < cur_value_buf_end_p);
ecma_free_value (*cur_value_buf_iter_p, do_deref_if_object);
cur_value_buf_iter_p++;
string_index++;
}
ecma_collection_chunk_t *chunk_p = ECMA_GET_POINTER (ecma_collection_chunk_t,
header_p->next_chunk_cp);
while (chunk_p != NULL)
{
JERRY_ASSERT (string_index < header_p->unit_number);
cur_value_buf_iter_p = (ecma_value_t*) chunk_p->data;
cur_value_buf_end_p = cur_value_buf_iter_p + sizeof (chunk_p->data) / sizeof (ecma_value_t);
while (cur_value_buf_iter_p != cur_value_buf_end_p
&& string_index < header_p->unit_number)
{
JERRY_ASSERT (cur_value_buf_iter_p < cur_value_buf_end_p);
ecma_free_value (*cur_value_buf_iter_p, do_deref_if_object);
cur_value_buf_iter_p++;
string_index++;
}
ecma_collection_chunk_t *next_chunk_p = ECMA_GET_POINTER (ecma_collection_chunk_t,
chunk_p->next_chunk_cp);
ecma_dealloc_collection_chunk (chunk_p);
chunk_p = next_chunk_p;
}
ecma_dealloc_collection_header (header_p);
} /* ecma_free_values_collection */
/**
* Allocate a collection of ecma-strings.
*
* @return pointer to the collection's header
*/
ecma_collection_header_t*
ecma_new_strings_collection (ecma_string_t* string_ptrs_buffer[], /**< pointers to ecma-strings */
ecma_length_t strings_number) /**< number of ecma-strings */
{
JERRY_ASSERT (string_ptrs_buffer != NULL);
JERRY_ASSERT (strings_number > 0);
ecma_collection_header_t *new_collection_p;
MEM_DEFINE_LOCAL_ARRAY (values_buffer, strings_number, ecma_value_t);
for (ecma_length_t string_index = 0;
string_index < strings_number;
string_index++)
{
values_buffer[string_index] = ecma_make_string_value (string_ptrs_buffer[string_index]);
}
new_collection_p = ecma_new_values_collection (values_buffer,
strings_number,
false);
MEM_FINALIZE_LOCAL_ARRAY (values_buffer);
return new_collection_p;
} /* ecma_new_strings_collection */
/**
* Initialize new collection iterator for the collection
*/
void
ecma_collection_iterator_init (ecma_collection_iterator_t *iterator_p, /**< context of iterator */
ecma_collection_header_t *collection_p) /**< header of collection */
{
iterator_p->header_p = collection_p;
iterator_p->next_chunk_cp = collection_p->next_chunk_cp;
iterator_p->current_index = 0;
iterator_p->current_value_p = NULL;
iterator_p->current_chunk_end_p = ((ecma_value_t*) iterator_p->header_p->data
+ sizeof (iterator_p->header_p->data) / sizeof (ecma_value_t));
} /* ecma_collection_iterator_init */
/**
* Move collection iterator to next element if there is any.
*
* @return true - if iterator moved,
* false - otherwise (current element is last element in the collection)
*/
bool
ecma_collection_iterator_next (ecma_collection_iterator_t *iterator_p) /**< context of iterator */
{
if (unlikely (iterator_p->header_p->unit_number == 0))
{
return false;
}
if (iterator_p->current_value_p == NULL)
{
JERRY_ASSERT (iterator_p->current_index == 0);
iterator_p->current_value_p = (ecma_value_t*) iterator_p->header_p->data;
return true;
}
if (iterator_p->current_index + 1 == iterator_p->header_p->unit_number)
{
return false;
}
JERRY_ASSERT (iterator_p->current_index + 1 < iterator_p->header_p->unit_number);
iterator_p->current_index++;
iterator_p->current_value_p++;
if (iterator_p->current_value_p == iterator_p->current_chunk_end_p)
{
ecma_collection_chunk_t *next_chunk_p = ECMA_GET_POINTER (ecma_collection_chunk_t,
iterator_p->next_chunk_cp);
JERRY_ASSERT (next_chunk_p != NULL);
iterator_p->next_chunk_cp = next_chunk_p->next_chunk_cp;
iterator_p->current_value_p = (ecma_value_t*) &next_chunk_p->data;
iterator_p->current_chunk_end_p = iterator_p->current_value_p + sizeof (next_chunk_p->data) / sizeof (ecma_value_t);
}
else
{
JERRY_ASSERT (iterator_p->current_value_p < iterator_p->current_chunk_end_p);
}
return true;
} /* ecma_collection_iterator_next */
/**
* @}
* @}
*/
File diff suppressed because it is too large Load Diff
+311
View File
@@ -0,0 +1,311 @@
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
*
* 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.
*/
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmahelpers Helpers for operations with ECMA data types
* @{
*/
#ifndef JERRY_ECMA_HELPERS_H
#define JERRY_ECMA_HELPERS_H
#include "ecma-globals.h"
#include "mem-allocator.h"
/**
* Get value of pointer from specified non-null compressed pointer field.
*/
#define ECMA_GET_NON_NULL_POINTER(type, field) \
((type *) mem_decompress_pointer (field))
/**
* Get value of pointer from specified compressed pointer field.
*/
#define ECMA_GET_POINTER(type, field) \
(((unlikely (field == ECMA_NULL_POINTER)) ? NULL : ECMA_GET_NON_NULL_POINTER (type, field)))
/**
* Set value of non-null compressed pointer field so that it will correspond
* to specified non_compressed_pointer.
*/
#define ECMA_SET_NON_NULL_POINTER(field, non_compressed_pointer) \
(field) = (mem_compress_pointer (non_compressed_pointer) & ((1u << ECMA_POINTER_FIELD_WIDTH) - 1))
/**
* Set value of compressed pointer field so that it will correspond
* to specified non_compressed_pointer.
*/
#define ECMA_SET_POINTER(field, non_compressed_pointer) \
do \
{ \
auto __temp_pointer = non_compressed_pointer; \
non_compressed_pointer = __temp_pointer; \
} while (0); \
\
(field) = (unlikely ((non_compressed_pointer) == NULL) ? ECMA_NULL_POINTER \
: (mem_compress_pointer (non_compressed_pointer) \
& ((1u << ECMA_POINTER_FIELD_WIDTH) - 1)))
/* ecma-helpers-value.c */
extern bool ecma_is_value_empty (const ecma_value_t& value);
extern bool ecma_is_value_undefined (const ecma_value_t& value);
extern bool ecma_is_value_null (const ecma_value_t& value);
extern bool ecma_is_value_boolean (const ecma_value_t& value);
extern bool ecma_is_value_true (const ecma_value_t& value);
extern bool ecma_is_value_number (const ecma_value_t& value);
extern bool ecma_is_value_string (const ecma_value_t& value);
extern bool ecma_is_value_object (const ecma_value_t& value);
extern void ecma_check_value_type_is_spec_defined (const ecma_value_t& value);
extern ecma_value_t ecma_make_simple_value (ecma_simple_value_t value);
extern ecma_value_t ecma_make_number_value (ecma_number_t* num_p);
extern ecma_value_t ecma_make_string_value (ecma_string_t* ecma_string_p);
extern ecma_value_t ecma_make_object_value (ecma_object_t* object_p);
extern ecma_number_t* __attr_pure___ ecma_get_number_from_value (const ecma_value_t& value);
extern ecma_string_t* __attr_pure___ ecma_get_string_from_value (const ecma_value_t& value);
extern ecma_object_t* __attr_pure___ ecma_get_object_from_value (const ecma_value_t& value);
extern ecma_value_t ecma_copy_value (const ecma_value_t& value, bool do_ref_if_object);
extern void ecma_free_value (ecma_value_t& value, bool do_deref_if_object);
extern ecma_completion_value_t ecma_make_completion_value (ecma_completion_type_t type,
const ecma_value_t& value);
extern ecma_completion_value_t ecma_make_label_completion_value (ecma_completion_type_t type,
uint8_t depth_level,
uint16_t offset);
extern ecma_completion_value_t ecma_make_simple_completion_value (ecma_simple_value_t simple_value);
extern ecma_completion_value_t ecma_make_normal_completion_value (const ecma_value_t& value);
extern ecma_completion_value_t ecma_make_throw_completion_value (const ecma_value_t& value);
extern ecma_completion_value_t ecma_make_throw_obj_completion_value (ecma_object_t *exception_p);
extern ecma_completion_value_t ecma_make_empty_completion_value (void);
extern ecma_completion_value_t ecma_make_return_completion_value (const ecma_value_t& value);
extern ecma_completion_value_t ecma_make_exit_completion_value (bool is_successful);
extern ecma_completion_value_t ecma_make_meta_completion_value (void);
extern ecma_value_t ecma_get_completion_value_value (ecma_completion_value_t completion_value);
extern ecma_number_t* __attr_const___
ecma_get_number_from_completion_value (ecma_completion_value_t completion_value);
extern ecma_string_t* __attr_const___
ecma_get_string_from_completion_value (ecma_completion_value_t completion_value);
extern ecma_object_t* __attr_const___
ecma_get_object_from_completion_value (ecma_completion_value_t completion_value);
extern ecma_completion_value_t ecma_copy_completion_value (ecma_completion_value_t value);
extern void ecma_free_completion_value (ecma_completion_value_t completion_value);
extern bool ecma_is_completion_value_normal (ecma_completion_value_t value);
extern bool ecma_is_completion_value_throw (ecma_completion_value_t value);
extern bool ecma_is_completion_value_return (ecma_completion_value_t value);
extern bool ecma_is_completion_value_exit (ecma_completion_value_t value);
extern bool ecma_is_completion_value_meta (ecma_completion_value_t value);
extern bool ecma_is_completion_value_break (ecma_completion_value_t value);
extern bool ecma_is_completion_value_continue (ecma_completion_value_t value);
extern bool ecma_is_completion_value_normal_simple_value (ecma_completion_value_t value,
ecma_simple_value_t simple_value);
extern bool ecma_is_completion_value_normal_true (ecma_completion_value_t value);
extern bool ecma_is_completion_value_normal_false (ecma_completion_value_t value);
extern bool ecma_is_completion_value_empty (ecma_completion_value_t value);
/* ecma-helpers-string.c */
extern ecma_string_t* ecma_new_ecma_string (const ecma_char_t *string_p);
extern ecma_string_t* ecma_new_ecma_string_from_uint32 (uint32_t uint_number);
extern ecma_string_t* ecma_new_ecma_string_from_number (ecma_number_t number);
extern void ecma_new_ecma_string_on_stack_from_lit_index (ecma_string_t *string_p,
literal_index_t lit_index);
extern ecma_string_t* ecma_new_ecma_string_from_lit_index (literal_index_t lit_index);
extern void ecma_new_ecma_string_on_stack_from_magic_string_id (ecma_string_t *string_p,
ecma_magic_string_id_t id);
extern ecma_string_t* ecma_new_ecma_string_from_magic_string_id (ecma_magic_string_id_t id);
extern ecma_string_t* ecma_concat_ecma_strings (ecma_string_t *string1_p, ecma_string_t *string2_p);
extern ecma_string_t* ecma_copy_or_ref_ecma_string (ecma_string_t *string_desc_p);
extern void ecma_deref_ecma_string (ecma_string_t *string_p);
extern void ecma_check_that_ecma_string_need_not_be_freed (const ecma_string_t *string_p);
extern ecma_number_t ecma_string_to_number (const ecma_string_t *str_p);
extern ssize_t ecma_string_to_zt_string (const ecma_string_t *string_desc_p,
ecma_char_t *buffer_p,
ssize_t buffer_size);
extern bool ecma_compare_ecma_strings_equal_hashes (const ecma_string_t *string1_p,
const ecma_string_t *string2_p);
extern bool ecma_compare_ecma_strings (const ecma_string_t *string1_p,
const ecma_string_t *string2_p);
extern bool ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p,
const ecma_string_t *string2_p);
extern int32_t ecma_string_get_length (const ecma_string_t *string_p);
extern ecma_char_t ecma_string_get_char_at_pos (const ecma_string_t *string_p, uint32_t index);
extern bool ecma_compare_zt_strings (const ecma_char_t *string1_p, const ecma_char_t *string2_p);
extern bool ecma_compare_zt_strings_relational (const ecma_char_t *string1_p, const ecma_char_t *string2_p);
extern ecma_char_t*
ecma_copy_zt_string_to_buffer (const ecma_char_t *string_p,
ecma_char_t *buffer_p,
ssize_t buffer_size);
extern ecma_length_t ecma_zt_string_length (const ecma_char_t *string_p);
extern void ecma_strings_init (void);
extern const ecma_char_t* ecma_get_magic_string_zt (ecma_magic_string_id_t id);
extern ecma_string_t* ecma_get_magic_string (ecma_magic_string_id_t id);
extern bool ecma_is_string_magic (const ecma_string_t *string_p, ecma_magic_string_id_t *out_id_p);
extern bool ecma_is_zt_string_magic (const ecma_char_t *zt_string_p, ecma_magic_string_id_t *out_id_p);
extern ecma_string_hash_t ecma_string_hash (const ecma_string_t *string_p);
extern ecma_string_hash_t ecma_chars_buffer_calc_hash_last_chars (const ecma_char_t *chars, ecma_length_t length);
/* ecma-helpers-number.c */
extern const ecma_number_t ecma_number_relative_eps;
extern ecma_number_t ecma_number_make_nan (void);
extern ecma_number_t ecma_number_make_infinity (bool sign);
extern bool ecma_number_is_nan (ecma_number_t num);
extern bool ecma_number_is_negative (ecma_number_t num);
extern bool ecma_number_is_zero (ecma_number_t num);
extern bool ecma_number_is_infinity (ecma_number_t num);
extern int32_t
ecma_number_get_fraction_and_exponent (ecma_number_t num,
uint64_t *out_fraction_p,
int32_t *out_exponent_p);
extern ecma_number_t
ecma_number_make_normal_positive_from_fraction_and_exponent (uint64_t fraction,
int32_t exponent);
extern ecma_number_t
ecma_number_make_from_sign_mantissa_and_exponent (bool sign,
uint64_t mantissa,
int32_t exponent);
extern ecma_number_t ecma_number_get_prev (ecma_number_t num);
extern ecma_number_t ecma_number_get_next (ecma_number_t num);
extern ecma_number_t ecma_number_negate (ecma_number_t num);
extern ecma_number_t ecma_number_trunc (ecma_number_t num);
extern ecma_number_t ecma_number_add (ecma_number_t left_num, ecma_number_t right_num);
extern ecma_number_t ecma_number_substract (ecma_number_t left_num, ecma_number_t right_num);
extern ecma_number_t ecma_number_multiply (ecma_number_t left_num, ecma_number_t right_num);
extern ecma_number_t ecma_number_divide (ecma_number_t left_num, ecma_number_t right_num);
extern ecma_number_t ecma_number_sqrt (ecma_number_t num);
extern ecma_number_t ecma_number_abs (ecma_number_t num);
extern ecma_number_t ecma_number_ln (ecma_number_t num);
extern ecma_number_t ecma_number_exp (ecma_number_t num);
/* ecma-helpers-values-collection.c */
extern ecma_collection_header_t *ecma_new_values_collection (const ecma_value_t values_buffer[],
ecma_length_t values_number,
bool do_ref_if_object);
extern void ecma_free_values_collection (ecma_collection_header_t* header_p, bool do_deref_if_object);
extern ecma_collection_header_t *ecma_new_strings_collection (ecma_string_t* string_ptrs_buffer[],
ecma_length_t strings_number);
/**
* Context of ecma-values' collection iterator
*/
typedef struct
{
ecma_collection_header_t *header_p; /**< collection header */
uint16_t next_chunk_cp; /**< compressed pointer to next chunk */
ecma_length_t current_index; /**< index of current element */
const ecma_value_t *current_value_p; /**< pointer to current element */
const ecma_value_t *current_chunk_beg_p; /**< pointer to beginning of current chunk's data */
const ecma_value_t *current_chunk_end_p; /**< pointer to place right after the end of current chunk's data */
} ecma_collection_iterator_t;
extern void
ecma_collection_iterator_init (ecma_collection_iterator_t *iterator_p,
ecma_collection_header_t *collection_p);
extern bool
ecma_collection_iterator_next (ecma_collection_iterator_t *iterator_p);
/* ecma-helpers.c */
extern ecma_object_t* ecma_create_object (ecma_object_t *prototype_object_p,
bool is_extensible,
ecma_object_type_t type);
extern ecma_object_t* ecma_create_decl_lex_env (ecma_object_t *outer_lexical_environment_p);
extern ecma_object_t* ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p,
ecma_object_t *binding_obj_p,
bool provide_this);
extern bool __attr_pure___ ecma_is_lexical_environment (const ecma_object_t *object_p);
extern bool __attr_pure___ ecma_get_object_extensible (const ecma_object_t *object_p);
extern void ecma_set_object_extensible (ecma_object_t *object_p, bool is_extensible);
extern ecma_object_type_t __attr_pure___ ecma_get_object_type (const ecma_object_t *object_p);
extern void ecma_set_object_type (ecma_object_t *object_p, ecma_object_type_t type);
extern ecma_object_t* __attr_pure___ ecma_get_object_prototype (const ecma_object_t *object_p);
extern bool __attr_pure___ ecma_get_object_is_builtin (const ecma_object_t *object_p);
extern void ecma_set_object_is_builtin (ecma_object_t *object_p,
bool is_builtin);
extern ecma_lexical_environment_type_t __attr_pure___ ecma_get_lex_env_type (const ecma_object_t *object_p);
extern ecma_object_t* __attr_pure___ ecma_get_lex_env_outer_reference (const ecma_object_t *object_p);
extern ecma_property_t* __attr_pure___ ecma_get_property_list (const ecma_object_t *object_p);
extern ecma_object_t* __attr_pure___ ecma_get_lex_env_binding_object (const ecma_object_t *object_p);
extern bool __attr_pure___ ecma_get_lex_env_provide_this (const ecma_object_t *object_p);
extern ecma_property_t* ecma_create_internal_property (ecma_object_t *object_p,
ecma_internal_property_id_t property_id);
extern ecma_property_t* ecma_find_internal_property (ecma_object_t *object_p,
ecma_internal_property_id_t property_id);
extern ecma_property_t* ecma_get_internal_property (ecma_object_t *object_p,
ecma_internal_property_id_t property_id);
extern ecma_property_t *ecma_create_named_data_property (ecma_object_t *obj_p,
ecma_string_t *name_p,
bool is_writable,
bool is_enumerable,
bool is_configurable);
extern ecma_property_t *ecma_create_named_accessor_property (ecma_object_t *obj_p,
ecma_string_t *name_p,
ecma_object_t *get_p,
ecma_object_t *set_p,
bool is_enumerable,
bool is_configurable);
extern ecma_property_t *ecma_find_named_property (ecma_object_t *obj_p,
ecma_string_t *name_p);
extern ecma_property_t *ecma_get_named_property (ecma_object_t *obj_p,
ecma_string_t *name_p);
extern ecma_property_t *ecma_get_named_data_property (ecma_object_t *obj_p,
ecma_string_t *name_p);
extern void ecma_free_property (ecma_object_t *obj_p, ecma_property_t *prop_p);
extern void ecma_delete_property (ecma_object_t *obj_p, ecma_property_t *prop_p);
extern ecma_value_t ecma_get_named_data_property_value (const ecma_property_t *prop_p);
extern void ecma_set_named_data_property_value (ecma_property_t *prop_p, const ecma_value_t& value);
extern void ecma_named_data_property_assign_value (ecma_object_t *obj_p,
ecma_property_t *prop_p,
const ecma_value_t& value);
extern bool ecma_is_property_writable (ecma_property_t* prop_p);
extern void ecma_set_property_writable_attr (ecma_property_t* prop_p, bool is_writable);
extern bool ecma_is_property_enumerable (ecma_property_t* prop_p);
extern void ecma_set_property_enumerable_attr (ecma_property_t* prop_p, bool is_enumerable);
extern bool ecma_is_property_configurable (ecma_property_t* prop_p);
extern void ecma_set_property_configurable_attr (ecma_property_t* prop_p, bool is_configurable);
extern bool ecma_is_property_lcached (ecma_property_t *prop_p);
extern void ecma_set_property_lcached (ecma_property_t *prop_p,
bool is_lcached);
extern ecma_property_descriptor_t ecma_make_empty_property_descriptor (void);
extern void ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p);
/* ecma-helpers-conversion.c */
extern ecma_number_t ecma_zt_string_to_number (const ecma_char_t *str_p);
extern ssize_t ecma_uint32_to_string (uint32_t value, ecma_char_t *out_buffer_p, ssize_t buffer_size);
extern uint32_t ecma_number_to_uint32 (ecma_number_t value);
extern int32_t ecma_number_to_int32 (ecma_number_t value);
extern ecma_number_t ecma_int32_to_number (int32_t value);
extern ecma_number_t ecma_uint32_to_number (uint32_t value);
extern ecma_length_t ecma_number_to_zt_string (ecma_number_t num, ecma_char_t *buffer_p, ssize_t buffer_size);
#endif /* !JERRY_ECMA_HELPERS_H */
/**
* @}
* @}
*/
+326
View File
@@ -0,0 +1,326 @@
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
*
* 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-gc.h"
#include "ecma-globals.h"
#include "ecma-helpers.h"
#include "ecma-lcache.h"
#include "jrt-libc-includes.h"
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmalcache Property lookup cache
* @{
*/
/**
* Entry of LCache hash table
*/
typedef struct
{
/** Compressed pointer to object (ECMA_NULL_POINTER marks record empty) */
uint16_t object_cp;
/** Compressed pointer to property's name */
uint16_t prop_name_cp;
/** Compressed pointer to a property of the object */
uint16_t prop_cp;
/** Padding structure to 8 bytes size */
uint16_t padding;
} ecma_lcache_hash_entry_t;
JERRY_STATIC_ASSERT (sizeof (ecma_lcache_hash_entry_t) == sizeof (uint64_t));
/**
* LCache hash value length, in bits
*/
#define ECMA_LCACHE_HASH_BITS (sizeof (ecma_string_hash_t) * JERRY_BITSINBYTE)
/**
* Number of rows in LCache's hash table
*/
#define ECMA_LCACHE_HASH_ROWS_COUNT (1ull << ECMA_LCACHE_HASH_BITS)
/**
* Number of entries in a row of LCache's hash table
*/
#define ECMA_LCACHE_HASH_ROW_LENGTH (2)
/**
* LCache's hash table
*/
static ecma_lcache_hash_entry_t ecma_lcache_hash_table[ ECMA_LCACHE_HASH_ROWS_COUNT ][ ECMA_LCACHE_HASH_ROW_LENGTH ];
/**
* Initialize LCache
*/
void
ecma_lcache_init (void)
{
memset (ecma_lcache_hash_table, 0, sizeof (ecma_lcache_hash_table));
} /* ecma_lcache_init */
/**
* Invalidate specified LCache entry
*/
static void
ecma_lcache_invalidate_entry (ecma_lcache_hash_entry_t *entry_p) /**< entry to invalidate */
{
JERRY_ASSERT (entry_p != NULL);
JERRY_ASSERT (entry_p->object_cp != ECMA_NULL_POINTER);
ecma_deref_object (ECMA_GET_NON_NULL_POINTER (ecma_object_t,
entry_p->object_cp));
entry_p->object_cp = ECMA_NULL_POINTER;
ecma_deref_ecma_string (ECMA_GET_NON_NULL_POINTER (ecma_string_t,
entry_p->prop_name_cp));
if (entry_p->prop_cp != ECMA_NULL_POINTER)
{
ecma_set_property_lcached (ECMA_GET_NON_NULL_POINTER (ecma_property_t,
entry_p->prop_cp),
false);
}
} /* ecma_lcache_invalidate_entry */
/**
* Invalidate all entries in LCache
*/
void
ecma_lcache_invalidate_all (void)
{
for (uint32_t row_index = 0; row_index < ECMA_LCACHE_HASH_ROWS_COUNT; row_index++)
{
for (uint32_t entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++)
{
if (ecma_lcache_hash_table[ row_index ][ entry_index ].object_cp != ECMA_NULL_POINTER)
{
ecma_lcache_invalidate_entry (&ecma_lcache_hash_table[ row_index ][ entry_index ]);
}
}
}
} /* ecma_lcache_invalidate_all */
/**
* Invalidate entries of LCache's row that correspond to given (object, property) pair
*/
static void
ecma_lcache_invalidate_row_for_object_property_pair (uint32_t row_index, /**< index of the row */
unsigned int object_cp, /**< compressed pointer
* to an object */
unsigned property_cp) /**< compressed pointer
* to the object's
* property */
{
for (uint32_t entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++)
{
if (ecma_lcache_hash_table[ row_index ][ entry_index ].object_cp == object_cp
&& ecma_lcache_hash_table[ row_index ][ entry_index ].prop_cp == property_cp)
{
ecma_lcache_invalidate_entry (&ecma_lcache_hash_table[ row_index ][ entry_index ]);
}
}
} /* ecma_lcache_invalidate_row_for_object_property_pair */
/**
* Insert an entry into LCache
*/
void
ecma_lcache_insert (ecma_object_t *object_p, /**< object */
ecma_string_t *prop_name_p, /**< property's name */
ecma_property_t *prop_p) /**< pointer to associated property or NULL
* (NULL indicates that the object doesn't have property
* with the name specified) */
{
JERRY_ASSERT (object_p != NULL);
JERRY_ASSERT (prop_name_p != NULL);
prop_name_p = ecma_copy_or_ref_ecma_string (prop_name_p);
ecma_string_hash_t hash_key = ecma_string_hash (prop_name_p);
if (prop_p != NULL)
{
if (unlikely (ecma_is_property_lcached (prop_p)))
{
uint16_t prop_cp;
ECMA_SET_NON_NULL_POINTER (prop_cp, prop_p);
int32_t entry_index;
for (entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++)
{
if (ecma_lcache_hash_table[hash_key][entry_index].object_cp != ECMA_NULL_POINTER
&& ecma_lcache_hash_table[hash_key][entry_index].prop_cp == prop_cp)
{
#ifndef JERRY_NDEBUG
ecma_object_t* obj_in_entry_p;
obj_in_entry_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t,
ecma_lcache_hash_table[hash_key][entry_index].object_cp);
JERRY_ASSERT (obj_in_entry_p == object_p);
#endif /* !JERRY_NDEBUG */
break;
}
}
JERRY_ASSERT (entry_index != ECMA_LCACHE_HASH_ROW_LENGTH);
ecma_lcache_invalidate_entry (&ecma_lcache_hash_table[hash_key][entry_index]);
}
JERRY_ASSERT (!ecma_is_property_lcached (prop_p));
ecma_set_property_lcached (prop_p, true);
}
int32_t entry_index;
for (entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++)
{
if (ecma_lcache_hash_table[hash_key][entry_index].object_cp == ECMA_NULL_POINTER)
{
break;
}
}
if (entry_index == ECMA_LCACHE_HASH_ROW_LENGTH)
{
/* No empty entry was found, invalidating the whole row */
for (uint32_t i = 0; i < ECMA_LCACHE_HASH_ROW_LENGTH; i++)
{
ecma_lcache_invalidate_entry (&ecma_lcache_hash_table[hash_key][i]);
}
entry_index = 0;
}
ecma_ref_object (object_p);
ECMA_SET_NON_NULL_POINTER (ecma_lcache_hash_table[ hash_key ][ entry_index ].object_cp, object_p);
ECMA_SET_NON_NULL_POINTER (ecma_lcache_hash_table[ hash_key ][ entry_index ].prop_name_cp, prop_name_p);
ECMA_SET_POINTER (ecma_lcache_hash_table[ hash_key ][ entry_index ].prop_cp, prop_p);
} /* ecma_lcache_insert */
/**
* Lookup property in the LCache
*
* @return true - if (object, property name) pair is registered in LCache,
* false - probably, not registered.
*/
bool __attr_always_inline___
ecma_lcache_lookup (ecma_object_t *object_p, /**< object */
const ecma_string_t *prop_name_p, /**< property's name */
ecma_property_t **prop_p_p) /**< out: if return value is true,
* then here will be pointer to property,
* if the object contains property with specified name,
* or, otherwise - NULL;
* if return value is false,
* then the output parameter is not set */
{
ecma_string_hash_t hash_key = ecma_string_hash (prop_name_p);
unsigned int object_cp;
ECMA_SET_NON_NULL_POINTER (object_cp, object_p);
for (uint32_t i = 0; i < ECMA_LCACHE_HASH_ROW_LENGTH; i++)
{
if (ecma_lcache_hash_table[hash_key][i].object_cp == object_cp)
{
ecma_string_t *entry_prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
ecma_lcache_hash_table[hash_key][i].prop_name_cp);
if (ecma_compare_ecma_strings_equal_hashes (prop_name_p, entry_prop_name_p))
{
ecma_property_t *prop_p = ECMA_GET_POINTER (ecma_property_t, ecma_lcache_hash_table[hash_key][i].prop_cp);
JERRY_ASSERT (prop_p == NULL || ecma_is_property_lcached (prop_p));
*prop_p_p = prop_p;
return true;
}
else
{
/* may be equal but it is long to compare it here */
}
}
}
return false;
} /* ecma_lcache_lookup */
/**
* Invalidate LCache entries associated with given object and property name / property
*
* Note:
* Either property name argument or property argument should be NULL,
* and another should be non-NULL.
* In case property name argument is NULL, property's name is taken
* from property's description.
*/
void
ecma_lcache_invalidate (ecma_object_t *object_p, /**< object */
ecma_string_t *prop_name_arg_p, /**< property's name (See also: Note) */
ecma_property_t *prop_p) /**< property (See also: Note) */
{
JERRY_ASSERT (object_p != NULL);
JERRY_ASSERT (prop_p != NULL || prop_name_arg_p != NULL);
ecma_string_t *prop_name_p = NULL;
if (prop_p != NULL)
{
JERRY_ASSERT (prop_p->type == ECMA_PROPERTY_NAMEDDATA
|| prop_p->type == ECMA_PROPERTY_NAMEDACCESSOR);
bool is_cached = ecma_is_property_lcached (prop_p);
if (!is_cached)
{
return;
}
ecma_set_property_lcached (prop_p, false);
if (prop_p->type == ECMA_PROPERTY_NAMEDDATA)
{
prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
prop_p->u.named_data_property.name_p);
}
else
{
prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
prop_p->u.named_accessor_property.name_p);
}
}
else
{
prop_name_p = prop_name_arg_p;
}
unsigned int object_cp, prop_cp;
ECMA_SET_NON_NULL_POINTER (object_cp, object_p);
ECMA_SET_POINTER (prop_cp, prop_p);
ecma_string_hash_t hash_key = ecma_string_hash (prop_name_p);
/* Property's name has was computed.
* Given (object, property name) pair should be in the row corresponding to computed hash.
*/
ecma_lcache_invalidate_row_for_object_property_pair (hash_key, object_cp, prop_cp);
} /* ecma_lcache_invalidate */
/**
* @}
* @}
*/
+37
View File
@@ -0,0 +1,37 @@
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
*
* 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.
*/
#ifndef ECMA_LCACHE_H
#define ECMA_LCACHE_H
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmalcache Property lookup cache
* @{
*/
extern void ecma_lcache_init (void);
extern void ecma_lcache_invalidate_all (void);
extern void ecma_lcache_insert (ecma_object_t *object_p, ecma_string_t *prop_name_p, ecma_property_t *prop_p);
extern bool ecma_lcache_lookup (ecma_object_t *object_p, const ecma_string_t *prop_name_p, ecma_property_t **prop_p_p);
extern void ecma_lcache_invalidate (ecma_object_t *object_p, ecma_string_t *prop_name_arg_p, ecma_property_t *prop_p);
/**
* @}
* @}
*/
#endif /* ECMA_LCACHE_H */
@@ -0,0 +1,210 @@
/* Copyright 2014 Samsung Electronics Co., Ltd.
*
* 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.
*/
/*
* List of ECMA magic strings
*/
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_ARGUMENTS, "arguments")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_EVAL, "eval")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_PROTOTYPE, "prototype")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_CONSTRUCTOR, "constructor")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_CALLER, "caller")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_CALLEE, "callee")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_UNDEFINED, "undefined")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_NULL, "null")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_FALSE, "false")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TRUE, "true")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_BOOLEAN, "boolean")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_NUMBER, "number")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_STRING, "string")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_OBJECT, "object")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_FUNCTION, "function")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_LENGTH, "length")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_NAN, "NaN")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_INFINITY_UL, "Infinity")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_UNDEFINED_UL, "Undefined")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_NULL_UL, "Null")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_OBJECT_UL, "Object")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_FUNCTION_UL, "Function")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_ARRAY_UL, "Array")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_ARGUMENTS_UL, "Arguments")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_STRING_UL, "String")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_BOOLEAN_UL, "Boolean")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_NUMBER_UL, "Number")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_DATE_UL, "Date")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_REG_EXP_UL, "RegExp")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_ERROR_UL, "Error")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_EVAL_ERROR_UL, "EvalError")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_RANGE_ERROR_UL, "RangeError")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_REFERENCE_ERROR_UL, "ReferenceError")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SYNTAX_ERROR_UL, "SyntaxError")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TYPE_ERROR_UL, "TypeError")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_URI_ERROR_UL, "URIError")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_MATH_UL, "Math")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_JSON_U, "JSON")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_PARSE_INT, "parseInt")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_PARSE_FLOAT, "parseFloat")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_IS_NAN, "isNaN")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_IS_FINITE, "isFinite")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_DECODE_URI, "decodeURI")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_DECODE_URI_COMPONENT, "decodeURIComponent")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_ENCODE_URI, "encodeURI")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_ENCODE_URI_COMPONENT, "encodeURIComponent")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_PROTOTYPE_OF_UL, "getPrototypeOf")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL, "getOwnPropertyDescriptor")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_OWN_PROPERTY_NAMES_UL, "getOwnPropertyNames")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_CREATE, "create")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_DEFINE_PROPERTY_UL, "defineProperty")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_DEFINE_PROPERTIES_UL, "defineProperties")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SEAL, "seal")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_FREEZE, "freeze")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_PREVENT_EXTENSIONS_UL, "preventExtensions")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_IS_SEALED_UL, "isSealed")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_IS_FROZEN_UL, "isFrozen")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_IS_EXTENSIBLE, "isExtensible")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_KEYS, "keys")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_WRITABLE, "writable")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_ENUMERABLE, "enumerable")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_CONFIGURABLE, "configurable")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_VALUE, "value")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET, "get")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SET, "set")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_E_U, "E")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_LN10_U, "LN10")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_LN2_U, "LN2")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_LOG2E_U, "LOG2E")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_LOG10E_U, "LOG10E")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_PI_U, "PI")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SQRT1_2_U, "SQRT1_2")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SQRT2_U, "SQRT2")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_ABS, "abs")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_ACOS, "acos")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_ASIN, "asin")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_ATAN, "atan")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_ATAN2, "atan2")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_CEIL, "ceil")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_COS, "cos")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_EXP, "exp")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_FLOOR, "floor")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_LOG, "log")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_MAX, "max")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_MIN, "min")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_POW, "pow")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_RANDOM, "random")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_ROUND, "round")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SIN, "sin")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SQRT, "sqrt")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TAN, "tan")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_FROM_CHAR_CODE_UL, "fromCharCode")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_IS_ARRAY_UL, "isArray")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TO_STRING_UL, "toString")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_VALUE_OF_UL, "valueOf")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TO_LOCALE_STRING_UL, "toLocaleString")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_HAS_OWN_PROPERTY_UL, "hasOwnProperty")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_IS_PROTOTYPE_OF_UL, "isPrototypeOf")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_PROPERTY_IS_ENUMERABLE_UL, "propertyIsEnumerable")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_CONCAT, "concat")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_POP, "pop")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_JOIN, "join")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_PUSH, "push")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_REVERSE, "reverse")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SHIFT, "shift")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SLICE, "slice")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SORT, "sort")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SPLICE, "splice")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_UNSHIFT, "unshift")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_INDEX_OF_UL, "indexOf")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_LAST_INDEX_OF_UL, "lastIndexOf")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_EVERY, "every")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SOME, "some")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_FOR_EACH_UL, "forEach")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_MAP, "map")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_FILTER, "filter")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_REDUCE, "reduce")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_REDUCE_RIGHT_UL, "reduceRight")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_CHAR_AT_UL, "charAt")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_CHAR_CODE_AT_UL, "charCodeAt")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_LOCALE_COMPARE_UL, "localeCompare")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_MATCH, "match")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_REPLACE, "replace")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SEARCH, "search")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SPLIT, "split")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SUBSTRING, "substring")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TO_LOWER_CASE_UL, "toLowerCase")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TO_LOCALE_LOWER_CASE_UL, "toLocaleLowerCase")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TO_UPPER_CASE_UL, "toUpperCase")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TO_LOCALE_UPPER_CASE_UL, "toLocaleUpperCase")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TRIM, "trim")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TO_FIXED_UL, "toFixed")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TO_EXPONENTIAL_UL, "toExponential")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TO_PRECISION_UL, "toPrecision")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TO_DATE_STRING_UL, "toDateString")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TO_TIME_STRING_UL, "toTimeString")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TO_LOCALE_DATE_STRING_UL, "toLocaleDateString")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TO_LOCALE_TIME_STRING_UL, "toLocaleTimeString")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_TIME_UL, "getTime")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_FULL_YEAR_UL, "getFullYear")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_UTC_FULL_YEAR_UL, "getUTCFullYear")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_MONTH_UL, "getMonth")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_UTC_MONTH_UL, "getUTCMonth")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_DATE_UL, "getDate")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_UTC_DATE_UL, "getUTCDate")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_DAY_UL, "getDay")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_UTC_DAY_UL, "getUTCDay")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_HOURS_UL, "getHours")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_UTC_HOURS_UL, "getUTCHours")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_MINUTES_UL, "getMinutes")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_UTC_MINUTES_UL, "getUTCMinutes")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_SECONDS_UL, "getSeconds")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_UTC_SECONDS_UL, "getUTCSeconds")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_MILLISECONDS_UL, "getMilliseconds")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_UTC_MILLISECONDS_UL, "getUTCMilliseconds")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_GET_TIMEZONE_OFFSET_UL, "getTimezoneOffset")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SET_TIME_UL, "setTime")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SET_MILLISECONDS_UL, "setMilliseconds")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SET_UTC_MILLISECONDS_UL, "setUTCMilliseconds")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SET_SECONDS_UL, "setSeconds")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SET_UTC_SECONDS_UL, "setUTCSeconds")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SET_MINUTES_UL, "setMinutes")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SET_UTC_MINUTES_UL, "setUTCMinutes")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SET_HOURS_UL, "setHours")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SET_UTC_HOURS_UL, "setUTCHours")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SET_DATE_UL, "setDate")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SET_UTC_DATE_UL, "setUTCDate")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SET_MONTH_UL, "setMonth")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SET_UTC_MONTH_UL, "setUTCMonth")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SET_FULL_YEAR_UL, "setFullYear")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SET_UTC_FULL_YEAR_UL, "setUTCFullYear")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TO_UTC_STRING_UL, "toUTCString")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TO_ISO_STRING_UL, "toISOString")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TO_JSON_UL, "toJSON")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_MAX_VALUE_U, "MAX_VALUE")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_MIN_VALUE_U, "MIN_VALUE")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_POSITIVE_INFINITY_U, "POSITIVE_INFINITY")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_NEGATIVE_INFINITY_U, "NEGATIVE_INFINITY")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_COMPACT_PROFILE_ERROR_UL, "CompactProfileError")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_APPLY, "apply")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_CALL, "call")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_BIND, "bind")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_EXEC, "exec")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_TEST, "test")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_NAME, "name")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_MESSAGE, "message")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_LEFT_SQUARE_CHAR, "[")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_RIGHT_SQUARE_CHAR, "]")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_COLON_CHAR, ":")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SPACE_CHAR, " ")
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING__EMPTY, "")
+283
View File
@@ -0,0 +1,283 @@
/* Copyright 2015 Samsung Electronics Co., Ltd.
*
* 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-helpers.h"
#include "ecma-stack.h"
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmastack ecma-stack
* @{
*/
/**
* Size of a ecma-stack frame's dynamic chunk
*/
#define ECMA_STACK_DYNAMIC_CHUNK_SIZE (mem_heap_recommend_allocation_size (sizeof (ecma_stack_chunk_header_t) + \
sizeof (ecma_value_t)))
/**
* Number of value slots in a ecma-stack frame's dynamic chunk
*/
#define ECMA_STACK_SLOTS_IN_DYNAMIC_CHUNK ((ECMA_STACK_DYNAMIC_CHUNK_SIZE - sizeof (ecma_stack_chunk_header_t)) / \
sizeof (ecma_value_t))
/**
* The top-most ecma-stack frame
*/
ecma_stack_frame_t* ecma_stack_top_frame_p;
/**
* Initialize ecma-stack
*/
void
ecma_stack_init (void)
{
ecma_stack_top_frame_p = NULL;
} /* ecma_stack_init */
/**
* Finalize ecma-stack
*/
void
ecma_stack_finalize ()
{
JERRY_ASSERT (ecma_stack_top_frame_p == NULL);
} /* ecma_stack_finalize */
/**
* Get ecma-stack's top frame
*
* @return pointer to the top frame descriptor
*/
ecma_stack_frame_t*
ecma_stack_get_top_frame (void)
{
return ecma_stack_top_frame_p;
} /* ecma_stack_get_top_frame */
/**
* Add the frame to ecma-stack
*/
void
ecma_stack_add_frame (ecma_stack_frame_t *frame_p, /**< frame to initialize */
ecma_value_t *regs_p, /**< array of register variables' values */
int32_t regs_num) /**< number of register variables */
{
frame_p->prev_frame_p = ecma_stack_top_frame_p;
ecma_stack_top_frame_p = frame_p;
frame_p->top_chunk_p = NULL;
frame_p->dynamically_allocated_value_slots_p = frame_p->inlined_values;
frame_p->current_slot_index = 0;
frame_p->regs_p = regs_p;
frame_p->regs_number = regs_num;
for (int32_t i = 0; i < regs_num; i++)
{
regs_p [i] = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
}
} /* ecma_stack_add_frame */
/**
* Free the ecma-stack frame
*
* Note:
* the frame should be the top-most frame
*/
void
ecma_stack_free_frame (ecma_stack_frame_t *frame_p) /**< frame to initialize */
{
/* the frame should be the top-most frame */
JERRY_ASSERT (ecma_stack_top_frame_p == frame_p);
ecma_stack_top_frame_p = frame_p->prev_frame_p;
while (frame_p->top_chunk_p != NULL)
{
ecma_stack_pop (frame_p);
}
for (int32_t reg_index = 0;
reg_index < frame_p->regs_number;
reg_index++)
{
ecma_free_value (frame_p->regs_p [reg_index], false);
}
} /* ecma_stack_free_frame */
/**
* Get value of specified register variable
*
* @return ecma-value
*/
ecma_value_t
ecma_stack_frame_get_reg_value (ecma_stack_frame_t *frame_p, /**< frame */
int32_t reg_index) /**< index of register variable */
{
JERRY_ASSERT (reg_index >= 0 && reg_index < frame_p->regs_number);
return frame_p->regs_p [reg_index];
} /* ecma_stack_frame_get_reg_value */
/**
* Set value of specified register variable
*/
void
ecma_stack_frame_set_reg_value (ecma_stack_frame_t *frame_p, /**< frame */
int32_t reg_index, /**< index of register variable */
ecma_value_t value) /**< ecma-value */
{
JERRY_ASSERT (reg_index >= 0 && reg_index < frame_p->regs_number);
frame_p->regs_p [reg_index] = value;
} /* ecma_stack_frame_set_reg_value */
/**
* Calculate number of value slots in the top-most chunk of the frame
*
* @return number of value slots
*/
static size_t
ecma_stack_slots_in_top_chunk (ecma_stack_frame_t *frame_p) /**< ecma-stack frame */
{
return ((frame_p->top_chunk_p == NULL) ? ECMA_STACK_FRAME_INLINED_VALUES_NUMBER : ECMA_STACK_SLOTS_IN_DYNAMIC_CHUNK);
} /* ecma_stack_slots_in_top_chunk */
/**
* Longpath for ecma_stack_push_value (for case current chunk may be doesn't have free slots)
*/
static void __attr_noinline___
ecma_stack_push_value_longpath (ecma_stack_frame_t *frame_p) /**< ecma-stack frame */
{
JERRY_ASSERT (frame_p->current_slot_index >= JERRY_MIN (ECMA_STACK_FRAME_INLINED_VALUES_NUMBER,
ECMA_STACK_SLOTS_IN_DYNAMIC_CHUNK));
const size_t slots_in_top_chunk = ecma_stack_slots_in_top_chunk (frame_p);
if (frame_p->current_slot_index == slots_in_top_chunk)
{
ecma_stack_chunk_header_t *chunk_p;
chunk_p = (ecma_stack_chunk_header_t *) mem_heap_alloc_block (ECMA_STACK_DYNAMIC_CHUNK_SIZE,
MEM_HEAP_ALLOC_SHORT_TERM);
ECMA_SET_POINTER (chunk_p->prev_chunk_p, frame_p->top_chunk_p);
frame_p->top_chunk_p = chunk_p;
frame_p->dynamically_allocated_value_slots_p = (ecma_value_t*) (frame_p->top_chunk_p + 1);
frame_p->current_slot_index = 0;
}
} /* ecma_stack_push_value_longpath */
/**
* Push ecma-value to ecma-stack
*/
void
ecma_stack_push_value (ecma_stack_frame_t *frame_p, /**< ecma-stack frame */
ecma_value_t value) /**< ecma-value */
{
frame_p->current_slot_index++;
if (frame_p->current_slot_index >= JERRY_MIN (ECMA_STACK_FRAME_INLINED_VALUES_NUMBER,
ECMA_STACK_SLOTS_IN_DYNAMIC_CHUNK))
{
ecma_stack_push_value_longpath (frame_p);
}
JERRY_ASSERT (frame_p->current_slot_index < ecma_stack_slots_in_top_chunk (frame_p));
frame_p->dynamically_allocated_value_slots_p [frame_p->current_slot_index] = value;
} /* ecma_stack_push_value */
/**
* Get top value from ecma-stack
*/
ecma_value_t __attr_always_inline___
ecma_stack_top_value (ecma_stack_frame_t *frame_p) /**< ecma-stack frame */
{
const size_t slots_in_top_chunk = ecma_stack_slots_in_top_chunk (frame_p);
JERRY_ASSERT (frame_p->current_slot_index < slots_in_top_chunk);
return frame_p->dynamically_allocated_value_slots_p [frame_p->current_slot_index];
} /* ecma_stack_top_value */
/**
* Longpath for ecma_stack_pop (for case a dynamically allocated chunk needs to be deallocated)
*/
static void __attr_noinline___
ecma_stack_pop_longpath (ecma_stack_frame_t *frame_p) /**< ecma-stack frame */
{
JERRY_ASSERT (frame_p->current_slot_index == 0 && frame_p->top_chunk_p != NULL);
ecma_stack_chunk_header_t *chunk_to_free_p = frame_p->top_chunk_p;
frame_p->top_chunk_p = ECMA_GET_POINTER (ecma_stack_chunk_header_t,
frame_p->top_chunk_p->prev_chunk_p);
if (frame_p->top_chunk_p != NULL)
{
frame_p->dynamically_allocated_value_slots_p = (ecma_value_t*) (frame_p->top_chunk_p + 1);
frame_p->current_slot_index = (uint32_t) (ECMA_STACK_SLOTS_IN_DYNAMIC_CHUNK - 1u);
}
else
{
frame_p->dynamically_allocated_value_slots_p = frame_p->inlined_values;
frame_p->current_slot_index = (uint32_t) (ECMA_STACK_FRAME_INLINED_VALUES_NUMBER - 1u);
}
mem_heap_free_block (chunk_to_free_p);
} /* ecma_stack_pop_longpath */
/**
* Pop top value from ecma-stack and free it
*/
void
ecma_stack_pop (ecma_stack_frame_t *frame_p) /**< ecma-stack frame */
{
JERRY_ASSERT (frame_p->current_slot_index < ecma_stack_slots_in_top_chunk (frame_p));
ecma_value_t value = ecma_stack_top_value (frame_p);
if (unlikely (frame_p->current_slot_index == 0
&& frame_p->top_chunk_p != NULL))
{
ecma_stack_pop_longpath (frame_p);
}
else
{
frame_p->current_slot_index--;
}
ecma_free_value (value, true);
} /* ecma_stack_pop */
/**
* Pop multiple top values from ecma-stack and free them
*/
void
ecma_stack_pop_multiple (ecma_stack_frame_t *frame_p, /**< ecma-stack frame */
uint32_t number) /**< number of elements to pop */
{
for (uint32_t i = 0; i < number; i++)
{
ecma_stack_pop (frame_p);
}
} /* ecma_stack_pop_multiple */
/**
* @}
* @}
*/
+80
View File
@@ -0,0 +1,80 @@
/* Copyright 2015 Samsung Electronics Co., Ltd.
*
* 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.
*/
#ifndef ECMA_STACK_H
#define ECMA_STACK_H
#include "config.h"
#include "ecma-globals.h"
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmastack ECMA stack
* @{
*/
/**
* Number of ecma-values inlined into stack frame
*/
#define ECMA_STACK_FRAME_INLINED_VALUES_NUMBER CONFIG_ECMA_STACK_FRAME_INLINED_VALUES_NUMBER
/**
* Header of a ECMA stack frame's chunk
*/
typedef struct
{
uint16_t prev_chunk_p; /**< previous chunk of same frame */
} ecma_stack_chunk_header_t;
/**
* ECMA stack frame
*/
typedef struct ecma_stack_frame_t
{
struct ecma_stack_frame_t *prev_frame_p; /**< previous frame */
ecma_stack_chunk_header_t *top_chunk_p; /**< the top-most chunk of the frame */
ecma_value_t *dynamically_allocated_value_slots_p; /**< pointer to dynamically allocated value slots
* in the top-most chunk */
uint32_t current_slot_index; /**< index of first free slot in the top chunk */
ecma_value_t inlined_values [ECMA_STACK_FRAME_INLINED_VALUES_NUMBER]; /**< place for values inlined in stack frame
* (instead of being dynamically allocated
* on the heap) */
ecma_value_t *regs_p; /**< register variables */
int32_t regs_number; /**< number of register variables */
} ecma_stack_frame_t;
extern void ecma_stack_init (void);
extern void ecma_stack_finalize (void);
extern ecma_stack_frame_t*
ecma_stack_get_top_frame (void);
extern void
ecma_stack_add_frame (ecma_stack_frame_t *frame_p,
ecma_value_t *regs_p,
int32_t regs_num);
extern void ecma_stack_free_frame (ecma_stack_frame_t *frame_p);
extern ecma_value_t ecma_stack_frame_get_reg_value (ecma_stack_frame_t *frame_p, int32_t reg_index);
extern void ecma_stack_frame_set_reg_value (ecma_stack_frame_t *frame_p, int32_t reg_index, ecma_value_t value);
extern void ecma_stack_push_value (ecma_stack_frame_t *frame_p, ecma_value_t value);
extern ecma_value_t ecma_stack_top_value (ecma_stack_frame_t *frame_p);
extern void ecma_stack_pop (ecma_stack_frame_t *frame_p);
extern void ecma_stack_pop_multiple (ecma_stack_frame_t *frame_p, uint32_t number);
/**
* @}
* @}
*/
#endif /* !ECMA_STACK_H */