mirror of
https://github.com/google/pebble.git
synced 2025-07-15 18:46:41 -04:00
Import of the watch repository from Pebble
This commit is contained in:
commit
3b92768480
10334 changed files with 2564465 additions and 0 deletions
132
third_party/jerryscript/jerry-core/ecma/base/ecma-alloc.c
vendored
Normal file
132
third_party/jerryscript/jerry-core/ecma/base/ecma-alloc.c
vendored
Normal file
|
@ -0,0 +1,132 @@
|
|||
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
|
||||
* Copyright 2016 University of Szeged.
|
||||
*
|
||||
* 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 "jmem-poolman.h"
|
||||
|
||||
JERRY_STATIC_ASSERT (sizeof (ecma_property_value_t) == sizeof (ecma_value_t),
|
||||
size_of_ecma_property_value_t_must_be_equal_to_size_of_ecma_value_t);
|
||||
JERRY_STATIC_ASSERT (((sizeof (ecma_property_value_t) - 1) & sizeof (ecma_property_value_t)) == 0,
|
||||
size_of_ecma_property_value_t_must_be_power_of_2);
|
||||
|
||||
JERRY_STATIC_ASSERT (sizeof (ecma_string_t) == sizeof (uint64_t),
|
||||
size_of_ecma_string_t_must_be_less_than_or_equal_to_8_bytes);
|
||||
|
||||
/** \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 *ecma_type ## _p; \
|
||||
ecma_type ## _p = (ecma_ ## ecma_type ## _t *) jmem_pools_alloc (sizeof (ecma_ ## ecma_type ## _t)); \
|
||||
\
|
||||
JERRY_ASSERT (ecma_type ## _p != NULL); \
|
||||
\
|
||||
return ecma_type ## _p; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Deallocation routine template
|
||||
*/
|
||||
#define DEALLOC(ecma_type) void \
|
||||
ecma_dealloc_ ## ecma_type (ecma_ ## ecma_type ## _t *ecma_type ## _p) \
|
||||
{ \
|
||||
jmem_pools_free ((uint8_t *) ecma_type ## _p, sizeof (ecma_ ## ecma_type ## _t)); \
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (number)
|
||||
DECLARE_ROUTINES_FOR (collection_header)
|
||||
DECLARE_ROUTINES_FOR (collection_chunk)
|
||||
DECLARE_ROUTINES_FOR (string)
|
||||
DECLARE_ROUTINES_FOR (getter_setter_pointers)
|
||||
DECLARE_ROUTINES_FOR (external_pointer)
|
||||
|
||||
/**
|
||||
* Allocate memory for extended object
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
inline ecma_extended_object_t * __attr_always_inline___
|
||||
ecma_alloc_extended_object (void)
|
||||
{
|
||||
return jmem_heap_alloc_block (sizeof (ecma_extended_object_t));
|
||||
} /* ecma_alloc_extended_object */
|
||||
|
||||
/**
|
||||
* Dealloc memory of an extended object
|
||||
*/
|
||||
inline void __attr_always_inline___
|
||||
ecma_dealloc_extended_object (ecma_extended_object_t *ext_object_p) /**< property pair to be freed */
|
||||
{
|
||||
jmem_heap_free_block (ext_object_p, sizeof (ecma_extended_object_t));
|
||||
} /* ecma_dealloc_extended_object */
|
||||
|
||||
/**
|
||||
* Allocate memory for ecma-property pair
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
inline ecma_property_pair_t * __attr_always_inline___
|
||||
ecma_alloc_property_pair (void)
|
||||
{
|
||||
return jmem_heap_alloc_block (sizeof (ecma_property_pair_t));
|
||||
} /* ecma_alloc_property_pair */
|
||||
|
||||
/**
|
||||
* Dealloc memory of an ecma-property
|
||||
*/
|
||||
inline void __attr_always_inline___
|
||||
ecma_dealloc_property_pair (ecma_property_pair_t *property_pair_p) /**< property pair to be freed */
|
||||
{
|
||||
jmem_heap_free_block (property_pair_p, sizeof (ecma_property_pair_t));
|
||||
} /* ecma_dealloc_property_pair */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
141
third_party/jerryscript/jerry-core/ecma/base/ecma-alloc.h
vendored
Normal file
141
third_party/jerryscript/jerry-core/ecma/base/ecma-alloc.h
vendored
Normal file
|
@ -0,0 +1,141 @@
|
|||
/* Copyright 2014-2016 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_ALLOC_H
|
||||
#define ECMA_ALLOC_H
|
||||
|
||||
#include "ecma-globals.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmaalloc Routines for allocation/freeing memory for ECMA data types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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 *);
|
||||
|
||||
/**
|
||||
* 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 *);
|
||||
|
||||
/**
|
||||
* 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 *);
|
||||
|
||||
/**
|
||||
* 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 *);
|
||||
|
||||
/**
|
||||
* 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 *);
|
||||
|
||||
/**
|
||||
* Allocate memory for getter-setter pointer pair
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
extern ecma_getter_setter_pointers_t *ecma_alloc_getter_setter_pointers (void);
|
||||
|
||||
/**
|
||||
* Dealloc memory from getter-setter pointer pair
|
||||
*/
|
||||
extern void ecma_dealloc_getter_setter_pointers (ecma_getter_setter_pointers_t *);
|
||||
|
||||
/**
|
||||
* Allocate memory for external pointer
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
extern ecma_external_pointer_t *ecma_alloc_external_pointer (void);
|
||||
|
||||
/**
|
||||
* Dealloc memory from external pointer
|
||||
*/
|
||||
extern void ecma_dealloc_external_pointer (ecma_external_pointer_t *);
|
||||
|
||||
/*
|
||||
* Allocate memory for extended object
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
extern ecma_extended_object_t *ecma_alloc_extended_object (void);
|
||||
|
||||
/**
|
||||
* Dealloc memory of an extended object
|
||||
*/
|
||||
extern void ecma_dealloc_extended_object (ecma_extended_object_t *);
|
||||
|
||||
/**
|
||||
* Allocate memory for ecma-property pair
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
extern ecma_property_pair_t *ecma_alloc_property_pair (void);
|
||||
|
||||
/**
|
||||
* Dealloc memory from an ecma-property pair
|
||||
*/
|
||||
extern void ecma_dealloc_property_pair (ecma_property_pair_t *);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* !ECMA_ALLOC_H */
|
615
third_party/jerryscript/jerry-core/ecma/base/ecma-gc.c
vendored
Normal file
615
third_party/jerryscript/jerry-core/ecma/base/ecma-gc.c
vendored
Normal file
|
@ -0,0 +1,615 @@
|
|||
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
|
||||
* Copyright 2016 University of Szeged.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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-property-hashmap.h"
|
||||
#include "jcontext.h"
|
||||
#include "jrt.h"
|
||||
#include "jrt-libc-includes.h"
|
||||
#include "jrt-bit-fields.h"
|
||||
#include "re-compiler.h"
|
||||
#include "vm-defines.h"
|
||||
#include "vm-stack.h"
|
||||
|
||||
#define JERRY_INTERNAL
|
||||
#include "jerry-internal.h"
|
||||
|
||||
/* TODO: Extract GC to a separate component */
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmagc Garbage collector
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Current state of an object's visited flag that
|
||||
* indicates whether the object is in visited state:
|
||||
*
|
||||
* visited_field | visited_flip_flag | real_value
|
||||
* false | false | false
|
||||
* false | true | true
|
||||
* true | false | true
|
||||
* true | true | false
|
||||
*/
|
||||
|
||||
static void ecma_gc_mark (ecma_object_t *object_p);
|
||||
static void ecma_gc_sweep (ecma_object_t *object_p);
|
||||
|
||||
/**
|
||||
* Get next object in list of objects with same generation.
|
||||
*/
|
||||
static inline ecma_object_t *
|
||||
ecma_gc_get_object_next (ecma_object_t *object_p) /**< object */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
|
||||
return ECMA_GET_POINTER (ecma_object_t, object_p->gc_next_cp);
|
||||
} /* ecma_gc_get_object_next */
|
||||
|
||||
/**
|
||||
* Set next object in list of objects with same generation.
|
||||
*/
|
||||
static inline 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);
|
||||
|
||||
ECMA_SET_POINTER (object_p->gc_next_cp, next_object_p);
|
||||
} /* ecma_gc_set_object_next */
|
||||
|
||||
/**
|
||||
* Get visited flag of the object.
|
||||
*/
|
||||
static inline bool
|
||||
ecma_gc_is_object_visited (ecma_object_t *object_p) /**< object */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
|
||||
bool flag_value = (object_p->type_flags_refs & ECMA_OBJECT_FLAG_GC_VISITED) != 0;
|
||||
|
||||
return flag_value != JERRY_CONTEXT (ecma_gc_visited_flip_flag);
|
||||
} /* ecma_gc_is_object_visited */
|
||||
|
||||
/**
|
||||
* Set visited flag of the object.
|
||||
*/
|
||||
static inline void
|
||||
ecma_gc_set_object_visited (ecma_object_t *object_p, /**< object */
|
||||
bool is_visited) /**< flag value */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
|
||||
if (is_visited != JERRY_CONTEXT (ecma_gc_visited_flip_flag))
|
||||
{
|
||||
object_p->type_flags_refs = (uint16_t) (object_p->type_flags_refs | ECMA_OBJECT_FLAG_GC_VISITED);
|
||||
}
|
||||
else
|
||||
{
|
||||
object_p->type_flags_refs = (uint16_t) (object_p->type_flags_refs & ~ECMA_OBJECT_FLAG_GC_VISITED);
|
||||
}
|
||||
} /* ecma_gc_set_object_visited */
|
||||
|
||||
/**
|
||||
* Initialize GC information for the object
|
||||
*/
|
||||
inline void
|
||||
ecma_init_gc_info (ecma_object_t *object_p) /**< object */
|
||||
{
|
||||
JERRY_CONTEXT (ecma_gc_objects_number)++;
|
||||
JERRY_CONTEXT (ecma_gc_new_objects)++;
|
||||
|
||||
JERRY_ASSERT (JERRY_CONTEXT (ecma_gc_new_objects) <= JERRY_CONTEXT (ecma_gc_objects_number));
|
||||
|
||||
JERRY_ASSERT (object_p->type_flags_refs < ECMA_OBJECT_REF_ONE);
|
||||
object_p->type_flags_refs = (uint16_t) (object_p->type_flags_refs | ECMA_OBJECT_REF_ONE);
|
||||
|
||||
ecma_gc_set_object_next (object_p, JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY]);
|
||||
JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY] = object_p;
|
||||
|
||||
/* Should be set to false at the beginning of garbage collection */
|
||||
ecma_gc_set_object_visited (object_p, false);
|
||||
} /* ecma_init_gc_info */
|
||||
|
||||
/**
|
||||
* Increase reference counter of an object
|
||||
*/
|
||||
void
|
||||
ecma_ref_object (ecma_object_t *object_p) /**< object */
|
||||
{
|
||||
if (likely (object_p->type_flags_refs < ECMA_OBJECT_MAX_REF))
|
||||
{
|
||||
object_p->type_flags_refs = (uint16_t) (object_p->type_flags_refs + ECMA_OBJECT_REF_ONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
jerry_fatal (ERR_REF_COUNT_LIMIT);
|
||||
}
|
||||
} /* ecma_ref_object */
|
||||
|
||||
/**
|
||||
* Decrease reference counter of an object
|
||||
*/
|
||||
void
|
||||
ecma_deref_object (ecma_object_t *object_p) /**< object */
|
||||
{
|
||||
JERRY_ASSERT (object_p->type_flags_refs >= ECMA_OBJECT_REF_ONE);
|
||||
object_p->type_flags_refs = (uint16_t) (object_p->type_flags_refs - ECMA_OBJECT_REF_ONE);
|
||||
} /* ecma_deref_object */
|
||||
|
||||
/**
|
||||
* Mark referenced object from property
|
||||
*/
|
||||
static void
|
||||
ecma_gc_mark_property (ecma_property_t *property_p) /**< property */
|
||||
{
|
||||
switch (ECMA_PROPERTY_GET_TYPE (*property_p))
|
||||
{
|
||||
case ECMA_PROPERTY_TYPE_NAMEDDATA:
|
||||
{
|
||||
ecma_value_t value = ECMA_PROPERTY_VALUE_PTR (property_p)->value;
|
||||
|
||||
if (ecma_is_value_object (value))
|
||||
{
|
||||
ecma_object_t *value_obj_p = ecma_get_object_from_value (value);
|
||||
|
||||
ecma_gc_set_object_visited (value_obj_p, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ECMA_PROPERTY_TYPE_NAMEDACCESSOR:
|
||||
{
|
||||
ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
ecma_object_t *getter_obj_p = ecma_get_named_accessor_property_getter (prop_value_p);
|
||||
ecma_object_t *setter_obj_p = ecma_get_named_accessor_property_setter (prop_value_p);
|
||||
|
||||
if (getter_obj_p != NULL)
|
||||
{
|
||||
ecma_gc_set_object_visited (getter_obj_p, true);
|
||||
}
|
||||
|
||||
if (setter_obj_p != NULL)
|
||||
{
|
||||
ecma_gc_set_object_visited (setter_obj_p, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ECMA_PROPERTY_TYPE_INTERNAL:
|
||||
{
|
||||
uint32_t property_value = ECMA_PROPERTY_VALUE_PTR (property_p)->value;
|
||||
|
||||
switch (ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (property_p))
|
||||
{
|
||||
case ECMA_INTERNAL_PROPERTY_ECMA_VALUE: /* an ecma_value_t except object */
|
||||
case ECMA_INTERNAL_PROPERTY_DATE_FLOAT: /* pointer to a ecma_number_t */
|
||||
case ECMA_INTERNAL_PROPERTY_CLASS: /* an enum */
|
||||
case ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE: /* pointer to a regexp bytecode array */
|
||||
case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* an external pointer */
|
||||
case ECMA_INTERNAL_PROPERTY_FREE_CALLBACK: /* an object's native free callback */
|
||||
case ECMA_INTERNAL_PROPERTY_INSTANTIATED_MASK_32_63: /* an integer (bit-mask) */
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS: /* an ecma value */
|
||||
{
|
||||
if (ecma_is_value_object (property_value))
|
||||
{
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (property_value);
|
||||
|
||||
ecma_gc_set_object_visited (obj_p, true);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS: /* a collection of ecma values */
|
||||
{
|
||||
ecma_collection_header_t *bound_arg_list_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_header_t,
|
||||
property_value);
|
||||
|
||||
ecma_collection_iterator_t bound_args_iterator;
|
||||
ecma_collection_iterator_init (&bound_args_iterator, bound_arg_list_p);
|
||||
|
||||
for (ecma_length_t i = 0; i < bound_arg_list_p->unit_number; i++)
|
||||
{
|
||||
bool is_moved = ecma_collection_iterator_next (&bound_args_iterator);
|
||||
JERRY_ASSERT (is_moved);
|
||||
|
||||
if (ecma_is_value_object (*bound_args_iterator.current_value_p))
|
||||
{
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (*bound_args_iterator.current_value_p);
|
||||
|
||||
ecma_gc_set_object_visited (obj_p, true);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION: /* an object */
|
||||
case ECMA_INTERNAL_PROPERTY_SCOPE: /* a lexical environment */
|
||||
case ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP: /* an object */
|
||||
{
|
||||
ecma_object_t *obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, property_value);
|
||||
|
||||
ecma_gc_set_object_visited (obj_p, true);
|
||||
|
||||
break;
|
||||
}
|
||||
case ECMA_INTERNAL_PROPERTY__COUNT: /* not a real internal property type,
|
||||
* but number of the real internal property types */
|
||||
{
|
||||
JERRY_UNREACHABLE ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
JERRY_UNREACHABLE ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /* ecma_gc_mark_property */
|
||||
|
||||
/**
|
||||
* Mark objects as visited starting from specified object as root
|
||||
*/
|
||||
void
|
||||
ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
JERRY_ASSERT (ecma_gc_is_object_visited (object_p));
|
||||
|
||||
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)
|
||||
{
|
||||
ecma_gc_set_object_visited (lex_env_p, true);
|
||||
}
|
||||
|
||||
if (ecma_get_lex_env_type (object_p) != ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
||||
{
|
||||
ecma_object_t *binding_object_p = ecma_get_lex_env_binding_object (object_p);
|
||||
ecma_gc_set_object_visited (binding_object_p, true);
|
||||
|
||||
traverse_properties = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_object_t *proto_p = ecma_get_object_prototype (object_p);
|
||||
if (proto_p != NULL)
|
||||
{
|
||||
ecma_gc_set_object_visited (proto_p, true);
|
||||
}
|
||||
|
||||
if (!ecma_get_object_is_builtin (object_p)
|
||||
&& ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION)
|
||||
{
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
ecma_object_t *scope_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
ext_func_p->u.function.scope_cp);
|
||||
|
||||
ecma_gc_set_object_visited (scope_p, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (traverse_properties)
|
||||
{
|
||||
ecma_property_header_t *prop_iter_p = ecma_get_property_list (object_p);
|
||||
|
||||
if (prop_iter_p != NULL
|
||||
&& ECMA_PROPERTY_GET_TYPE (prop_iter_p->types[0]) == ECMA_PROPERTY_TYPE_HASHMAP)
|
||||
{
|
||||
prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t,
|
||||
prop_iter_p->next_property_cp);
|
||||
}
|
||||
|
||||
while (prop_iter_p != NULL)
|
||||
{
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));
|
||||
|
||||
if (prop_iter_p->types[0] != ECMA_PROPERTY_TYPE_DELETED)
|
||||
{
|
||||
ecma_gc_mark_property (prop_iter_p->types + 0);
|
||||
}
|
||||
|
||||
if (prop_iter_p->types[1] != ECMA_PROPERTY_TYPE_DELETED)
|
||||
{
|
||||
ecma_gc_mark_property (prop_iter_p->types + 1);
|
||||
}
|
||||
|
||||
prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t,
|
||||
prop_iter_p->next_property_cp);
|
||||
}
|
||||
}
|
||||
} /* 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)
|
||||
&& object_p->type_flags_refs < ECMA_OBJECT_REF_ONE);
|
||||
|
||||
if (!ecma_is_lexical_environment (object_p))
|
||||
{
|
||||
/* if the object provides free callback, invoke it with handle stored in the object */
|
||||
|
||||
ecma_external_pointer_t freecb_p;
|
||||
ecma_external_pointer_t native_p;
|
||||
|
||||
bool is_retrieved = ecma_get_external_pointer_value (object_p,
|
||||
ECMA_INTERNAL_PROPERTY_FREE_CALLBACK,
|
||||
&freecb_p);
|
||||
|
||||
if (is_retrieved && ((jerry_object_free_callback_t) freecb_p) != NULL)
|
||||
{
|
||||
is_retrieved = ecma_get_external_pointer_value (object_p,
|
||||
ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE,
|
||||
&native_p);
|
||||
JERRY_ASSERT (is_retrieved);
|
||||
|
||||
jerry_dispatch_object_free_callback (freecb_p, native_p);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ecma_is_lexical_environment (object_p)
|
||||
|| ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
||||
{
|
||||
ecma_property_header_t *prop_iter_p = ecma_get_property_list (object_p);
|
||||
|
||||
if (prop_iter_p != NULL
|
||||
&& ECMA_PROPERTY_GET_TYPE (prop_iter_p->types[0]) == ECMA_PROPERTY_TYPE_HASHMAP)
|
||||
{
|
||||
ecma_property_hashmap_free (object_p);
|
||||
prop_iter_p = ecma_get_property_list (object_p);
|
||||
}
|
||||
|
||||
while (prop_iter_p != NULL)
|
||||
{
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));
|
||||
|
||||
/* Both cannot be deleted. */
|
||||
JERRY_ASSERT (prop_iter_p->types[0] != ECMA_PROPERTY_TYPE_DELETED
|
||||
|| prop_iter_p->types[1] != ECMA_PROPERTY_TYPE_DELETED);
|
||||
|
||||
ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p;
|
||||
|
||||
for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
|
||||
{
|
||||
if (prop_iter_p->types[i] != ECMA_PROPERTY_TYPE_DELETED)
|
||||
{
|
||||
ecma_string_t *name_p = ECMA_GET_POINTER (ecma_string_t, prop_pair_p->names_cp[i]);
|
||||
|
||||
ecma_free_property (object_p, name_p, prop_iter_p->types + i);
|
||||
|
||||
if (name_p != NULL)
|
||||
{
|
||||
ecma_deref_ecma_string (name_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Both must be deleted. */
|
||||
JERRY_ASSERT (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_DELETED
|
||||
&& prop_iter_p->types[1] == ECMA_PROPERTY_TYPE_DELETED);
|
||||
|
||||
prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t,
|
||||
prop_iter_p->next_property_cp);
|
||||
|
||||
ecma_dealloc_property_pair (prop_pair_p);
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_ASSERT (JERRY_CONTEXT (ecma_gc_objects_number) > 0);
|
||||
JERRY_CONTEXT (ecma_gc_objects_number)--;
|
||||
|
||||
if (!ecma_is_lexical_environment (object_p))
|
||||
{
|
||||
if (ecma_get_object_is_builtin (object_p)
|
||||
|| ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION)
|
||||
{
|
||||
ecma_dealloc_extended_object ((ecma_extended_object_t *) object_p);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION)
|
||||
{
|
||||
/* Function with byte-code (not a built-in function). */
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
ecma_bytecode_deref (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t,
|
||||
ext_func_p->u.function.bytecode_cp));
|
||||
|
||||
ecma_dealloc_extended_object (ext_func_p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ecma_dealloc_object (object_p);
|
||||
} /* ecma_gc_sweep */
|
||||
|
||||
/**
|
||||
* Run garbage collection
|
||||
*/
|
||||
void
|
||||
ecma_gc_run (jmem_free_unused_memory_severity_t severity) /**< gc severity */
|
||||
{
|
||||
JERRY_CONTEXT (ecma_gc_new_objects) = 0;
|
||||
|
||||
JERRY_ASSERT (JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_BLACK] == NULL);
|
||||
|
||||
/* if some object is referenced from stack or globals (i.e. it is root), mark it */
|
||||
for (ecma_object_t *obj_iter_p = JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY];
|
||||
obj_iter_p != NULL;
|
||||
obj_iter_p = ecma_gc_get_object_next (obj_iter_p))
|
||||
{
|
||||
JERRY_ASSERT (!ecma_gc_is_object_visited (obj_iter_p));
|
||||
|
||||
if (obj_iter_p->type_flags_refs >= ECMA_OBJECT_REF_ONE)
|
||||
{
|
||||
ecma_gc_set_object_visited (obj_iter_p, true);
|
||||
}
|
||||
}
|
||||
|
||||
bool marked_anything_during_current_iteration = false;
|
||||
|
||||
do
|
||||
{
|
||||
marked_anything_during_current_iteration = false;
|
||||
|
||||
ecma_object_t *obj_prev_p = NULL;
|
||||
ecma_object_t *obj_iter_p = JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY];
|
||||
|
||||
while (obj_iter_p != NULL)
|
||||
{
|
||||
ecma_object_t *obj_next_p = ecma_gc_get_object_next (obj_iter_p);
|
||||
|
||||
if (ecma_gc_is_object_visited (obj_iter_p))
|
||||
{
|
||||
/* Moving the object to list of marked objects */
|
||||
ecma_gc_set_object_next (obj_iter_p, JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_BLACK]);
|
||||
JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_BLACK] = obj_iter_p;
|
||||
|
||||
if (likely (obj_prev_p != NULL))
|
||||
{
|
||||
JERRY_ASSERT (ecma_gc_get_object_next (obj_prev_p) == obj_iter_p);
|
||||
|
||||
ecma_gc_set_object_next (obj_prev_p, obj_next_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY] = obj_next_p;
|
||||
}
|
||||
|
||||
ecma_gc_mark (obj_iter_p);
|
||||
marked_anything_during_current_iteration = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
obj_prev_p = obj_iter_p;
|
||||
}
|
||||
|
||||
obj_iter_p = obj_next_p;
|
||||
}
|
||||
}
|
||||
while (marked_anything_during_current_iteration);
|
||||
|
||||
/* Sweeping objects that are currently unmarked */
|
||||
ecma_object_t *obj_iter_p = JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY];
|
||||
|
||||
while (obj_iter_p != NULL)
|
||||
{
|
||||
ecma_object_t *obj_next_p = ecma_gc_get_object_next (obj_iter_p);
|
||||
|
||||
JERRY_ASSERT (!ecma_gc_is_object_visited (obj_iter_p));
|
||||
|
||||
ecma_gc_sweep (obj_iter_p);
|
||||
obj_iter_p = obj_next_p;
|
||||
}
|
||||
|
||||
if (severity == JMEM_FREE_UNUSED_MEMORY_SEVERITY_HIGH)
|
||||
{
|
||||
/* Remove the property hashmap of BLACK objects */
|
||||
obj_iter_p = JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_BLACK];
|
||||
|
||||
while (obj_iter_p != NULL)
|
||||
{
|
||||
JERRY_ASSERT (ecma_gc_is_object_visited (obj_iter_p));
|
||||
|
||||
if (!ecma_is_lexical_environment (obj_iter_p)
|
||||
|| ecma_get_lex_env_type (obj_iter_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
||||
{
|
||||
ecma_property_header_t *prop_iter_p = ecma_get_property_list (obj_iter_p);
|
||||
if (prop_iter_p != NULL
|
||||
&& ECMA_PROPERTY_GET_TYPE (prop_iter_p->types[0]) == ECMA_PROPERTY_TYPE_HASHMAP)
|
||||
{
|
||||
ecma_property_hashmap_free (obj_iter_p);
|
||||
}
|
||||
}
|
||||
|
||||
obj_iter_p = ecma_gc_get_object_next (obj_iter_p);
|
||||
}
|
||||
}
|
||||
|
||||
/* Unmarking all objects */
|
||||
ecma_object_t *black_objects = JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_BLACK];
|
||||
JERRY_CONTEXT (ecma_gc_objects_lists)[ECMA_GC_COLOR_WHITE_GRAY] = black_objects;
|
||||
JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_BLACK] = NULL;
|
||||
|
||||
JERRY_CONTEXT (ecma_gc_visited_flip_flag) = !JERRY_CONTEXT (ecma_gc_visited_flip_flag);
|
||||
|
||||
#ifndef CONFIG_DISABLE_REGEXP_BUILTIN
|
||||
/* Free RegExp bytecodes stored in cache */
|
||||
re_cache_gc_run ();
|
||||
#endif /* !CONFIG_DISABLE_REGEXP_BUILTIN */
|
||||
} /* ecma_gc_run */
|
||||
|
||||
/**
|
||||
* Try to free some memory (depending on severity).
|
||||
*/
|
||||
void
|
||||
ecma_free_unused_memory (jmem_free_unused_memory_severity_t severity, /**< severity of the request */
|
||||
size_t requested_size_bytes, /**< number of bytes to be allocated */
|
||||
bool fatal_if_not_freed) /**< run-time will terminate if not enough memory is freed */
|
||||
{
|
||||
if (severity == JMEM_FREE_UNUSED_MEMORY_SEVERITY_LOW)
|
||||
{
|
||||
/*
|
||||
* If there is enough newly allocated objects since last GC, probably it is worthwhile to start GC now.
|
||||
* Otherwise, probability to free sufficient space is considered to be low.
|
||||
*/
|
||||
size_t new_objects_share = CONFIG_ECMA_GC_NEW_OBJECTS_SHARE_TO_START_GC;
|
||||
|
||||
if (JERRY_CONTEXT (ecma_gc_new_objects) * new_objects_share > JERRY_CONTEXT (ecma_gc_objects_number))
|
||||
{
|
||||
ecma_gc_run (severity);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (severity == JMEM_FREE_UNUSED_MEMORY_SEVERITY_HIGH);
|
||||
|
||||
/* Freeing as much memory as we currently can */
|
||||
ecma_gc_run (severity);
|
||||
}
|
||||
} /* ecma_free_unused_memory */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
40
third_party/jerryscript/jerry-core/ecma/base/ecma-gc.h
vendored
Normal file
40
third_party/jerryscript/jerry-core/ecma/base/ecma-gc.h
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
/* Copyright 2014-2016 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_GC_H
|
||||
#define ECMA_GC_H
|
||||
|
||||
#include "ecma-globals.h"
|
||||
#include "jmem-allocator.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmagc Garbage collector
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern void ecma_init_gc_info (ecma_object_t *);
|
||||
extern void ecma_ref_object (ecma_object_t *);
|
||||
extern void ecma_deref_object (ecma_object_t *);
|
||||
extern void ecma_gc_run (jmem_free_unused_memory_severity_t);
|
||||
extern void ecma_free_unused_memory (jmem_free_unused_memory_severity_t, size_t, bool);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* !ECMA_GC_H */
|
1023
third_party/jerryscript/jerry-core/ecma/base/ecma-globals.h
vendored
Normal file
1023
third_party/jerryscript/jerry-core/ecma/base/ecma-globals.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
1062
third_party/jerryscript/jerry-core/ecma/base/ecma-helpers-conversion.c
vendored
Normal file
1062
third_party/jerryscript/jerry-core/ecma/base/ecma-helpers-conversion.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
237
third_party/jerryscript/jerry-core/ecma/base/ecma-helpers-errol.c
vendored
Normal file
237
third_party/jerryscript/jerry-core/ecma/base/ecma-helpers-errol.c
vendored
Normal file
|
@ -0,0 +1,237 @@
|
|||
/* Copyright 2016 Samsung Electronics Co., Ltd.
|
||||
* Copyright 2016 University of Szeged
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This file is based on work under the following copyright and permission
|
||||
* notice:
|
||||
*
|
||||
* Copyright (c) 2016 Marc Andrysco
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "ecma-helpers.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmahelpers Helpers for operations with ECMA data types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Printing Floating-Point Numbers
|
||||
*
|
||||
* available at http://cseweb.ucsd.edu/~mandrysc/pub/dtoa.pdf
|
||||
*/
|
||||
|
||||
/**
|
||||
* Floating point format definitions
|
||||
*/
|
||||
#define ECMA_NEXT_FLOAT(value) (nextafter ((value), INFINITY))
|
||||
#define ECMA_PREV_FLOAT(value) (nextafter ((value), -INFINITY))
|
||||
|
||||
#define ERROL0_EPSILON 0.0000001
|
||||
|
||||
/**
|
||||
* High-precision data structure.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
double value; /**< value */
|
||||
double offset; /**< offset */
|
||||
} ecma_high_prec_t;
|
||||
|
||||
/**
|
||||
* Normalize the number by factoring in the error.
|
||||
*/
|
||||
static inline void __attr_always_inline___
|
||||
ecma_normalize_high_prec_data (ecma_high_prec_t *hp_data_p) /**< [in, out] float pair */
|
||||
{
|
||||
double val = hp_data_p->value;
|
||||
|
||||
hp_data_p->value += hp_data_p->offset;
|
||||
hp_data_p->offset += val - hp_data_p->value;
|
||||
} /* ecma_normalize_high_prec_data */
|
||||
|
||||
/**
|
||||
* Multiply the high-precision number by ten.
|
||||
*/
|
||||
static inline void __attr_always_inline___
|
||||
ecma_multiply_high_prec_by_10 (ecma_high_prec_t *hp_data_p) /**< [in, out] high-precision number */
|
||||
{
|
||||
double value = hp_data_p->value;
|
||||
|
||||
hp_data_p->value *= 10.0;
|
||||
hp_data_p->offset *= 10.0;
|
||||
|
||||
double offset = hp_data_p->value;
|
||||
|
||||
offset -= value * 8.0;
|
||||
offset -= value * 2.0;
|
||||
|
||||
hp_data_p->offset -= offset;
|
||||
|
||||
ecma_normalize_high_prec_data (hp_data_p);
|
||||
} /* ecma_multiply_high_prec_by_10 */
|
||||
|
||||
/**
|
||||
* Divide the high-precision number by ten.
|
||||
*/
|
||||
static void
|
||||
ecma_divide_high_prec_by_10 (ecma_high_prec_t *hp_data_p) /**< [in, out] high-precision number */
|
||||
{
|
||||
double value = hp_data_p->value;
|
||||
|
||||
hp_data_p->value /= 10.0;
|
||||
hp_data_p->offset /= 10.0;
|
||||
|
||||
value -= hp_data_p->value * 8.0;
|
||||
value -= hp_data_p->value * 2.0;
|
||||
|
||||
hp_data_p->offset += value / 10.0;
|
||||
|
||||
ecma_normalize_high_prec_data (hp_data_p);
|
||||
} /* ecma_divide_high_prec_by_10 */
|
||||
|
||||
/**
|
||||
* Errol0 double to ASCII conversion, guaranteed correct but possibly not optimal.
|
||||
*
|
||||
* @return number of generated digits
|
||||
*/
|
||||
inline lit_utf8_size_t __attr_always_inline___
|
||||
ecma_errol0_dtoa (double val, /**< ecma number */
|
||||
lit_utf8_byte_t *buffer_p, /**< buffer to generate digits into */
|
||||
int32_t *exp_p) /**< [out] exponent */
|
||||
{
|
||||
double power_of_10 = 1.0;
|
||||
int32_t exp = 1;
|
||||
|
||||
/* normalize the midpoint */
|
||||
ecma_high_prec_t mid;
|
||||
|
||||
mid.value = val;
|
||||
mid.offset = 0.0;
|
||||
|
||||
while (((mid.value > 10.0) || ((mid.value == 10.0) && (mid.offset >= 0.0))) && (exp < 308))
|
||||
{
|
||||
exp++;
|
||||
ecma_divide_high_prec_by_10 (&mid);
|
||||
power_of_10 /= 10.0;
|
||||
}
|
||||
|
||||
while (((mid.value < 1.0) || ((mid.value == 1.0) && (mid.offset < 0.0))) && (exp > -307))
|
||||
{
|
||||
exp--;
|
||||
ecma_multiply_high_prec_by_10 (&mid);
|
||||
power_of_10 *= 10.0;
|
||||
}
|
||||
|
||||
ecma_high_prec_t high_bound, low_bound;
|
||||
|
||||
high_bound.value = mid.value;
|
||||
high_bound.offset = mid.offset;
|
||||
|
||||
if (ECMA_NEXT_FLOAT (val) != INFINITY)
|
||||
{
|
||||
high_bound.offset += (ECMA_NEXT_FLOAT (val) - val) * power_of_10 / (2.0 + ERROL0_EPSILON);
|
||||
}
|
||||
|
||||
low_bound.value = mid.value;
|
||||
low_bound.offset = mid.offset + (ECMA_PREV_FLOAT (val) - val) * power_of_10 / (2.0 + ERROL0_EPSILON);
|
||||
|
||||
ecma_normalize_high_prec_data (&high_bound);
|
||||
ecma_normalize_high_prec_data (&low_bound);
|
||||
|
||||
/* normalized boundaries */
|
||||
|
||||
while (high_bound.value > 10.0 || (high_bound.value == 10.0 && (high_bound.offset >= 0.0)))
|
||||
{
|
||||
exp++;
|
||||
ecma_divide_high_prec_by_10 (&high_bound);
|
||||
ecma_divide_high_prec_by_10 (&low_bound);
|
||||
}
|
||||
|
||||
while (high_bound.value < 1.0 || (high_bound.value == 1.0 && (high_bound.offset < 0.0)))
|
||||
{
|
||||
exp--;
|
||||
ecma_multiply_high_prec_by_10 (&high_bound);
|
||||
ecma_multiply_high_prec_by_10 (&low_bound);
|
||||
}
|
||||
|
||||
/* digit generation */
|
||||
|
||||
lit_utf8_byte_t *dst_p = buffer_p;
|
||||
|
||||
while (high_bound.value != 0.0 || high_bound.offset != 0.0)
|
||||
{
|
||||
uint8_t high_digit = (uint8_t) high_bound.value;
|
||||
|
||||
if ((high_bound.value == high_digit) && (high_bound.offset < 0))
|
||||
{
|
||||
high_digit = (uint8_t) (high_digit - 1u);
|
||||
}
|
||||
|
||||
uint8_t low_digit = (uint8_t) low_bound.value;
|
||||
|
||||
if ((low_bound.value == low_digit) && (low_bound.offset < 0))
|
||||
{
|
||||
low_digit = (uint8_t) (low_digit - 1u);
|
||||
}
|
||||
|
||||
if (low_digit != high_digit)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
*dst_p++ = (lit_utf8_byte_t) ('0' + high_digit);
|
||||
|
||||
high_bound.value -= high_digit;
|
||||
ecma_multiply_high_prec_by_10 (&high_bound);
|
||||
|
||||
low_bound.value -= low_digit;
|
||||
ecma_multiply_high_prec_by_10 (&low_bound);
|
||||
}
|
||||
|
||||
double mdig = (high_bound.value + low_bound.value) / 2.0 + 0.5;
|
||||
*dst_p++ = (lit_utf8_byte_t) ('0' + (uint8_t) mdig);
|
||||
|
||||
*exp_p = exp;
|
||||
|
||||
return (lit_utf8_size_t) (dst_p - buffer_p);
|
||||
} /* ecma_errol0_dtoa */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
159
third_party/jerryscript/jerry-core/ecma/base/ecma-helpers-external-pointers.c
vendored
Normal file
159
third_party/jerryscript/jerry-core/ecma/base/ecma-helpers-external-pointers.c
vendored
Normal file
|
@ -0,0 +1,159 @@
|
|||
/* Copyright 2015-2016 Samsung Electronics Co., Ltd.
|
||||
* Copyright 2016 University of Szeged.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecma-alloc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmahelpers Helpers for operations with ECMA data types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create internal property with specified identifier and store external pointer in the property.
|
||||
*
|
||||
* Note:
|
||||
* property identifier should be one of the following:
|
||||
* - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE;
|
||||
* - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK.
|
||||
*
|
||||
* @return true - if property was just created with specified value,
|
||||
* false - otherwise, if property existed before the call, it's value was updated.
|
||||
*/
|
||||
bool
|
||||
ecma_create_external_pointer_property (ecma_object_t *obj_p, /**< object to create property in */
|
||||
ecma_internal_property_id_t id, /**< identifier of internal
|
||||
* property to create */
|
||||
ecma_external_pointer_t ptr_value) /**< value to store in the property */
|
||||
{
|
||||
JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE
|
||||
|| id == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK);
|
||||
|
||||
ecma_value_t *prop_p = ecma_find_internal_property (obj_p, id);
|
||||
bool is_new = (prop_p == NULL);
|
||||
|
||||
if (is_new)
|
||||
{
|
||||
prop_p = ecma_create_internal_property (obj_p, id);
|
||||
}
|
||||
|
||||
JERRY_STATIC_ASSERT (sizeof (uint32_t) <= sizeof (ECMA_PROPERTY_VALUE_PTR (prop_p)->value),
|
||||
size_of_internal_property_value_must_be_greater_than_or_equal_to_4_bytes);
|
||||
|
||||
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
|
||||
|
||||
*prop_p = (ecma_value_t) ptr_value;
|
||||
|
||||
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
|
||||
|
||||
ecma_external_pointer_t *handler_p;
|
||||
|
||||
if (is_new)
|
||||
{
|
||||
handler_p = ecma_alloc_external_pointer ();
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER (*prop_p, handler_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
handler_p = ECMA_GET_NON_NULL_POINTER (ecma_external_pointer_t, *prop_p);
|
||||
}
|
||||
|
||||
*handler_p = ptr_value;
|
||||
|
||||
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
|
||||
|
||||
return is_new;
|
||||
} /* ecma_create_external_pointer_property */
|
||||
|
||||
/**
|
||||
* Get value of external pointer stored in the object's property with specified identifier
|
||||
*
|
||||
* Note:
|
||||
* property identifier should be one of the following:
|
||||
* - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE;
|
||||
* - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK.
|
||||
*
|
||||
* @return true - if property exists and it's value is returned through out_pointer_p,
|
||||
* false - otherwise (value returned through out_pointer_p is NULL).
|
||||
*/
|
||||
bool
|
||||
ecma_get_external_pointer_value (ecma_object_t *obj_p, /**< object to get property value from */
|
||||
ecma_internal_property_id_t id, /**< identifier of internal property
|
||||
* to get value from */
|
||||
ecma_external_pointer_t *out_pointer_p) /**< [out] value of the external pointer */
|
||||
{
|
||||
JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE
|
||||
|| id == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK);
|
||||
|
||||
ecma_value_t *prop_p = ecma_find_internal_property (obj_p, id);
|
||||
|
||||
if (prop_p == NULL)
|
||||
{
|
||||
*out_pointer_p = (ecma_external_pointer_t) NULL;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
|
||||
|
||||
*out_pointer_p = *prop_p;
|
||||
|
||||
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
|
||||
|
||||
*out_pointer_p = *ECMA_GET_NON_NULL_POINTER (ecma_external_pointer_t, *prop_p);
|
||||
|
||||
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
|
||||
|
||||
return true;
|
||||
} /* ecma_get_external_pointer_value */
|
||||
|
||||
/**
|
||||
* Free memory associated with external pointer stored in the property
|
||||
*
|
||||
* Note:
|
||||
* property identifier should be one of the following:
|
||||
* - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE;
|
||||
* - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK.
|
||||
*/
|
||||
void
|
||||
ecma_free_external_pointer_in_property (ecma_property_t *prop_p) /**< internal property */
|
||||
{
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (prop_p) == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE
|
||||
|| ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (prop_p) == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK);
|
||||
|
||||
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
|
||||
|
||||
/* no additional memory was allocated for the pointer storage */
|
||||
|
||||
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
|
||||
|
||||
ecma_external_pointer_t *handler_p = ECMA_GET_NON_NULL_POINTER (ecma_external_pointer_t,
|
||||
ECMA_PROPERTY_VALUE_PTR (prop_p)->value);
|
||||
|
||||
ecma_dealloc_external_pointer (handler_p);
|
||||
|
||||
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
|
||||
|
||||
} /* ecma_free_external_pointer_in_property */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
737
third_party/jerryscript/jerry-core/ecma/base/ecma-helpers-number.c
vendored
Normal file
737
third_party/jerryscript/jerry-core/ecma/base/ecma-helpers-number.c
vendored
Normal file
|
@ -0,0 +1,737 @@
|
|||
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
|
||||
* Copyright 2015-2016 University of Szeged.
|
||||
*
|
||||
* 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-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmahelpers Helpers for operations with ECMA data types
|
||||
* @{
|
||||
*/
|
||||
|
||||
JERRY_STATIC_ASSERT (sizeof (ecma_value_t) == sizeof (ecma_integer_value_t),
|
||||
size_of_ecma_value_t_must_be_equal_to_the_size_of_ecma_integer_value_t);
|
||||
|
||||
JERRY_STATIC_ASSERT (ECMA_DIRECT_SHIFT == ECMA_VALUE_SHIFT + 1,
|
||||
currently_directly_encoded_values_has_one_extra_flag);
|
||||
|
||||
JERRY_STATIC_ASSERT (((1 << (ECMA_DIRECT_SHIFT - 1)) | ECMA_TYPE_DIRECT) == ECMA_DIRECT_TYPE_SIMPLE_VALUE,
|
||||
currently_directly_encoded_values_start_after_direct_type_simple_value);
|
||||
|
||||
#define ECMA_NUMBER_SIGN_POS (ECMA_NUMBER_FRACTION_WIDTH + \
|
||||
ECMA_NUMBER_BIASED_EXP_WIDTH)
|
||||
|
||||
#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32
|
||||
JERRY_STATIC_ASSERT (sizeof (ecma_number_t) == sizeof (uint32_t),
|
||||
size_of_ecma_number_t_must_be_equal_to_4_bytes);
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
{
|
||||
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) << ECMA_NUMBER_SIGN_POS) |
|
||||
(biased_exp << ECMA_NUMBER_FRACTION_WIDTH) |
|
||||
((uint32_t) fraction));
|
||||
|
||||
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, /**< [out] sign (optional) */
|
||||
uint32_t *biased_exp_p, /**< [out] biased exponent (optional) */
|
||||
uint64_t *fraction_p) /**< [out] fraction (optional) */
|
||||
{
|
||||
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 >> ECMA_NUMBER_SIGN_POS) != 0);
|
||||
}
|
||||
|
||||
if (biased_exp_p != NULL)
|
||||
{
|
||||
*biased_exp_p = (((packed_value) & ~(1u << ECMA_NUMBER_SIGN_POS)) >> ECMA_NUMBER_FRACTION_WIDTH);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
#elif CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64
|
||||
JERRY_STATIC_ASSERT (sizeof (ecma_number_t) == sizeof (uint64_t),
|
||||
size_of_ecma_number_t_must_be_equal_to_8_bytes);
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
{
|
||||
uint64_t packed_value = (((sign ? 1ull : 0ull) << ECMA_NUMBER_SIGN_POS) |
|
||||
(((uint64_t) biased_exp) << ECMA_NUMBER_FRACTION_WIDTH) |
|
||||
fraction);
|
||||
|
||||
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, /**< [out] sign (optional) */
|
||||
uint32_t *biased_exp_p, /**< [out] biased exponent (optional) */
|
||||
uint64_t *fraction_p) /**< [out] fraction (optional) */
|
||||
{
|
||||
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 >> ECMA_NUMBER_SIGN_POS) != 0);
|
||||
}
|
||||
|
||||
if (biased_exp_p != NULL)
|
||||
{
|
||||
*biased_exp_p = (uint32_t) (((packed_value) & ~(1ull << ECMA_NUMBER_SIGN_POS)) >> ECMA_NUMBER_FRACTION_WIDTH);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
#endif /* CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32 */
|
||||
|
||||
/**
|
||||
* 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 __attr_always_inline___
|
||||
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 __attr_always_inline___
|
||||
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 */
|
||||
{
|
||||
JERRY_ASSERT (!ecma_number_is_nan (num));
|
||||
|
||||
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 ECMA_NUMBER_ZERO;
|
||||
}
|
||||
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 */
|
||||
|
||||
/**
|
||||
* Calculate remainder of division of two numbers,
|
||||
* as specified in ECMA-262 v5, 11.5.3, item 6.
|
||||
*
|
||||
* Note:
|
||||
* operands shouldn't contain NaN, Infinity, or zero.
|
||||
*
|
||||
* @return number - calculated remainder.
|
||||
*/
|
||||
ecma_number_t
|
||||
ecma_number_calc_remainder (ecma_number_t left_num, /**< left operand */
|
||||
ecma_number_t right_num) /**< right operand */
|
||||
{
|
||||
JERRY_ASSERT (!ecma_number_is_nan (left_num)
|
||||
&& !ecma_number_is_zero (left_num)
|
||||
&& !ecma_number_is_infinity (left_num));
|
||||
JERRY_ASSERT (!ecma_number_is_nan (right_num)
|
||||
&& !ecma_number_is_zero (right_num)
|
||||
&& !ecma_number_is_infinity (right_num));
|
||||
|
||||
const ecma_number_t q = ecma_number_trunc (ecma_number_divide (left_num, right_num));
|
||||
ecma_number_t r = ecma_number_substract (left_num, ecma_number_multiply (right_num, q));
|
||||
|
||||
if (ecma_number_is_zero (r)
|
||||
&& ecma_number_is_negative (left_num))
|
||||
{
|
||||
r = ecma_number_negate (r);
|
||||
}
|
||||
|
||||
return r;
|
||||
} /* ecma_number_calc_remainder */
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
1698
third_party/jerryscript/jerry-core/ecma/base/ecma-helpers-string.c
vendored
Normal file
1698
third_party/jerryscript/jerry-core/ecma/base/ecma-helpers-string.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
924
third_party/jerryscript/jerry-core/ecma/base/ecma-helpers-value.c
vendored
Normal file
924
third_party/jerryscript/jerry-core/ecma/base/ecma-helpers-value.c
vendored
Normal file
|
@ -0,0 +1,924 @@
|
|||
/* Copyright 2015-2016 Samsung Electronics Co., Ltd.
|
||||
* Copyright 2016 University of Szeged.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecma-alloc.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "jrt.h"
|
||||
#include "jrt-bit-fields.h"
|
||||
#include "vm-defines.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmahelpers Helpers for operations with ECMA data types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Masking the type and flags
|
||||
*/
|
||||
#define ECMA_VALUE_FULL_MASK (ECMA_VALUE_TYPE_MASK | ECMA_VALUE_ERROR_FLAG)
|
||||
|
||||
JERRY_STATIC_ASSERT (ECMA_TYPE___MAX <= ECMA_VALUE_TYPE_MASK,
|
||||
ecma_types_must_be_less_than_mask);
|
||||
|
||||
JERRY_STATIC_ASSERT ((ECMA_VALUE_FULL_MASK + 1) == (1 << ECMA_VALUE_SHIFT),
|
||||
ecma_value_part_must_start_after_flags);
|
||||
|
||||
JERRY_STATIC_ASSERT (ECMA_VALUE_SHIFT <= JMEM_ALIGNMENT_LOG,
|
||||
ecma_value_shift_must_be_less_than_or_equal_than_mem_alignment_log);
|
||||
|
||||
JERRY_STATIC_ASSERT (sizeof (jmem_cpointer_t) <= sizeof (ecma_value_t),
|
||||
size_of_jmem_cpointer_t_must_be_less_or_equal_to_the_size_of_ecma_value_t);
|
||||
|
||||
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
|
||||
|
||||
JERRY_STATIC_ASSERT (sizeof (uintptr_t) <= sizeof (ecma_value_t),
|
||||
uintptr_t_must_fit_in_ecma_value_t);
|
||||
|
||||
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
|
||||
|
||||
JERRY_STATIC_ASSERT (sizeof (uintptr_t) > sizeof (ecma_value_t),
|
||||
uintptr_t_must_not_fit_in_ecma_value_t);
|
||||
|
||||
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
|
||||
|
||||
JERRY_STATIC_ASSERT ((ECMA_SIMPLE_VALUE_FALSE | 0x1) == ECMA_SIMPLE_VALUE_TRUE
|
||||
&& ECMA_SIMPLE_VALUE_FALSE != ECMA_SIMPLE_VALUE_TRUE,
|
||||
only_the_lowest_bit_must_be_different_for_simple_value_true_and_false);
|
||||
|
||||
/**
|
||||
* Get type field of ecma value
|
||||
*
|
||||
* @return type field
|
||||
*/
|
||||
static inline ecma_type_t __attr_pure___ __attr_always_inline___
|
||||
ecma_get_value_type_field (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
return value & ECMA_VALUE_TYPE_MASK;
|
||||
} /* ecma_get_value_type_field */
|
||||
|
||||
/**
|
||||
* Convert a pointer into an ecma value.
|
||||
*
|
||||
* @return ecma value
|
||||
*/
|
||||
static inline ecma_value_t __attr_pure___ __attr_always_inline___
|
||||
ecma_pointer_to_ecma_value (const void *ptr) /**< pointer */
|
||||
{
|
||||
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
|
||||
|
||||
uintptr_t uint_ptr = (uintptr_t) ptr;
|
||||
JERRY_ASSERT ((uint_ptr & ECMA_VALUE_FULL_MASK) == 0);
|
||||
return (ecma_value_t) uint_ptr;
|
||||
|
||||
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
|
||||
|
||||
jmem_cpointer_t ptr_cp;
|
||||
ECMA_SET_NON_NULL_POINTER (ptr_cp, ptr);
|
||||
return ((ecma_value_t) ptr_cp) << ECMA_VALUE_SHIFT;
|
||||
|
||||
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
|
||||
} /* ecma_pointer_to_ecma_value */
|
||||
|
||||
/**
|
||||
* Get a pointer from an ecma value
|
||||
*
|
||||
* @return pointer
|
||||
*/
|
||||
static inline void * __attr_pure___ __attr_always_inline___
|
||||
ecma_get_pointer_from_ecma_value (ecma_value_t value) /**< value */
|
||||
{
|
||||
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
|
||||
return (void *) (uintptr_t) ((value) & ~ECMA_VALUE_FULL_MASK);
|
||||
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
|
||||
return ECMA_GET_NON_NULL_POINTER (ecma_number_t,
|
||||
value >> ECMA_VALUE_SHIFT);
|
||||
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
|
||||
} /* ecma_get_pointer_from_ecma_value */
|
||||
|
||||
/**
|
||||
* Check if the value is direct ecma-value.
|
||||
*
|
||||
* @return true - if the value is a direct value,
|
||||
* false - otherwise.
|
||||
*/
|
||||
inline bool __attr_pure___ __attr_always_inline___
|
||||
ecma_is_value_direct (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
return (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT);
|
||||
} /* ecma_is_value_direct */
|
||||
|
||||
/**
|
||||
* Check if the value is simple ecma-value.
|
||||
*
|
||||
* @return true - if the value is a simple value,
|
||||
* false - otherwise.
|
||||
*/
|
||||
inline bool __attr_pure___ __attr_always_inline___
|
||||
ecma_is_value_simple (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
return (value & ECMA_DIRECT_TYPE_MASK) == ECMA_DIRECT_TYPE_SIMPLE_VALUE;
|
||||
} /* ecma_is_value_simple */
|
||||
|
||||
/**
|
||||
* Check whether the value is a given simple value.
|
||||
*
|
||||
* @return true - if the value is equal to the given simple value,
|
||||
* false - otherwise.
|
||||
*/
|
||||
static inline bool __attr_pure___ __attr_always_inline___
|
||||
ecma_is_value_equal_to_simple_value (ecma_value_t value, /**< ecma value */
|
||||
ecma_simple_value_t simple_value) /**< simple value */
|
||||
{
|
||||
return (value | ECMA_VALUE_ERROR_FLAG) == (ecma_make_simple_value (simple_value) | ECMA_VALUE_ERROR_FLAG);
|
||||
} /* ecma_is_value_equal_to_simple_value */
|
||||
|
||||
/**
|
||||
* Check if the value is empty.
|
||||
*
|
||||
* @return true - if the value contains implementation-defined empty simple value,
|
||||
* false - otherwise.
|
||||
*/
|
||||
inline bool __attr_pure___ __attr_always_inline___
|
||||
ecma_is_value_empty (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
return ecma_is_value_equal_to_simple_value (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.
|
||||
*/
|
||||
inline bool __attr_pure___ __attr_always_inline___
|
||||
ecma_is_value_undefined (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
return ecma_is_value_equal_to_simple_value (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.
|
||||
*/
|
||||
inline bool __attr_pure___ __attr_always_inline___
|
||||
ecma_is_value_null (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
return ecma_is_value_equal_to_simple_value (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.
|
||||
*/
|
||||
inline bool __attr_pure___ __attr_always_inline___
|
||||
ecma_is_value_boolean (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
return ecma_is_value_true (value | (1 << ECMA_DIRECT_SHIFT));
|
||||
} /* ecma_is_value_boolean */
|
||||
|
||||
/**
|
||||
* Check if the value is true.
|
||||
*
|
||||
* @return true - if the value contains ecma-true simple value,
|
||||
* false - otherwise.
|
||||
*/
|
||||
inline bool __attr_pure___ __attr_always_inline___
|
||||
ecma_is_value_true (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
return ecma_is_value_equal_to_simple_value (value, ECMA_SIMPLE_VALUE_TRUE);
|
||||
} /* ecma_is_value_true */
|
||||
|
||||
/**
|
||||
* Check if the value is false.
|
||||
*
|
||||
* @return true - if the value contains ecma-false simple value,
|
||||
* false - otherwise.
|
||||
*/
|
||||
inline bool __attr_pure___ __attr_always_inline___
|
||||
ecma_is_value_false (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
return ecma_is_value_equal_to_simple_value (value, ECMA_SIMPLE_VALUE_FALSE);
|
||||
} /* ecma_is_value_false */
|
||||
|
||||
/**
|
||||
* Check if the value is not found.
|
||||
*
|
||||
* @return true - if the value contains ecma-not-found simple value,
|
||||
* false - otherwise.
|
||||
*/
|
||||
inline bool __attr_pure___ __attr_always_inline___
|
||||
ecma_is_value_found (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
return value != ecma_make_simple_value (ECMA_SIMPLE_VALUE_NOT_FOUND);
|
||||
} /* ecma_is_value_found */
|
||||
|
||||
/**
|
||||
* Check if the value is array hole.
|
||||
*
|
||||
* @return true - if the value contains ecma-array-hole simple value,
|
||||
* false - otherwise.
|
||||
*/
|
||||
inline bool __attr_pure___ __attr_always_inline___
|
||||
ecma_is_value_array_hole (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
return ecma_is_value_equal_to_simple_value (value, ECMA_SIMPLE_VALUE_ARRAY_HOLE);
|
||||
} /* ecma_is_value_array_hole */
|
||||
|
||||
/**
|
||||
* Check if the value is integer ecma-number.
|
||||
*
|
||||
* @return true - if the value contains an integer ecma-number value,
|
||||
* false - otherwise.
|
||||
*/
|
||||
inline bool __attr_pure___ __attr_always_inline___
|
||||
ecma_is_value_integer_number (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
return (value & ECMA_DIRECT_TYPE_MASK) == ECMA_DIRECT_TYPE_INTEGER_VALUE;
|
||||
} /* ecma_is_value_integer_number */
|
||||
|
||||
/**
|
||||
* Check if both values are integer ecma-numbers.
|
||||
*
|
||||
* @return true - if both values contain integer ecma-number values,
|
||||
* false - otherwise.
|
||||
*/
|
||||
inline bool __attr_pure___ __attr_always_inline___
|
||||
ecma_are_values_integer_numbers (ecma_value_t first_value, /**< first ecma value */
|
||||
ecma_value_t second_value) /**< second ecma value */
|
||||
{
|
||||
JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_INTEGER_VALUE == 0,
|
||||
ecma_direct_type_integer_value_must_be_zero);
|
||||
|
||||
return ((first_value | second_value) & ECMA_DIRECT_TYPE_MASK) == ECMA_DIRECT_TYPE_INTEGER_VALUE;
|
||||
} /* ecma_are_values_integer_numbers */
|
||||
|
||||
/**
|
||||
* Check if the value is floating-point ecma-number.
|
||||
*
|
||||
* @return true - if the value contains a floating-point ecma-number value,
|
||||
* false - otherwise.
|
||||
*/
|
||||
inline bool __attr_pure___ __attr_always_inline___
|
||||
ecma_is_value_float_number (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
return (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT);
|
||||
} /* ecma_is_value_float_number */
|
||||
|
||||
/**
|
||||
* Check if the value is ecma-number.
|
||||
*
|
||||
* @return true - if the value contains ecma-number value,
|
||||
* false - otherwise.
|
||||
*/
|
||||
inline bool __attr_pure___ __attr_always_inline___
|
||||
ecma_is_value_number (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
return (ecma_is_value_integer_number (value)
|
||||
|| ecma_is_value_float_number (value));
|
||||
} /* ecma_is_value_number */
|
||||
|
||||
/**
|
||||
* Check if the value is ecma-string.
|
||||
*
|
||||
* @return true - if the value contains ecma-string value,
|
||||
* false - otherwise.
|
||||
*/
|
||||
inline bool __attr_pure___ __attr_always_inline___
|
||||
ecma_is_value_string (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.
|
||||
*/
|
||||
inline bool __attr_pure___ __attr_always_inline___
|
||||
ecma_is_value_object (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 (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
|
||||
*/
|
||||
inline ecma_value_t __attr_const___ __attr_always_inline___
|
||||
ecma_make_simple_value (const ecma_simple_value_t simple_value) /**< simple value */
|
||||
{
|
||||
return (((ecma_value_t) (simple_value)) << ECMA_DIRECT_SHIFT) | ECMA_DIRECT_TYPE_SIMPLE_VALUE;
|
||||
} /* ecma_make_simple_value */
|
||||
|
||||
/**
|
||||
* Creates an ecma value from the given raw boolean.
|
||||
*
|
||||
* @return boolean ecma_value
|
||||
*/
|
||||
inline ecma_value_t __attr_const___ __attr_always_inline___
|
||||
ecma_make_boolean_value (bool boolean_value) /**< raw bool value from which the ecma value will be created */
|
||||
{
|
||||
return ecma_make_simple_value (boolean_value ? ECMA_SIMPLE_VALUE_TRUE
|
||||
: ECMA_SIMPLE_VALUE_FALSE);
|
||||
} /* ecma_make_boolean_value */
|
||||
|
||||
/**
|
||||
* Encode an integer number into an ecma-value without allocating memory
|
||||
*
|
||||
* Note:
|
||||
* The value must fit into the range of allowed ecma integer values
|
||||
*
|
||||
* @return ecma-value
|
||||
*/
|
||||
inline ecma_value_t __attr_const___ __attr_always_inline___
|
||||
ecma_make_integer_value (ecma_integer_value_t integer_value) /**< integer number to be encoded */
|
||||
{
|
||||
JERRY_ASSERT (ECMA_IS_INTEGER_NUMBER (integer_value));
|
||||
|
||||
return ((ecma_value_t) (integer_value << ECMA_DIRECT_SHIFT)) | ECMA_DIRECT_TYPE_INTEGER_VALUE;
|
||||
} /* ecma_make_integer_value */
|
||||
|
||||
/**
|
||||
* Allocate and initialize a new float number without checks.
|
||||
*
|
||||
* @return ecma-value
|
||||
*/
|
||||
static ecma_value_t __attr_const___
|
||||
ecma_create_float_number (ecma_number_t ecma_number) /**< value of the float number */
|
||||
{
|
||||
ecma_number_t *ecma_num_p = ecma_alloc_number ();
|
||||
|
||||
*ecma_num_p = ecma_number;
|
||||
|
||||
return ecma_pointer_to_ecma_value (ecma_num_p) | ECMA_TYPE_FLOAT;
|
||||
} /* ecma_create_float_number */
|
||||
|
||||
/**
|
||||
* Create a new NaN value.
|
||||
*
|
||||
* @return ecma-value
|
||||
*/
|
||||
inline ecma_value_t __attr_always_inline___
|
||||
ecma_make_nan_value (void)
|
||||
{
|
||||
return ecma_create_float_number (ecma_number_make_nan ());
|
||||
} /* ecma_make_nan_value */
|
||||
|
||||
/**
|
||||
* Checks whether the passed number is +0.0
|
||||
*
|
||||
* @return true, if it is +0.0, false otherwise
|
||||
*/
|
||||
static inline bool __attr_const___ __attr_always_inline___
|
||||
ecma_is_number_equal_to_positive_zero (ecma_number_t ecma_number) /**< number */
|
||||
{
|
||||
#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32
|
||||
union
|
||||
{
|
||||
uint32_t u32_value;
|
||||
ecma_number_t float_value;
|
||||
} u;
|
||||
|
||||
u.float_value = ecma_number;
|
||||
|
||||
return u.u32_value == 0;
|
||||
#else /* CONFIG_ECMA_NUMBER_TYPE != CONFIG_ECMA_NUMBER_FLOAT32 */
|
||||
union
|
||||
{
|
||||
uint64_t u64_value;
|
||||
ecma_number_t float_value;
|
||||
} u;
|
||||
|
||||
u.float_value = ecma_number;
|
||||
|
||||
return u.u64_value == 0;
|
||||
#endif /* CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32 */
|
||||
} /* ecma_is_number_equal_to_positive_zero */
|
||||
|
||||
/**
|
||||
* Encode a number into an ecma-value
|
||||
*
|
||||
* @return ecma-value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_make_number_value (ecma_number_t ecma_number) /**< number to be encoded */
|
||||
{
|
||||
ecma_integer_value_t integer_value = (ecma_integer_value_t) ecma_number;
|
||||
|
||||
if ((ecma_number_t) integer_value == ecma_number
|
||||
&& ((integer_value == 0) ? ecma_is_number_equal_to_positive_zero (ecma_number)
|
||||
: ECMA_IS_INTEGER_NUMBER (integer_value)))
|
||||
{
|
||||
return ecma_make_integer_value (integer_value);
|
||||
}
|
||||
|
||||
return ecma_create_float_number (ecma_number);
|
||||
} /* ecma_make_number_value */
|
||||
|
||||
/**
|
||||
* Encode an int32 number into an ecma-value
|
||||
*
|
||||
* @return ecma-value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_make_int32_value (int32_t int32_number) /**< int32 number to be encoded */
|
||||
{
|
||||
if (ECMA_IS_INTEGER_NUMBER (int32_number))
|
||||
{
|
||||
return ecma_make_integer_value ((ecma_integer_value_t) int32_number);
|
||||
}
|
||||
|
||||
return ecma_create_float_number ((ecma_number_t) int32_number);
|
||||
} /* ecma_make_int32_value */
|
||||
|
||||
/**
|
||||
* Encode an unsigned int32 number into an ecma-value
|
||||
*
|
||||
* @return ecma-value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_make_uint32_value (uint32_t uint32_number) /**< uint32 number to be encoded */
|
||||
{
|
||||
if (uint32_number <= ECMA_INTEGER_NUMBER_MAX)
|
||||
{
|
||||
return ecma_make_integer_value ((ecma_integer_value_t) uint32_number);
|
||||
}
|
||||
|
||||
return ecma_create_float_number ((ecma_number_t) uint32_number);
|
||||
} /* ecma_make_uint32_value */
|
||||
|
||||
/**
|
||||
* String value constructor
|
||||
*/
|
||||
ecma_value_t __attr_const___
|
||||
ecma_make_string_value (const ecma_string_t *ecma_string_p) /**< string to reference in value */
|
||||
{
|
||||
JERRY_ASSERT (ecma_string_p != NULL);
|
||||
|
||||
return ecma_pointer_to_ecma_value (ecma_string_p) | ECMA_TYPE_STRING;
|
||||
} /* ecma_make_string_value */
|
||||
|
||||
/**
|
||||
* Object value constructor
|
||||
*/
|
||||
ecma_value_t __attr_const___
|
||||
ecma_make_object_value (const ecma_object_t *object_p) /**< object to reference in value */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
|
||||
return ecma_pointer_to_ecma_value (object_p) | ECMA_TYPE_OBJECT;
|
||||
} /* ecma_make_object_value */
|
||||
|
||||
/**
|
||||
* Error value constructor
|
||||
*/
|
||||
ecma_value_t __attr_const___
|
||||
ecma_make_error_value (ecma_value_t value) /**< original ecma value */
|
||||
{
|
||||
/* Error values cannot be converted. */
|
||||
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (value));
|
||||
|
||||
return value | ECMA_VALUE_ERROR_FLAG;
|
||||
} /* ecma_make_error_value */
|
||||
|
||||
/**
|
||||
* Error value constructor
|
||||
*/
|
||||
ecma_value_t __attr_const___
|
||||
ecma_make_error_obj_value (const ecma_object_t *object_p) /**< object to reference in value */
|
||||
{
|
||||
return ecma_make_error_value (ecma_make_object_value (object_p));
|
||||
} /* ecma_make_error_obj_value */
|
||||
|
||||
/**
|
||||
* Get integer value from an integer ecma value
|
||||
*
|
||||
* @return floating point value
|
||||
*/
|
||||
inline ecma_integer_value_t __attr_pure___ __attr_always_inline___
|
||||
ecma_get_integer_from_value (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_integer_number (value));
|
||||
|
||||
return ((ecma_integer_value_t) value) >> ECMA_DIRECT_SHIFT;
|
||||
} /* ecma_get_integer_from_value */
|
||||
|
||||
inline ecma_number_t __attr_pure___ __attr_always_inline___
|
||||
ecma_get_float_from_value (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT);
|
||||
|
||||
return *(ecma_number_t *) ecma_get_pointer_from_ecma_value (value);
|
||||
} /* ecma_get_float_from_value */
|
||||
|
||||
/**
|
||||
* Get floating point value from an ecma value
|
||||
*
|
||||
* @return floating point value
|
||||
*/
|
||||
ecma_number_t __attr_pure___
|
||||
ecma_get_number_from_value (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
if (ecma_is_value_integer_number (value))
|
||||
{
|
||||
return (ecma_number_t) ecma_get_integer_from_value (value);
|
||||
}
|
||||
|
||||
return ecma_get_float_from_value (value);
|
||||
} /* ecma_get_number_from_value */
|
||||
|
||||
/**
|
||||
* Get uint32 value from an ecma value
|
||||
*
|
||||
* @return floating point value
|
||||
*/
|
||||
uint32_t __attr_pure___
|
||||
ecma_get_uint32_from_value (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
if (ecma_is_value_integer_number (value))
|
||||
{
|
||||
/* Works with negative numbers as well. */
|
||||
return (uint32_t) (((ecma_integer_value_t) value) >> ECMA_DIRECT_SHIFT);
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT);
|
||||
|
||||
return ecma_number_to_uint32 (*(ecma_number_t *) ecma_get_pointer_from_ecma_value (value));
|
||||
} /* ecma_get_uint32_from_value */
|
||||
|
||||
/**
|
||||
* Get pointer to ecma-string from ecma value
|
||||
*
|
||||
* @return the pointer
|
||||
*/
|
||||
inline ecma_string_t *__attr_pure___ __attr_always_inline___
|
||||
ecma_get_string_from_value (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_STRING);
|
||||
|
||||
return (ecma_string_t *) ecma_get_pointer_from_ecma_value (value);
|
||||
} /* ecma_get_string_from_value */
|
||||
|
||||
/**
|
||||
* Get pointer to ecma-object from ecma value
|
||||
*
|
||||
* @return the pointer
|
||||
*/
|
||||
inline ecma_object_t *__attr_pure___ __attr_always_inline___
|
||||
ecma_get_object_from_value (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_OBJECT);
|
||||
|
||||
return (ecma_object_t *) ecma_get_pointer_from_ecma_value (value);
|
||||
} /* ecma_get_object_from_value */
|
||||
|
||||
/**
|
||||
* Invert a boolean value
|
||||
*
|
||||
* @return ecma value
|
||||
*/
|
||||
inline ecma_value_t __attr_pure___ __attr_always_inline___
|
||||
ecma_invert_boolean_value (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_boolean (value));
|
||||
|
||||
return (value ^ (1 << ECMA_DIRECT_SHIFT));
|
||||
} /* ecma_invert_boolean_value */
|
||||
|
||||
/**
|
||||
* Get the value from an error ecma value
|
||||
*
|
||||
* @return ecma value
|
||||
*/
|
||||
ecma_value_t __attr_pure___
|
||||
ecma_get_value_from_error_value (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
JERRY_ASSERT (ECMA_IS_VALUE_ERROR (value));
|
||||
|
||||
value = (ecma_value_t) (value & ~ECMA_VALUE_ERROR_FLAG);
|
||||
|
||||
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (value));
|
||||
|
||||
return value;
|
||||
} /* ecma_get_value_from_error_value */
|
||||
|
||||
/**
|
||||
* Copy ecma value.
|
||||
*
|
||||
* @return copy of the given value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_copy_value (ecma_value_t value) /**< value description */
|
||||
{
|
||||
switch (ecma_get_value_type_field (value))
|
||||
{
|
||||
case ECMA_TYPE_DIRECT:
|
||||
{
|
||||
return value;
|
||||
}
|
||||
case ECMA_TYPE_FLOAT:
|
||||
{
|
||||
ecma_number_t *num_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (value);
|
||||
|
||||
return ecma_create_float_number (*num_p);
|
||||
}
|
||||
case ECMA_TYPE_STRING:
|
||||
{
|
||||
ecma_ref_ecma_string (ecma_get_string_from_value (value));
|
||||
return value;
|
||||
}
|
||||
case ECMA_TYPE_OBJECT:
|
||||
{
|
||||
ecma_ref_object (ecma_get_object_from_value (value));
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_UNREACHABLE ();
|
||||
} /* ecma_copy_value */
|
||||
|
||||
/**
|
||||
* Copy ecma value.
|
||||
*
|
||||
* Note:
|
||||
* this function is similar to ecma_copy_value, but it is
|
||||
* faster for direct values since no function call is performed.
|
||||
* It also increases the binary size so it is recommended for
|
||||
* critical code paths only.
|
||||
*
|
||||
* @return copy of the given value
|
||||
*/
|
||||
inline ecma_value_t __attr_always_inline___
|
||||
ecma_fast_copy_value (ecma_value_t value) /**< value description */
|
||||
{
|
||||
return (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT) ? value : ecma_copy_value (value);
|
||||
} /* ecma_fast_copy_value */
|
||||
|
||||
/**
|
||||
* Copy the ecma value if not an object
|
||||
*
|
||||
* @return copy of the given value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_copy_value_if_not_object (ecma_value_t value) /**< value description */
|
||||
{
|
||||
if (ecma_get_value_type_field (value) != ECMA_TYPE_OBJECT)
|
||||
{
|
||||
return ecma_copy_value (value);
|
||||
}
|
||||
|
||||
return value;
|
||||
} /* ecma_copy_value_if_not_object */
|
||||
|
||||
/**
|
||||
* Assign a new value to an ecma-value
|
||||
*
|
||||
* Note:
|
||||
* value previously stored in the property is freed
|
||||
*/
|
||||
void
|
||||
ecma_value_assign_value (ecma_value_t *value_p, /**< [in, out] ecma value */
|
||||
ecma_value_t ecma_value) /**< value to assign */
|
||||
{
|
||||
JERRY_STATIC_ASSERT (ECMA_TYPE_DIRECT == 0,
|
||||
ecma_type_direct_must_be_zero_for_the_next_check);
|
||||
|
||||
if (*value_p == ecma_value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ecma_get_value_type_field (ecma_value || *value_p) == ECMA_TYPE_DIRECT)
|
||||
{
|
||||
*value_p = ecma_value;
|
||||
}
|
||||
else if (ecma_is_value_float_number (ecma_value)
|
||||
&& ecma_is_value_float_number (*value_p))
|
||||
{
|
||||
const ecma_number_t *num_src_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (ecma_value);
|
||||
ecma_number_t *num_dst_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (*value_p);
|
||||
|
||||
*num_dst_p = *num_src_p;
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_free_value_if_not_object (*value_p);
|
||||
*value_p = ecma_copy_value_if_not_object (ecma_value);
|
||||
}
|
||||
} /* ecma_value_assign_value */
|
||||
|
||||
/**
|
||||
* Update the value of a float number to a new value
|
||||
*
|
||||
* Note:
|
||||
* The original value is destroyed.
|
||||
*
|
||||
* @return updated ecma value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_update_float_number (ecma_value_t float_value, /**< original float value */
|
||||
ecma_number_t new_number) /**< updated number value */
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_float_number (float_value));
|
||||
|
||||
ecma_integer_value_t integer_number = (ecma_integer_value_t) new_number;
|
||||
ecma_number_t *number_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (float_value);
|
||||
|
||||
if ((ecma_number_t) integer_number == new_number
|
||||
&& ((integer_number == 0) ? ecma_is_number_equal_to_positive_zero (new_number)
|
||||
: ECMA_IS_INTEGER_NUMBER (integer_number)))
|
||||
{
|
||||
ecma_dealloc_number (number_p);
|
||||
return ecma_make_integer_value (integer_number);
|
||||
}
|
||||
|
||||
*number_p = new_number;
|
||||
return float_value;
|
||||
} /* ecma_update_float_number */
|
||||
|
||||
/**
|
||||
* Assign a float number to an ecma-value
|
||||
*
|
||||
* Note:
|
||||
* value previously stored in the property is freed
|
||||
*/
|
||||
static void
|
||||
ecma_value_assign_float_number (ecma_value_t *value_p, /**< [in, out] ecma value */
|
||||
ecma_number_t ecma_number) /**< number to assign */
|
||||
{
|
||||
if (ecma_is_value_float_number (*value_p))
|
||||
{
|
||||
ecma_number_t *num_dst_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (*value_p);
|
||||
|
||||
*num_dst_p = ecma_number;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ecma_get_value_type_field (*value_p) != ECMA_TYPE_DIRECT
|
||||
&& ecma_get_value_type_field (*value_p) != ECMA_TYPE_OBJECT)
|
||||
{
|
||||
ecma_free_value (*value_p);
|
||||
}
|
||||
|
||||
*value_p = ecma_create_float_number (ecma_number);
|
||||
} /* ecma_value_assign_float_number */
|
||||
|
||||
/**
|
||||
* Assign a number to an ecma-value
|
||||
*
|
||||
* Note:
|
||||
* value previously stored in the property is freed
|
||||
*/
|
||||
void
|
||||
ecma_value_assign_number (ecma_value_t *value_p, /**< [in, out] ecma value */
|
||||
ecma_number_t ecma_number) /**< number to assign */
|
||||
{
|
||||
ecma_integer_value_t integer_value = (ecma_integer_value_t) ecma_number;
|
||||
|
||||
if ((ecma_number_t) integer_value == ecma_number
|
||||
&& ((integer_value == 0) ? ecma_is_number_equal_to_positive_zero (ecma_number)
|
||||
: ECMA_IS_INTEGER_NUMBER (integer_value)))
|
||||
{
|
||||
if (ecma_get_value_type_field (*value_p) != ECMA_TYPE_DIRECT
|
||||
&& ecma_get_value_type_field (*value_p) != ECMA_TYPE_OBJECT)
|
||||
{
|
||||
ecma_free_value (*value_p);
|
||||
}
|
||||
*value_p = ecma_make_integer_value (integer_value);
|
||||
return;
|
||||
}
|
||||
|
||||
ecma_value_assign_float_number (value_p, ecma_number);
|
||||
} /* ecma_value_assign_number */
|
||||
|
||||
/**
|
||||
* Assign an uint32 value to an ecma-value
|
||||
*
|
||||
* Note:
|
||||
* value previously stored in the property is freed
|
||||
*/
|
||||
void
|
||||
ecma_value_assign_uint32 (ecma_value_t *value_p, /**< [in, out] ecma value */
|
||||
uint32_t uint32_number) /**< number to assign */
|
||||
{
|
||||
if (uint32_number <= ECMA_INTEGER_NUMBER_MAX)
|
||||
{
|
||||
if (ecma_get_value_type_field (*value_p) != ECMA_TYPE_DIRECT
|
||||
&& ecma_get_value_type_field (*value_p) != ECMA_TYPE_OBJECT)
|
||||
{
|
||||
ecma_free_value (*value_p);
|
||||
}
|
||||
|
||||
*value_p = ecma_make_integer_value ((ecma_integer_value_t) uint32_number);
|
||||
return;
|
||||
}
|
||||
|
||||
ecma_value_assign_float_number (value_p, (ecma_number_t) uint32_number);
|
||||
} /* ecma_value_assign_uint32 */
|
||||
|
||||
/**
|
||||
* Free the ecma value
|
||||
*/
|
||||
void
|
||||
ecma_free_value (ecma_value_t value) /**< value description */
|
||||
{
|
||||
switch (ecma_get_value_type_field (value))
|
||||
{
|
||||
case ECMA_TYPE_DIRECT:
|
||||
{
|
||||
/* no memory is allocated */
|
||||
break;
|
||||
}
|
||||
|
||||
case ECMA_TYPE_FLOAT:
|
||||
{
|
||||
ecma_number_t *number_p = (ecma_number_t *) ecma_get_pointer_from_ecma_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:
|
||||
{
|
||||
ecma_deref_object (ecma_get_object_from_value (value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /* ecma_free_value */
|
||||
|
||||
/**
|
||||
* Free the ecma value
|
||||
*
|
||||
* Note:
|
||||
* this function is similar to ecma_free_value, but it is
|
||||
* faster for direct values since no function call is performed.
|
||||
* It also increases the binary size so it is recommended for
|
||||
* critical code paths only.
|
||||
*/
|
||||
inline void __attr_always_inline___
|
||||
ecma_fast_free_value (ecma_value_t value) /**< value description */
|
||||
{
|
||||
if (ecma_get_value_type_field (value) != ECMA_TYPE_DIRECT)
|
||||
{
|
||||
ecma_free_value (value);
|
||||
}
|
||||
} /* ecma_fast_free_value */
|
||||
|
||||
/**
|
||||
* Free the ecma value if not an object
|
||||
*/
|
||||
void
|
||||
ecma_free_value_if_not_object (ecma_value_t value) /**< value description */
|
||||
{
|
||||
if (ecma_get_value_type_field (value) != ECMA_TYPE_OBJECT)
|
||||
{
|
||||
ecma_free_value (value);
|
||||
}
|
||||
} /* ecma_free_value_if_not_object */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
374
third_party/jerryscript/jerry-core/ecma/base/ecma-helpers-values-collection.c
vendored
Normal file
374
third_party/jerryscript/jerry-core/ecma/base/ecma-helpers-values-collection.c
vendored
Normal file
|
@ -0,0 +1,374 @@
|
|||
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
|
||||
* Copyright 2016 University of Szeged.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecma-alloc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "jrt.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmahelpers Helpers for operations with ECMA data types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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 || values_number == 0);
|
||||
|
||||
const size_t values_in_chunk = JERRY_SIZE_OF_STRUCT_MEMBER (ecma_collection_chunk_t, data) / sizeof (ecma_value_t);
|
||||
|
||||
ecma_collection_header_t *header_p = ecma_alloc_collection_header ();
|
||||
|
||||
header_p->unit_number = values_number;
|
||||
|
||||
jmem_cpointer_t *next_chunk_cp_p = &header_p->first_chunk_cp;
|
||||
ecma_collection_chunk_t *last_chunk_p = NULL;
|
||||
ecma_value_t *cur_value_buf_iter_p = NULL;
|
||||
ecma_value_t *cur_value_buf_end_p = NULL;
|
||||
|
||||
for (ecma_length_t value_index = 0;
|
||||
value_index < values_number;
|
||||
value_index++)
|
||||
{
|
||||
if (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 + values_in_chunk;
|
||||
|
||||
last_chunk_p = chunk_p;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (cur_value_buf_iter_p + 1 <= cur_value_buf_end_p);
|
||||
|
||||
if (do_ref_if_object)
|
||||
{
|
||||
*cur_value_buf_iter_p++ = ecma_copy_value (values_buffer[value_index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
*cur_value_buf_iter_p++ = ecma_copy_value_if_not_object (values_buffer[value_index]);
|
||||
}
|
||||
}
|
||||
|
||||
*next_chunk_cp_p = ECMA_NULL_POINTER;
|
||||
ECMA_SET_POINTER (header_p->last_chunk_cp, last_chunk_p);
|
||||
|
||||
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);
|
||||
|
||||
const size_t values_in_chunk = JERRY_SIZE_OF_STRUCT_MEMBER (ecma_collection_chunk_t, data) / sizeof (ecma_value_t);
|
||||
|
||||
ecma_collection_chunk_t *chunk_p = ECMA_GET_POINTER (ecma_collection_chunk_t,
|
||||
header_p->first_chunk_cp);
|
||||
ecma_length_t value_index = 0;
|
||||
|
||||
while (chunk_p != NULL)
|
||||
{
|
||||
JERRY_ASSERT (value_index < header_p->unit_number);
|
||||
|
||||
ecma_value_t *cur_value_buf_iter_p = (ecma_value_t *) chunk_p->data;
|
||||
ecma_value_t *cur_value_buf_end_p = cur_value_buf_iter_p + values_in_chunk;
|
||||
|
||||
while (cur_value_buf_iter_p != cur_value_buf_end_p
|
||||
&& value_index < header_p->unit_number)
|
||||
{
|
||||
JERRY_ASSERT (cur_value_buf_iter_p < cur_value_buf_end_p);
|
||||
|
||||
if (do_deref_if_object)
|
||||
{
|
||||
ecma_free_value (*cur_value_buf_iter_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_free_value_if_not_object (*cur_value_buf_iter_p);
|
||||
}
|
||||
|
||||
cur_value_buf_iter_p++;
|
||||
value_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 */
|
||||
|
||||
/**
|
||||
* Append new value to ecma values collection
|
||||
*/
|
||||
void
|
||||
ecma_append_to_values_collection (ecma_collection_header_t *header_p, /**< collection's header */
|
||||
ecma_value_t v, /**< ecma value to append */
|
||||
bool do_ref_if_object) /**< if the value is object value,
|
||||
increase reference counter of the object */
|
||||
{
|
||||
const size_t values_in_chunk = JERRY_SIZE_OF_STRUCT_MEMBER (ecma_collection_chunk_t, data) / sizeof (ecma_value_t);
|
||||
|
||||
size_t values_number = header_p->unit_number;
|
||||
size_t pos_of_new_value_in_chunk = values_number % values_in_chunk;
|
||||
|
||||
values_number++;
|
||||
|
||||
if ((ecma_length_t) values_number == values_number)
|
||||
{
|
||||
header_p->unit_number = (ecma_length_t) values_number;
|
||||
}
|
||||
else
|
||||
{
|
||||
jerry_fatal (ERR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
ecma_collection_chunk_t *chunk_p = ECMA_GET_POINTER (ecma_collection_chunk_t,
|
||||
header_p->last_chunk_cp);
|
||||
|
||||
if (pos_of_new_value_in_chunk == 0)
|
||||
{
|
||||
/* all chunks are currently filled with values */
|
||||
|
||||
chunk_p = ecma_alloc_collection_chunk ();
|
||||
chunk_p->next_chunk_cp = ECMA_NULL_POINTER;
|
||||
|
||||
if (header_p->last_chunk_cp == ECMA_NULL_POINTER)
|
||||
{
|
||||
JERRY_ASSERT (header_p->first_chunk_cp == ECMA_NULL_POINTER);
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER (header_p->first_chunk_cp, chunk_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_collection_chunk_t *last_chunk_p = ECMA_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
|
||||
header_p->last_chunk_cp);
|
||||
|
||||
JERRY_ASSERT (last_chunk_p->next_chunk_cp == ECMA_NULL_POINTER);
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER (last_chunk_p->next_chunk_cp, chunk_p);
|
||||
}
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER (header_p->last_chunk_cp, chunk_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* last chunk can be appended with the new value */
|
||||
JERRY_ASSERT (chunk_p != NULL);
|
||||
}
|
||||
|
||||
ecma_value_t *values_p = (ecma_value_t *) chunk_p->data;
|
||||
|
||||
JERRY_ASSERT ((uint8_t *) (values_p + pos_of_new_value_in_chunk + 1) <= (uint8_t *) (chunk_p + 1));
|
||||
|
||||
if (do_ref_if_object)
|
||||
{
|
||||
values_p[pos_of_new_value_in_chunk] = ecma_copy_value (v);
|
||||
}
|
||||
else
|
||||
{
|
||||
values_p[pos_of_new_value_in_chunk] = ecma_copy_value_if_not_object (v);
|
||||
}
|
||||
} /* ecma_append_to_values_collection */
|
||||
|
||||
/**
|
||||
* Remove last element of the collection
|
||||
*
|
||||
* Warning:
|
||||
* the function invalidates all iterators that are configured to access the passed collection
|
||||
*/
|
||||
void
|
||||
ecma_remove_last_value_from_values_collection (ecma_collection_header_t *header_p) /**< collection's header */
|
||||
{
|
||||
JERRY_ASSERT (header_p != NULL && header_p->unit_number > 0);
|
||||
|
||||
const size_t values_in_chunk = JERRY_SIZE_OF_STRUCT_MEMBER (ecma_collection_chunk_t, data) / sizeof (ecma_value_t);
|
||||
size_t values_number = header_p->unit_number;
|
||||
size_t pos_of_value_to_remove_in_chunk = (values_number - 1u) % values_in_chunk;
|
||||
|
||||
ecma_collection_chunk_t *last_chunk_p = ECMA_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
|
||||
header_p->last_chunk_cp);
|
||||
|
||||
ecma_value_t *values_p = (ecma_value_t *) last_chunk_p->data;
|
||||
JERRY_ASSERT ((uint8_t *) (values_p + pos_of_value_to_remove_in_chunk + 1) <= (uint8_t *) (last_chunk_p + 1));
|
||||
|
||||
ecma_value_t value_to_remove = values_p[pos_of_value_to_remove_in_chunk];
|
||||
|
||||
ecma_free_value (value_to_remove);
|
||||
|
||||
header_p->unit_number--;
|
||||
|
||||
if (pos_of_value_to_remove_in_chunk == 0)
|
||||
{
|
||||
ecma_collection_chunk_t *chunk_to_remove_p = last_chunk_p;
|
||||
|
||||
/* free last chunk */
|
||||
if (header_p->first_chunk_cp == header_p->last_chunk_cp)
|
||||
{
|
||||
header_p->first_chunk_cp = ECMA_NULL_POINTER;
|
||||
header_p->last_chunk_cp = ECMA_NULL_POINTER;
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_collection_chunk_t *chunk_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
|
||||
header_p->first_chunk_cp);
|
||||
|
||||
while (chunk_iter_p->next_chunk_cp != header_p->last_chunk_cp)
|
||||
{
|
||||
chunk_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
|
||||
chunk_iter_p->next_chunk_cp);
|
||||
}
|
||||
|
||||
ecma_collection_chunk_t *new_last_chunk_p = chunk_iter_p;
|
||||
|
||||
JERRY_ASSERT (ECMA_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
|
||||
new_last_chunk_p->next_chunk_cp) == chunk_to_remove_p);
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER (header_p->last_chunk_cp, new_last_chunk_p);
|
||||
new_last_chunk_p->next_chunk_cp = ECMA_NULL_POINTER;
|
||||
}
|
||||
|
||||
ecma_dealloc_collection_chunk (chunk_to_remove_p);
|
||||
}
|
||||
} /* ecma_remove_last_value_from_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 || strings_number == 0);
|
||||
|
||||
ecma_collection_header_t *new_collection_p;
|
||||
|
||||
new_collection_p = ecma_new_values_collection (NULL, 0, false);
|
||||
|
||||
for (ecma_length_t string_index = 0;
|
||||
string_index < strings_number;
|
||||
string_index++)
|
||||
{
|
||||
ecma_append_to_values_collection (new_collection_p,
|
||||
ecma_make_string_value (string_ptrs_buffer[string_index]),
|
||||
false);
|
||||
}
|
||||
|
||||
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 != NULL ? collection_p->first_chunk_cp : JMEM_CP_NULL);
|
||||
iterator_p->current_index = 0;
|
||||
iterator_p->current_value_p = NULL;
|
||||
iterator_p->current_chunk_end_p = NULL;
|
||||
} /* 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 (iterator_p->header_p == NULL
|
||||
|| unlikely (iterator_p->header_p->unit_number == 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t values_in_chunk = JERRY_SIZE_OF_STRUCT_MEMBER (ecma_collection_chunk_t, data) / sizeof (ecma_value_t);
|
||||
|
||||
if (iterator_p->current_value_p == NULL)
|
||||
{
|
||||
JERRY_ASSERT (iterator_p->current_index == 0);
|
||||
|
||||
ecma_collection_chunk_t *first_chunk_p = ECMA_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
|
||||
iterator_p->header_p->first_chunk_cp);
|
||||
|
||||
iterator_p->next_chunk_cp = first_chunk_p->next_chunk_cp;
|
||||
iterator_p->current_value_p = (ecma_value_t *) &first_chunk_p->data;
|
||||
iterator_p->current_chunk_end_p = (iterator_p->current_value_p + values_in_chunk);
|
||||
}
|
||||
else
|
||||
{
|
||||
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 + values_in_chunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (iterator_p->current_value_p < iterator_p->current_chunk_end_p);
|
||||
}
|
||||
|
||||
return true;
|
||||
} /* ecma_collection_iterator_next */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
1400
third_party/jerryscript/jerry-core/ecma/base/ecma-helpers.c
vendored
Normal file
1400
third_party/jerryscript/jerry-core/ecma/base/ecma-helpers.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
340
third_party/jerryscript/jerry-core/ecma/base/ecma-helpers.h
vendored
Normal file
340
third_party/jerryscript/jerry-core/ecma/base/ecma-helpers.h
vendored
Normal file
|
@ -0,0 +1,340 @@
|
|||
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
|
||||
* Copyright 2015-2016 University of Szeged.
|
||||
*
|
||||
* 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_HELPERS_H
|
||||
#define ECMA_HELPERS_H
|
||||
|
||||
#include "ecma-globals.h"
|
||||
#include "jmem-allocator.h"
|
||||
#include "lit-strings.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmahelpers Helpers for operations with ECMA data types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get value of pointer from specified non-null compressed pointer.
|
||||
*/
|
||||
#define ECMA_GET_NON_NULL_POINTER(type, field) JMEM_CP_GET_NON_NULL_POINTER (type, field)
|
||||
|
||||
/**
|
||||
* Get value of pointer from specified compressed pointer.
|
||||
*/
|
||||
#define ECMA_GET_POINTER(type, field) JMEM_CP_GET_POINTER (type, field)
|
||||
|
||||
/**
|
||||
* Set value of non-null compressed pointer so that it will correspond
|
||||
* to specified non_compressed_pointer.
|
||||
*/
|
||||
#define ECMA_SET_NON_NULL_POINTER(field, non_compressed_pointer) JMEM_CP_SET_NON_NULL_POINTER (field, \
|
||||
non_compressed_pointer)
|
||||
|
||||
/**
|
||||
* Set value of compressed pointer so that it will correspond
|
||||
* to specified non_compressed_pointer.
|
||||
*/
|
||||
#define ECMA_SET_POINTER(field, non_compressed_pointer) JMEM_CP_SET_POINTER (field, non_compressed_pointer)
|
||||
|
||||
/**
|
||||
* Convert ecma-string's contents to a cesu-8 string and put it into a buffer.
|
||||
*/
|
||||
#define ECMA_STRING_TO_UTF8_STRING(ecma_str_ptr, /**< ecma string pointer */ \
|
||||
utf8_ptr, /**< [out] output buffer pointer */ \
|
||||
utf8_str_size) /**< [out] output buffer size */ \
|
||||
lit_utf8_size_t utf8_str_size; \
|
||||
bool utf8_ptr ## must_be_freed; \
|
||||
const lit_utf8_byte_t *utf8_ptr = ecma_string_raw_chars (ecma_str_ptr, &utf8_str_size, &utf8_ptr ## must_be_freed); \
|
||||
utf8_ptr ## must_be_freed = false; /* it was used as 'is_ascii' in 'ecma_string_raw_chars', so we must reset it */ \
|
||||
\
|
||||
if (utf8_ptr == NULL) \
|
||||
{ \
|
||||
utf8_ptr = (const lit_utf8_byte_t *) jmem_heap_alloc_block (utf8_str_size); \
|
||||
ecma_string_to_utf8_bytes (ecma_str_ptr, (lit_utf8_byte_t *) utf8_ptr, utf8_str_size); \
|
||||
utf8_ptr ## must_be_freed = true; \
|
||||
}
|
||||
|
||||
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
|
||||
|
||||
/**
|
||||
* Set an internal property value of pointer
|
||||
*/
|
||||
#define ECMA_SET_INTERNAL_VALUE_POINTER(field, pointer) \
|
||||
(field) = ((ecma_value_t) pointer)
|
||||
|
||||
/**
|
||||
* Get an internal property value of pointer
|
||||
*/
|
||||
#define ECMA_GET_INTERNAL_VALUE_POINTER(type, field) \
|
||||
((type *) field)
|
||||
|
||||
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
|
||||
|
||||
/**
|
||||
* Set an internal property value of non-null pointer so that it will correspond
|
||||
* to specified non_compressed_pointer.
|
||||
*/
|
||||
#define ECMA_SET_INTERNAL_VALUE_POINTER(field, non_compressed_pointer) \
|
||||
ECMA_SET_NON_NULL_POINTER (field, non_compressed_pointer)
|
||||
|
||||
/**
|
||||
* Get an internal property value of pointer from specified compressed pointer.
|
||||
*/
|
||||
#define ECMA_GET_INTERNAL_VALUE_POINTER(type, field) \
|
||||
ECMA_GET_POINTER (type, field)
|
||||
|
||||
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
|
||||
|
||||
/**
|
||||
* Free the cesu-8 string buffer allocated by 'ECMA_STRING_TO_UTF8_STRING'
|
||||
*/
|
||||
#define ECMA_FINALIZE_UTF8_STRING(utf8_ptr, /**< pointer to character buffer */ \
|
||||
utf8_str_size) /**< buffer size */ \
|
||||
if (utf8_ptr ## must_be_freed) \
|
||||
{ \
|
||||
JERRY_ASSERT (utf8_ptr != NULL); \
|
||||
jmem_heap_free_block ((void *) utf8_ptr, utf8_str_size); \
|
||||
}
|
||||
|
||||
/* ecma-helpers-value.c */
|
||||
extern bool ecma_is_value_direct (ecma_value_t) __attr_pure___;
|
||||
extern bool ecma_is_value_simple (ecma_value_t) __attr_pure___;
|
||||
extern bool ecma_is_value_empty (ecma_value_t) __attr_pure___;
|
||||
extern bool ecma_is_value_undefined (ecma_value_t) __attr_pure___;
|
||||
extern bool ecma_is_value_null (ecma_value_t) __attr_pure___;
|
||||
extern bool ecma_is_value_boolean (ecma_value_t) __attr_pure___;
|
||||
extern bool ecma_is_value_true (ecma_value_t) __attr_pure___;
|
||||
extern bool ecma_is_value_false (ecma_value_t) __attr_pure___;
|
||||
extern bool ecma_is_value_found (ecma_value_t) __attr_pure___;
|
||||
extern bool ecma_is_value_array_hole (ecma_value_t) __attr_pure___;
|
||||
|
||||
extern bool ecma_is_value_integer_number (ecma_value_t) __attr_pure___;
|
||||
extern bool ecma_are_values_integer_numbers (ecma_value_t, ecma_value_t) __attr_pure___;
|
||||
extern bool ecma_is_value_float_number (ecma_value_t) __attr_pure___;
|
||||
extern bool ecma_is_value_number (ecma_value_t) __attr_pure___;
|
||||
extern bool ecma_is_value_string (ecma_value_t) __attr_pure___;
|
||||
extern bool ecma_is_value_object (ecma_value_t) __attr_pure___;
|
||||
|
||||
extern void ecma_check_value_type_is_spec_defined (ecma_value_t);
|
||||
|
||||
extern ecma_value_t ecma_make_simple_value (const ecma_simple_value_t value) __attr_const___;
|
||||
extern ecma_value_t ecma_make_boolean_value (bool) __attr_const___;
|
||||
extern ecma_value_t ecma_make_integer_value (ecma_integer_value_t) __attr_const___;
|
||||
extern ecma_value_t ecma_make_nan_value (void);
|
||||
extern ecma_value_t ecma_make_number_value (ecma_number_t);
|
||||
extern ecma_value_t ecma_make_int32_value (int32_t);
|
||||
extern ecma_value_t ecma_make_uint32_value (uint32_t);
|
||||
extern ecma_value_t ecma_make_string_value (const ecma_string_t *);
|
||||
extern ecma_value_t ecma_make_object_value (const ecma_object_t *);
|
||||
extern ecma_value_t ecma_make_error_value (ecma_value_t);
|
||||
extern ecma_value_t ecma_make_error_obj_value (const ecma_object_t *);
|
||||
extern ecma_integer_value_t ecma_get_integer_from_value (ecma_value_t) __attr_pure___;
|
||||
extern ecma_number_t ecma_get_float_from_value (ecma_value_t) __attr_pure___;
|
||||
extern ecma_number_t ecma_get_number_from_value (ecma_value_t) __attr_pure___;
|
||||
extern uint32_t ecma_get_uint32_from_value (ecma_value_t) __attr_pure___;
|
||||
extern ecma_string_t *ecma_get_string_from_value (ecma_value_t) __attr_pure___;
|
||||
extern ecma_object_t *ecma_get_object_from_value (ecma_value_t) __attr_pure___;
|
||||
extern ecma_value_t ecma_get_value_from_error_value (ecma_value_t) __attr_pure___;
|
||||
extern ecma_value_t ecma_invert_boolean_value (ecma_value_t) __attr_pure___;
|
||||
extern ecma_value_t ecma_copy_value (ecma_value_t);
|
||||
extern ecma_value_t ecma_fast_copy_value (ecma_value_t);
|
||||
extern ecma_value_t ecma_copy_value_if_not_object (ecma_value_t);
|
||||
extern ecma_value_t ecma_update_float_number (ecma_value_t, ecma_number_t);
|
||||
extern void ecma_value_assign_value (ecma_value_t *, ecma_value_t);
|
||||
extern void ecma_value_assign_number (ecma_value_t *, ecma_number_t);
|
||||
extern void ecma_value_assign_uint32 (ecma_value_t *, uint32_t);
|
||||
extern void ecma_free_value (ecma_value_t);
|
||||
extern void ecma_fast_free_value (ecma_value_t);
|
||||
extern void ecma_free_value_if_not_object (ecma_value_t);
|
||||
|
||||
/* ecma-helpers-string.c */
|
||||
extern ecma_string_t *ecma_new_ecma_string_from_utf8 (const lit_utf8_byte_t *, lit_utf8_size_t);
|
||||
extern ecma_string_t *ecma_new_ecma_string_from_utf8_to_cesu8 (const lit_utf8_byte_t *, lit_utf8_size_t);
|
||||
extern ecma_string_t *ecma_new_ecma_string_from_code_unit (ecma_char_t);
|
||||
extern ecma_string_t *ecma_new_ecma_string_from_uint32 (uint32_t);
|
||||
extern ecma_string_t *ecma_new_ecma_string_from_number (ecma_number_t);
|
||||
extern ecma_string_t *ecma_new_ecma_string_from_magic_string_id (lit_magic_string_id_t);
|
||||
extern ecma_string_t *ecma_new_ecma_string_from_magic_string_ex_id (lit_magic_string_ex_id_t);
|
||||
extern ecma_string_t *ecma_new_ecma_length_string ();
|
||||
extern ecma_string_t *ecma_concat_ecma_strings (ecma_string_t *, ecma_string_t *);
|
||||
extern void ecma_ref_ecma_string (ecma_string_t *);
|
||||
extern void ecma_deref_ecma_string (ecma_string_t *);
|
||||
extern ecma_number_t ecma_string_to_number (const ecma_string_t *);
|
||||
extern bool ecma_string_get_array_index (const ecma_string_t *, uint32_t *);
|
||||
|
||||
extern lit_utf8_size_t __attr_return_value_should_be_checked___
|
||||
ecma_string_copy_to_utf8_buffer (const ecma_string_t *, lit_utf8_byte_t *, lit_utf8_size_t);
|
||||
|
||||
extern lit_utf8_size_t __attr_return_value_should_be_checked___
|
||||
ecma_string_copy_and_convert_to_utf8_buffer (const ecma_string_t *, lit_utf8_byte_t *, lit_utf8_size_t);
|
||||
|
||||
extern void ecma_string_to_utf8_bytes (const ecma_string_t *, lit_utf8_byte_t *, lit_utf8_size_t);
|
||||
extern const lit_utf8_byte_t *ecma_string_raw_chars (const ecma_string_t *, lit_utf8_size_t *, bool *);
|
||||
extern void ecma_init_ecma_string_from_uint32 (ecma_string_t *, uint32_t);
|
||||
extern void ecma_init_ecma_length_string (ecma_string_t *);
|
||||
extern bool ecma_string_is_empty (const ecma_string_t *);
|
||||
extern bool ecma_string_is_length (const ecma_string_t *);
|
||||
|
||||
extern bool ecma_compare_ecma_strings_equal_hashes (const ecma_string_t *, const ecma_string_t *);
|
||||
extern bool ecma_compare_ecma_strings (const ecma_string_t *, const ecma_string_t *);
|
||||
extern bool ecma_compare_ecma_strings_relational (const ecma_string_t *, const ecma_string_t *);
|
||||
extern ecma_length_t ecma_string_get_length (const ecma_string_t *);
|
||||
extern lit_utf8_size_t ecma_string_get_size (const ecma_string_t *);
|
||||
extern lit_utf8_size_t ecma_string_get_utf8_size (const ecma_string_t *);
|
||||
extern ecma_char_t ecma_string_get_char_at_pos (const ecma_string_t *, ecma_length_t);
|
||||
|
||||
extern ecma_string_t *ecma_get_magic_string (lit_magic_string_id_t);
|
||||
extern ecma_string_t *ecma_get_magic_string_ex (lit_magic_string_ex_id_t);
|
||||
extern bool ecma_is_string_magic (const ecma_string_t *, lit_magic_string_id_t *);
|
||||
|
||||
extern lit_string_hash_t ecma_string_hash (const ecma_string_t *);
|
||||
extern ecma_string_t *ecma_string_substr (const ecma_string_t *, ecma_length_t, ecma_length_t);
|
||||
extern ecma_string_t *ecma_string_trim (const ecma_string_t *);
|
||||
|
||||
/* ecma-helpers-number.c */
|
||||
extern ecma_number_t ecma_number_make_nan (void);
|
||||
extern ecma_number_t ecma_number_make_infinity (bool);
|
||||
extern bool ecma_number_is_nan (ecma_number_t);
|
||||
extern bool ecma_number_is_negative (ecma_number_t);
|
||||
extern bool ecma_number_is_zero (ecma_number_t);
|
||||
extern bool ecma_number_is_infinity (ecma_number_t);
|
||||
extern int32_t
|
||||
ecma_number_get_fraction_and_exponent (ecma_number_t, uint64_t *, int32_t *);
|
||||
extern ecma_number_t
|
||||
ecma_number_make_normal_positive_from_fraction_and_exponent (uint64_t, int32_t);
|
||||
extern ecma_number_t
|
||||
ecma_number_make_from_sign_mantissa_and_exponent (bool, uint64_t, int32_t);
|
||||
extern ecma_number_t ecma_number_get_prev (ecma_number_t);
|
||||
extern ecma_number_t ecma_number_get_next (ecma_number_t);
|
||||
extern ecma_number_t ecma_number_negate (ecma_number_t);
|
||||
extern ecma_number_t ecma_number_trunc (ecma_number_t);
|
||||
extern ecma_number_t ecma_number_calc_remainder (ecma_number_t, ecma_number_t);
|
||||
extern ecma_number_t ecma_number_add (ecma_number_t, ecma_number_t);
|
||||
extern ecma_number_t ecma_number_substract (ecma_number_t, ecma_number_t);
|
||||
extern ecma_number_t ecma_number_multiply (ecma_number_t, ecma_number_t);
|
||||
extern ecma_number_t ecma_number_divide (ecma_number_t, ecma_number_t);
|
||||
extern lit_utf8_size_t ecma_number_to_decimal (ecma_number_t, lit_utf8_byte_t *, int32_t *);
|
||||
|
||||
/* ecma-helpers-values-collection.c */
|
||||
extern ecma_collection_header_t *ecma_new_values_collection (const ecma_value_t[], ecma_length_t, bool);
|
||||
extern void ecma_free_values_collection (ecma_collection_header_t *, bool);
|
||||
extern void ecma_append_to_values_collection (ecma_collection_header_t *, ecma_value_t, bool);
|
||||
extern void ecma_remove_last_value_from_values_collection (ecma_collection_header_t *);
|
||||
extern ecma_collection_header_t *ecma_new_strings_collection (ecma_string_t *[], ecma_length_t);
|
||||
|
||||
/**
|
||||
* Context of ecma values' collection iterator
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ecma_collection_header_t *header_p; /**< collection header */
|
||||
jmem_cpointer_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 *, ecma_collection_header_t *);
|
||||
extern bool
|
||||
ecma_collection_iterator_next (ecma_collection_iterator_t *);
|
||||
|
||||
/* ecma-helpers.c */
|
||||
extern ecma_object_t *ecma_create_object (ecma_object_t *, bool, bool, ecma_object_type_t);
|
||||
extern ecma_object_t *ecma_create_decl_lex_env (ecma_object_t *);
|
||||
extern ecma_object_t *ecma_create_object_lex_env (ecma_object_t *, ecma_object_t *, bool);
|
||||
extern bool ecma_is_lexical_environment (const ecma_object_t *) __attr_pure___;
|
||||
extern bool ecma_get_object_extensible (const ecma_object_t *) __attr_pure___;
|
||||
extern void ecma_set_object_extensible (ecma_object_t *, bool);
|
||||
extern ecma_object_type_t ecma_get_object_type (const ecma_object_t *) __attr_pure___;
|
||||
extern void ecma_set_object_type (ecma_object_t *, ecma_object_type_t);
|
||||
extern ecma_object_t *ecma_get_object_prototype (const ecma_object_t *) __attr_pure___;
|
||||
extern bool ecma_get_object_is_builtin (const ecma_object_t *) __attr_pure___;
|
||||
extern void ecma_set_object_is_builtin (ecma_object_t *);
|
||||
extern ecma_lexical_environment_type_t ecma_get_lex_env_type (const ecma_object_t *) __attr_pure___;
|
||||
extern ecma_object_t *ecma_get_lex_env_outer_reference (const ecma_object_t *) __attr_pure___;
|
||||
extern ecma_property_header_t *ecma_get_property_list (const ecma_object_t *) __attr_pure___;
|
||||
extern ecma_object_t *ecma_get_lex_env_binding_object (const ecma_object_t *) __attr_pure___;
|
||||
extern bool ecma_get_lex_env_provide_this (const ecma_object_t *) __attr_pure___;
|
||||
|
||||
extern ecma_value_t *ecma_create_internal_property (ecma_object_t *, ecma_internal_property_id_t);
|
||||
extern ecma_value_t *ecma_find_internal_property (ecma_object_t *, ecma_internal_property_id_t);
|
||||
extern ecma_value_t *ecma_get_internal_property (ecma_object_t *, ecma_internal_property_id_t);
|
||||
|
||||
extern ecma_property_value_t *
|
||||
ecma_create_named_data_property (ecma_object_t *, ecma_string_t *, uint8_t, ecma_property_t **);
|
||||
extern ecma_property_value_t *
|
||||
ecma_create_named_accessor_property (ecma_object_t *, ecma_string_t *, ecma_object_t *, ecma_object_t *, uint8_t);
|
||||
extern ecma_property_t *
|
||||
ecma_find_named_property (ecma_object_t *, ecma_string_t *);
|
||||
extern ecma_property_value_t *
|
||||
ecma_get_named_data_property (ecma_object_t *, ecma_string_t *);
|
||||
|
||||
extern void ecma_free_property (ecma_object_t *, ecma_string_t *, ecma_property_t *);
|
||||
|
||||
extern void ecma_delete_property (ecma_object_t *, ecma_property_value_t *);
|
||||
|
||||
extern void ecma_named_data_property_assign_value (ecma_object_t *, ecma_property_value_t *, ecma_value_t);
|
||||
|
||||
extern ecma_object_t *ecma_get_named_accessor_property_getter (const ecma_property_value_t *);
|
||||
extern ecma_object_t *ecma_get_named_accessor_property_setter (const ecma_property_value_t *);
|
||||
extern void ecma_set_named_accessor_property_getter (ecma_object_t *, ecma_property_value_t *, ecma_object_t *);
|
||||
extern void ecma_set_named_accessor_property_setter (ecma_object_t *, ecma_property_value_t *, ecma_object_t *);
|
||||
extern bool ecma_is_property_writable (ecma_property_t);
|
||||
extern void ecma_set_property_writable_attr (ecma_property_t *, bool);
|
||||
extern bool ecma_is_property_enumerable (ecma_property_t);
|
||||
extern void ecma_set_property_enumerable_attr (ecma_property_t *, bool);
|
||||
extern bool ecma_is_property_configurable (ecma_property_t);
|
||||
extern void ecma_set_property_configurable_attr (ecma_property_t *, bool);
|
||||
|
||||
extern bool ecma_is_property_lcached (ecma_property_t *);
|
||||
extern void ecma_set_property_lcached (ecma_property_t *, bool);
|
||||
|
||||
extern ecma_property_descriptor_t ecma_make_empty_property_descriptor (void);
|
||||
extern void ecma_free_property_descriptor (ecma_property_descriptor_t *);
|
||||
|
||||
extern ecma_property_t *ecma_get_next_property_pair (ecma_property_pair_t *);
|
||||
|
||||
extern void ecma_bytecode_ref (ecma_compiled_code_t *);
|
||||
extern void ecma_bytecode_deref (ecma_compiled_code_t *);
|
||||
|
||||
/* ecma-helpers-external-pointers.c */
|
||||
extern bool
|
||||
ecma_create_external_pointer_property (ecma_object_t *, ecma_internal_property_id_t, ecma_external_pointer_t);
|
||||
extern bool
|
||||
ecma_get_external_pointer_value (ecma_object_t *, ecma_internal_property_id_t, ecma_external_pointer_t *);
|
||||
extern void
|
||||
ecma_free_external_pointer_in_property (ecma_property_t *);
|
||||
|
||||
/* ecma-helpers-conversion.c */
|
||||
extern ecma_number_t ecma_utf8_string_to_number (const lit_utf8_byte_t *, lit_utf8_size_t);
|
||||
extern lit_utf8_size_t ecma_uint32_to_utf8_string (uint32_t, lit_utf8_byte_t *, lit_utf8_size_t);
|
||||
extern uint32_t ecma_number_to_uint32 (ecma_number_t);
|
||||
extern int32_t ecma_number_to_int32 (ecma_number_t);
|
||||
extern lit_utf8_size_t ecma_number_to_utf8_string (ecma_number_t, lit_utf8_byte_t *, lit_utf8_size_t);
|
||||
|
||||
/* ecma-helpers-errol.c */
|
||||
extern lit_utf8_size_t ecma_errol0_dtoa (double, lit_utf8_byte_t *, int32_t *);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* !ECMA_HELPERS_H */
|
61
third_party/jerryscript/jerry-core/ecma/base/ecma-init-finalize.c
vendored
Normal file
61
third_party/jerryscript/jerry-core/ecma/base/ecma-init-finalize.c
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
/* Copyright 2014-2016 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-builtins.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-init-finalize.h"
|
||||
#include "ecma-lcache.h"
|
||||
#include "ecma-lex-env.h"
|
||||
#include "ecma-literal-storage.h"
|
||||
#include "jmem-allocator.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmainitfinalize Initialization and finalization of ECMA components
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialize ECMA components
|
||||
*/
|
||||
void
|
||||
ecma_init (void)
|
||||
{
|
||||
ecma_lcache_init ();
|
||||
ecma_init_global_lex_env ();
|
||||
|
||||
jmem_register_free_unused_memory_callback (ecma_free_unused_memory);
|
||||
} /* ecma_init */
|
||||
|
||||
/**
|
||||
* Finalize ECMA components
|
||||
*/
|
||||
void
|
||||
ecma_finalize (void)
|
||||
{
|
||||
jmem_unregister_free_unused_memory_callback (ecma_free_unused_memory);
|
||||
|
||||
ecma_finalize_global_lex_env ();
|
||||
ecma_finalize_builtins ();
|
||||
ecma_gc_run (JMEM_FREE_UNUSED_MEMORY_SEVERITY_LOW);
|
||||
ecma_finalize_lit_storage ();
|
||||
} /* ecma_finalize */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
34
third_party/jerryscript/jerry-core/ecma/base/ecma-init-finalize.h
vendored
Normal file
34
third_party/jerryscript/jerry-core/ecma/base/ecma-init-finalize.h
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* Copyright 2014-2016 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_INIT_FINALIZE_H
|
||||
#define ECMA_INIT_FINALIZE_H
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmainitfinalize Initialization and finalization of ECMA components
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern void ecma_init (void);
|
||||
extern void ecma_finalize (void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* !ECMA_INIT_FINALIZE_H */
|
229
third_party/jerryscript/jerry-core/ecma/base/ecma-lcache.c
vendored
Normal file
229
third_party/jerryscript/jerry-core/ecma/base/ecma-lcache.c
vendored
Normal file
|
@ -0,0 +1,229 @@
|
|||
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
|
||||
* Copyright 2016 University of Szeged.
|
||||
*
|
||||
* 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 "jcontext.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmalcache Property lookup cache
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_ECMA_LCACHE_DISABLE
|
||||
|
||||
/**
|
||||
* Mask for hash bits
|
||||
*/
|
||||
#define ECMA_LCACHE_HASH_MASK (ECMA_LCACHE_HASH_ROWS_COUNT - 1)
|
||||
|
||||
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */
|
||||
|
||||
/**
|
||||
* Initialize LCache
|
||||
*/
|
||||
void
|
||||
ecma_lcache_init (void)
|
||||
{
|
||||
#ifndef CONFIG_ECMA_LCACHE_DISABLE
|
||||
memset (JERRY_HASH_TABLE_CONTEXT (table), 0, sizeof (jerry_hash_table_t));
|
||||
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */
|
||||
} /* ecma_lcache_init */
|
||||
|
||||
#ifndef CONFIG_ECMA_LCACHE_DISABLE
|
||||
/**
|
||||
* Invalidate specified LCache entry
|
||||
*/
|
||||
static inline void __attr_always_inline___
|
||||
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);
|
||||
JERRY_ASSERT (entry_p->prop_name_cp != ECMA_NULL_POINTER);
|
||||
JERRY_ASSERT (entry_p->prop_p != NULL);
|
||||
|
||||
entry_p->object_cp = ECMA_NULL_POINTER;
|
||||
ecma_set_property_lcached (entry_p->prop_p, false);
|
||||
} /* ecma_lcache_invalidate_entry */
|
||||
|
||||
/**
|
||||
* Compute the row index of object / property name pair
|
||||
*
|
||||
* @return row index
|
||||
*/
|
||||
static inline size_t __attr_always_inline___
|
||||
ecma_lcache_row_index (jmem_cpointer_t object_cp, /**< compressed pointer to object */
|
||||
const ecma_string_t *prop_name_p) /**< proeprty name */
|
||||
{
|
||||
/* Randomize the hash of the property name with the object pointer using a xor operation,
|
||||
* so properties of different objects with the same name can be cached effectively. */
|
||||
return (size_t) ((ecma_string_hash (prop_name_p) ^ object_cp) & ECMA_LCACHE_HASH_MASK);
|
||||
} /* ecma_lcache_row_index */
|
||||
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */
|
||||
|
||||
/**
|
||||
* Insert an entry into LCache
|
||||
*/
|
||||
void
|
||||
ecma_lcache_insert (ecma_object_t *object_p, /**< object */
|
||||
ecma_string_t *prop_name_p, /**< property name */
|
||||
ecma_property_t *prop_p) /**< property */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
JERRY_ASSERT (prop_name_p != NULL);
|
||||
JERRY_ASSERT (prop_p != NULL && !ecma_is_property_lcached (prop_p));
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA
|
||||
|| ECMA_PROPERTY_GET_TYPE (*prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
|
||||
|
||||
#ifndef CONFIG_ECMA_LCACHE_DISABLE
|
||||
jmem_cpointer_t object_cp;
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER (object_cp, object_p);
|
||||
|
||||
size_t row_index = ecma_lcache_row_index (object_cp, prop_name_p);
|
||||
ecma_lcache_hash_entry_t *entries_p = JERRY_HASH_TABLE_CONTEXT (table)[row_index];
|
||||
|
||||
int32_t entry_index;
|
||||
for (entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++)
|
||||
{
|
||||
if (entries_p[entry_index].object_cp == ECMA_NULL_POINTER)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry_index == ECMA_LCACHE_HASH_ROW_LENGTH)
|
||||
{
|
||||
/* Invalidate the last entry. */
|
||||
ecma_lcache_invalidate_entry (entries_p + ECMA_LCACHE_HASH_ROW_LENGTH - 1);
|
||||
|
||||
/* Shift other entries towards the end. */
|
||||
for (uint32_t i = ECMA_LCACHE_HASH_ROW_LENGTH - 1; i > 0; i--)
|
||||
{
|
||||
entries_p[i] = entries_p[i - 1];
|
||||
}
|
||||
|
||||
entry_index = 0;
|
||||
}
|
||||
|
||||
ecma_lcache_hash_entry_t *entry_p = entries_p + entry_index;
|
||||
ECMA_SET_NON_NULL_POINTER (entry_p->object_cp, object_p);
|
||||
ECMA_SET_NON_NULL_POINTER (entry_p->prop_name_cp, prop_name_p);
|
||||
entry_p->prop_p = prop_p;
|
||||
|
||||
ecma_set_property_lcached (entry_p->prop_p, true);
|
||||
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */
|
||||
} /* ecma_lcache_insert */
|
||||
|
||||
/**
|
||||
* Lookup property in the LCache
|
||||
*
|
||||
* @return a pointer to an ecma_property_t if the lookup is successful
|
||||
* NULL otherwise
|
||||
*/
|
||||
inline ecma_property_t * __attr_always_inline___
|
||||
ecma_lcache_lookup (ecma_object_t *object_p, /**< object */
|
||||
const ecma_string_t *prop_name_p) /**< property's name */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
JERRY_ASSERT (prop_name_p != NULL);
|
||||
|
||||
#ifndef CONFIG_ECMA_LCACHE_DISABLE
|
||||
jmem_cpointer_t object_cp;
|
||||
ECMA_SET_NON_NULL_POINTER (object_cp, object_p);
|
||||
|
||||
size_t row_index = ecma_lcache_row_index (object_cp, prop_name_p);
|
||||
ecma_lcache_hash_entry_t *entry_p = JERRY_HASH_TABLE_CONTEXT (table) [row_index];
|
||||
ecma_lcache_hash_entry_t *entry_end_p = entry_p + ECMA_LCACHE_HASH_ROW_LENGTH;
|
||||
ecma_string_container_t prop_container = ECMA_STRING_GET_CONTAINER (prop_name_p);
|
||||
|
||||
while (entry_p < entry_end_p)
|
||||
{
|
||||
if (entry_p->object_cp == object_cp)
|
||||
{
|
||||
ecma_string_t *entry_prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
entry_p->prop_name_cp);
|
||||
|
||||
JERRY_ASSERT ((prop_name_p->hash & ECMA_LCACHE_HASH_MASK) == (entry_prop_name_p->hash & ECMA_LCACHE_HASH_MASK));
|
||||
|
||||
if (prop_name_p == entry_prop_name_p
|
||||
|| (prop_container > ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING
|
||||
&& prop_container == ECMA_STRING_GET_CONTAINER (entry_prop_name_p)
|
||||
&& prop_name_p->u.common_field == entry_prop_name_p->u.common_field))
|
||||
{
|
||||
ecma_property_t *prop_p = entry_p->prop_p;
|
||||
JERRY_ASSERT (prop_p != NULL && ecma_is_property_lcached (prop_p));
|
||||
|
||||
return prop_p;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* They can be equal, but generic string comparison is too costly. */
|
||||
}
|
||||
}
|
||||
entry_p++;
|
||||
}
|
||||
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */
|
||||
|
||||
return NULL;
|
||||
} /* ecma_lcache_lookup */
|
||||
|
||||
/**
|
||||
* Invalidate LCache entries associated with given object and property name / property
|
||||
*/
|
||||
void
|
||||
ecma_lcache_invalidate (ecma_object_t *object_p, /**< object */
|
||||
ecma_string_t *prop_name_p, /**< property's name */
|
||||
ecma_property_t *prop_p) /**< property */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
JERRY_ASSERT (prop_name_p != NULL);
|
||||
JERRY_ASSERT (prop_p != NULL && ecma_is_property_lcached (prop_p));
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA
|
||||
|| ECMA_PROPERTY_GET_TYPE (*prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
|
||||
|
||||
#ifndef CONFIG_ECMA_LCACHE_DISABLE
|
||||
jmem_cpointer_t object_cp;
|
||||
ECMA_SET_NON_NULL_POINTER (object_cp, object_p);
|
||||
|
||||
size_t row_index = ecma_lcache_row_index (object_cp, prop_name_p);
|
||||
ecma_lcache_hash_entry_t *entry_p = JERRY_HASH_TABLE_CONTEXT (table) [row_index];
|
||||
|
||||
for (uint32_t entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++)
|
||||
{
|
||||
if (entry_p->object_cp != ECMA_NULL_POINTER && entry_p->prop_p == prop_p)
|
||||
{
|
||||
JERRY_ASSERT (entry_p->object_cp == object_cp);
|
||||
|
||||
ecma_lcache_invalidate_entry (entry_p);
|
||||
return;
|
||||
}
|
||||
entry_p++;
|
||||
}
|
||||
|
||||
/* The property must be present. */
|
||||
JERRY_UNREACHABLE ();
|
||||
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */
|
||||
} /* ecma_lcache_invalidate */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
36
third_party/jerryscript/jerry-core/ecma/base/ecma-lcache.h
vendored
Normal file
36
third_party/jerryscript/jerry-core/ecma/base/ecma-lcache.h
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* Copyright 2014-2016 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_insert (ecma_object_t *, ecma_string_t *, ecma_property_t *);
|
||||
extern ecma_property_t *ecma_lcache_lookup (ecma_object_t *, const ecma_string_t *);
|
||||
extern void ecma_lcache_invalidate (ecma_object_t *, ecma_string_t *, ecma_property_t *);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* !ECMA_LCACHE_H */
|
514
third_party/jerryscript/jerry-core/ecma/base/ecma-literal-storage.c
vendored
Normal file
514
third_party/jerryscript/jerry-core/ecma/base/ecma-literal-storage.c
vendored
Normal file
|
@ -0,0 +1,514 @@
|
|||
/* Copyright 2016 Samsung Electronics Co., Ltd.
|
||||
* Copyright 2016 University of Szeged.
|
||||
*
|
||||
* 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-literal-storage.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "jcontext.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmalitstorage Literal storage
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Free string list
|
||||
*/
|
||||
static void
|
||||
ecma_free_string_list (ecma_lit_storage_item_t *string_list_p) /**< string list */
|
||||
{
|
||||
while (string_list_p != NULL)
|
||||
{
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (string_list_p->values[i] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_string_t *string_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
string_list_p->values[i]);
|
||||
|
||||
JERRY_ASSERT (ECMA_STRING_IS_REF_EQUALS_TO_ONE (string_p));
|
||||
ecma_deref_ecma_string (string_p);
|
||||
}
|
||||
}
|
||||
|
||||
ecma_lit_storage_item_t *prev_item = string_list_p;
|
||||
string_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, string_list_p->next_cp);
|
||||
jmem_pools_free (prev_item, sizeof (ecma_lit_storage_item_t));
|
||||
}
|
||||
} /* ecma_free_string_list */
|
||||
|
||||
/**
|
||||
* Finalize literal storage
|
||||
*/
|
||||
void
|
||||
ecma_finalize_lit_storage (void)
|
||||
{
|
||||
ecma_free_string_list (JERRY_CONTEXT (string_list_first_p));
|
||||
ecma_free_string_list (JERRY_CONTEXT (number_list_first_p));
|
||||
} /* ecma_finalize_lit_storage */
|
||||
|
||||
/**
|
||||
* Find or create a literal string.
|
||||
*
|
||||
* @return ecma_string_t compressed pointer
|
||||
*/
|
||||
jmem_cpointer_t
|
||||
ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, /**< string to be searched */
|
||||
lit_utf8_size_t size) /**< size of the string */
|
||||
{
|
||||
ecma_string_t *string_p = ecma_new_ecma_string_from_utf8 (chars_p, size);
|
||||
|
||||
ecma_lit_storage_item_t *string_list_p = JERRY_CONTEXT (string_list_first_p);
|
||||
jmem_cpointer_t *empty_cpointer_p = NULL;
|
||||
|
||||
while (string_list_p != NULL)
|
||||
{
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (string_list_p->values[i] == JMEM_CP_NULL)
|
||||
{
|
||||
if (empty_cpointer_p == NULL)
|
||||
{
|
||||
empty_cpointer_p = string_list_p->values + i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
string_list_p->values[i]);
|
||||
|
||||
if (ecma_compare_ecma_strings (string_p, value_p))
|
||||
{
|
||||
/* Return with string if found in the list. */
|
||||
ecma_deref_ecma_string (string_p);
|
||||
return string_list_p->values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, string_list_p->next_cp);
|
||||
}
|
||||
|
||||
jmem_cpointer_t result;
|
||||
JMEM_CP_SET_NON_NULL_POINTER (result, string_p);
|
||||
|
||||
if (empty_cpointer_p != NULL)
|
||||
{
|
||||
*empty_cpointer_p = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
ecma_lit_storage_item_t *new_item_p;
|
||||
new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t));
|
||||
|
||||
new_item_p->values[0] = result;
|
||||
for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
new_item_p->values[i] = JMEM_CP_NULL;
|
||||
}
|
||||
|
||||
JMEM_CP_SET_POINTER (new_item_p->next_cp, JERRY_CONTEXT (string_list_first_p));
|
||||
JERRY_CONTEXT (string_list_first_p) = new_item_p;
|
||||
|
||||
return result;
|
||||
} /* ecma_find_or_create_literal_string */
|
||||
|
||||
/**
|
||||
* Find or create a literal number.
|
||||
*
|
||||
* @return ecma_string_t compressed pointer
|
||||
*/
|
||||
jmem_cpointer_t
|
||||
ecma_find_or_create_literal_number (ecma_number_t number_arg) /**< number to be searched */
|
||||
{
|
||||
ecma_value_t num = ecma_make_number_value (number_arg);
|
||||
|
||||
ecma_lit_storage_item_t *number_list_p = JERRY_CONTEXT (number_list_first_p);
|
||||
jmem_cpointer_t *empty_cpointer_p = NULL;
|
||||
|
||||
while (number_list_p != NULL)
|
||||
{
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (number_list_p->values[i] == JMEM_CP_NULL)
|
||||
{
|
||||
if (empty_cpointer_p == NULL)
|
||||
{
|
||||
empty_cpointer_p = number_list_p->values + i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
number_list_p->values[i]);
|
||||
|
||||
JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (value_p) == ECMA_STRING_LITERAL_NUMBER);
|
||||
|
||||
if (ecma_is_value_integer_number (num))
|
||||
{
|
||||
if (value_p->u.lit_number == num)
|
||||
{
|
||||
return number_list_p->values[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ecma_is_value_float_number (value_p->u.lit_number)
|
||||
&& ecma_get_float_from_value (value_p->u.lit_number) == ecma_get_float_from_value (num))
|
||||
{
|
||||
ecma_free_value (num);
|
||||
return number_list_p->values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
number_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, number_list_p->next_cp);
|
||||
}
|
||||
|
||||
ecma_string_t *string_p = (ecma_string_t *) jmem_pools_alloc (sizeof (ecma_string_t));
|
||||
string_p->refs_and_container = ECMA_STRING_REF_ONE | ECMA_STRING_LITERAL_NUMBER;
|
||||
string_p->u.lit_number = num;
|
||||
|
||||
jmem_cpointer_t result;
|
||||
JMEM_CP_SET_NON_NULL_POINTER (result, string_p);
|
||||
|
||||
if (empty_cpointer_p != NULL)
|
||||
{
|
||||
*empty_cpointer_p = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
ecma_lit_storage_item_t *new_item_p;
|
||||
new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t));
|
||||
|
||||
new_item_p->values[0] = result;
|
||||
for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
new_item_p->values[i] = JMEM_CP_NULL;
|
||||
}
|
||||
|
||||
JMEM_CP_SET_POINTER (new_item_p->next_cp, JERRY_CONTEXT (number_list_first_p));
|
||||
JERRY_CONTEXT (number_list_first_p) = new_item_p;
|
||||
|
||||
return result;
|
||||
} /* ecma_find_or_create_literal_number */
|
||||
|
||||
/**
|
||||
* Log2 of snapshot literal alignment.
|
||||
*/
|
||||
#define JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG 2
|
||||
|
||||
/**
|
||||
* Snapshot literal alignment.
|
||||
*/
|
||||
#define JERRY_SNAPSHOT_LITERAL_ALIGNMENT (1u << JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG)
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_SAVE
|
||||
|
||||
/**
|
||||
* Save literals to specified snapshot buffer.
|
||||
*
|
||||
* @return true, if save was performed successfully (i.e. buffer size is sufficient),
|
||||
* false - otherwise.
|
||||
*/
|
||||
bool
|
||||
ecma_save_literals_for_snapshot (uint8_t *buffer_p, /**< [out] output snapshot buffer */
|
||||
size_t buffer_size, /**< size of the buffer */
|
||||
size_t *in_out_buffer_offset_p, /**< [in,out] write position in the buffer */
|
||||
lit_mem_to_snapshot_id_map_entry_t **out_map_p, /**< [out] map from literal identifiers
|
||||
* to the literal offsets
|
||||
* in snapshot */
|
||||
uint32_t *out_map_len_p, /**< [out] number of literals */
|
||||
uint32_t *out_lit_table_size_p) /**< [out] number of bytes, saved to snapshot buffer */
|
||||
{
|
||||
/* Count literals and literal space. */
|
||||
uint32_t string_count = 0;
|
||||
uint32_t number_count = 0;
|
||||
uint32_t lit_table_size = 2 * sizeof (uint32_t);
|
||||
|
||||
ecma_lit_storage_item_t *string_list_p = JERRY_CONTEXT (string_list_first_p);
|
||||
|
||||
while (string_list_p != NULL)
|
||||
{
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (string_list_p->values[i] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_string_t *string_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
string_list_p->values[i]);
|
||||
|
||||
lit_table_size += (uint32_t) JERRY_ALIGNUP (sizeof (uint16_t) + ecma_string_get_size (string_p),
|
||||
JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
|
||||
string_count++;
|
||||
}
|
||||
}
|
||||
|
||||
string_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, string_list_p->next_cp);
|
||||
}
|
||||
|
||||
ecma_lit_storage_item_t *number_list_p = JERRY_CONTEXT (number_list_first_p);
|
||||
|
||||
while (number_list_p != NULL)
|
||||
{
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (number_list_p->values[i] != JMEM_CP_NULL)
|
||||
{
|
||||
lit_table_size += (uint32_t) sizeof (ecma_number_t);
|
||||
number_count++;
|
||||
}
|
||||
}
|
||||
|
||||
number_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, number_list_p->next_cp);
|
||||
}
|
||||
|
||||
/* Check whether enough space is available. */
|
||||
if (*in_out_buffer_offset_p + lit_table_size > buffer_size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check whether the maximum literal table size is reached. */
|
||||
if ((lit_table_size >> JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG) > UINT16_MAX)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t total_count = string_count + number_count;
|
||||
lit_mem_to_snapshot_id_map_entry_t *map_p;
|
||||
|
||||
map_p = jmem_heap_alloc_block (total_count * sizeof (lit_mem_to_snapshot_id_map_entry_t));
|
||||
|
||||
/* Set return values (no error is possible from here). */
|
||||
buffer_p += *in_out_buffer_offset_p;
|
||||
*in_out_buffer_offset_p += lit_table_size;
|
||||
*out_map_p = map_p;
|
||||
*out_map_len_p = total_count;
|
||||
*out_lit_table_size_p = lit_table_size;
|
||||
|
||||
/* Write data into the buffer. */
|
||||
|
||||
/* The zero value is reserved for NULL (no literal)
|
||||
* constant so the first literal must have offset one. */
|
||||
uint32_t literal_offset = JERRY_SNAPSHOT_LITERAL_ALIGNMENT;
|
||||
|
||||
((uint32_t *) buffer_p)[0] = string_count;
|
||||
((uint32_t *) buffer_p)[1] = number_count;
|
||||
buffer_p += 2 * sizeof (uint32_t);
|
||||
|
||||
string_list_p = JERRY_CONTEXT (string_list_first_p);
|
||||
|
||||
while (string_list_p != NULL)
|
||||
{
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (string_list_p->values[i] != JMEM_CP_NULL)
|
||||
{
|
||||
map_p->literal_id = string_list_p->values[i];
|
||||
map_p->literal_offset = (jmem_cpointer_t) (literal_offset >> JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG);
|
||||
map_p++;
|
||||
|
||||
ecma_string_t *string_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
string_list_p->values[i]);
|
||||
|
||||
ecma_length_t length = ecma_string_get_size (string_p);
|
||||
|
||||
*((uint16_t *) buffer_p) = (uint16_t) length;
|
||||
ecma_string_to_utf8_bytes (string_p, buffer_p + sizeof (uint16_t), length);
|
||||
|
||||
length = JERRY_ALIGNUP (sizeof (uint16_t) + length,
|
||||
JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
|
||||
|
||||
buffer_p += length;
|
||||
literal_offset += length;
|
||||
}
|
||||
}
|
||||
|
||||
string_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, string_list_p->next_cp);
|
||||
}
|
||||
|
||||
number_list_p = JERRY_CONTEXT (number_list_first_p);
|
||||
|
||||
while (number_list_p != NULL)
|
||||
{
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (number_list_p->values[i] != JMEM_CP_NULL)
|
||||
{
|
||||
map_p->literal_id = number_list_p->values[i];
|
||||
map_p->literal_offset = (jmem_cpointer_t) (literal_offset >> JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG);
|
||||
map_p++;
|
||||
|
||||
ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
number_list_p->values[i]);
|
||||
|
||||
JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (value_p) == ECMA_STRING_LITERAL_NUMBER);
|
||||
|
||||
ecma_number_t num = ecma_get_number_from_value (value_p->u.lit_number);
|
||||
memcpy (buffer_p, &num, sizeof (ecma_number_t));
|
||||
|
||||
ecma_length_t length = JERRY_ALIGNUP (sizeof (ecma_number_t),
|
||||
JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
|
||||
|
||||
buffer_p += length;
|
||||
literal_offset += length;
|
||||
}
|
||||
}
|
||||
|
||||
number_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, number_list_p->next_cp);
|
||||
}
|
||||
|
||||
return true;
|
||||
} /* ecma_save_literals_for_snapshot */
|
||||
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_SAVE */
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
|
||||
|
||||
/**
|
||||
* Helper function for ecma_load_literals_from_snapshot.
|
||||
*
|
||||
* Note: always inline because it is used only once.
|
||||
*
|
||||
* @return true, if load was performed successfully
|
||||
* false - otherwise (i.e. buffer length is incorrect).
|
||||
*/
|
||||
static inline bool __attr_always_inline___
|
||||
ecma_load_literals_from_buffer (const uint8_t *buffer_p, /**< buffer with literal table in snapshot */
|
||||
uint32_t lit_table_size, /**< size of literal table in snapshot */
|
||||
lit_mem_to_snapshot_id_map_entry_t *map_p, /**< literal map */
|
||||
uint32_t string_count, /**< number of strings */
|
||||
uint32_t number_count) /**< number of numbers */
|
||||
{
|
||||
/* The zero value is reserved for NULL (no literal)
|
||||
* constant so the first literal must have offset one. */
|
||||
uint32_t literal_offset = JERRY_SNAPSHOT_LITERAL_ALIGNMENT;
|
||||
|
||||
/* Load strings first. */
|
||||
while (string_count > 0)
|
||||
{
|
||||
if (lit_table_size < literal_offset + sizeof (uint32_t))
|
||||
{
|
||||
/* Buffer is not sufficent. */
|
||||
return false;
|
||||
}
|
||||
|
||||
lit_utf8_size_t length = *((uint16_t *) buffer_p);
|
||||
lit_utf8_size_t aligned_length = JERRY_ALIGNUP (sizeof (uint16_t) + length,
|
||||
JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
|
||||
|
||||
if (lit_table_size < literal_offset + aligned_length)
|
||||
{
|
||||
/* Buffer is not sufficent. */
|
||||
return false;
|
||||
}
|
||||
|
||||
map_p->literal_id = ecma_find_or_create_literal_string (buffer_p + sizeof (uint16_t), length);
|
||||
map_p->literal_offset = (jmem_cpointer_t) (literal_offset >> JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG);
|
||||
map_p++;
|
||||
|
||||
buffer_p += aligned_length;
|
||||
literal_offset += aligned_length;
|
||||
|
||||
string_count--;
|
||||
}
|
||||
|
||||
/* Load numbers. */
|
||||
while (number_count > 0)
|
||||
{
|
||||
if (lit_table_size < literal_offset + sizeof (ecma_number_t))
|
||||
{
|
||||
/* Buffer is not sufficent. */
|
||||
return false;
|
||||
}
|
||||
|
||||
ecma_number_t num;
|
||||
memcpy (&num, buffer_p, sizeof (ecma_number_t));
|
||||
|
||||
map_p->literal_id = ecma_find_or_create_literal_number (num);
|
||||
map_p->literal_offset = (jmem_cpointer_t) (literal_offset >> JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG);
|
||||
map_p++;
|
||||
|
||||
ecma_length_t length = JERRY_ALIGNUP (sizeof (ecma_number_t),
|
||||
JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
|
||||
|
||||
buffer_p += length;
|
||||
literal_offset += length;
|
||||
|
||||
number_count--;
|
||||
}
|
||||
|
||||
return (lit_table_size == (literal_offset + 2 * sizeof (uint32_t) - JERRY_SNAPSHOT_LITERAL_ALIGNMENT));
|
||||
} /* ecma_load_literals_from_buffer */
|
||||
|
||||
/**
|
||||
* Load literals from snapshot.
|
||||
*
|
||||
* @return true, if load was performed successfully (i.e. literals saved in the snapshot are consistent),
|
||||
* false - otherwise (i.e. snapshot is incorrect).
|
||||
*/
|
||||
bool
|
||||
ecma_load_literals_from_snapshot (const uint8_t *buffer_p, /**< buffer with literal table in snapshot */
|
||||
uint32_t lit_table_size, /**< size of literal table in snapshot */
|
||||
lit_mem_to_snapshot_id_map_entry_t **out_map_p, /**< [out] map from literal offsets
|
||||
* in snapshot to identifiers
|
||||
* of loaded literals in literal
|
||||
* storage */
|
||||
uint32_t *out_map_len_p) /**< [out] literals number */
|
||||
{
|
||||
*out_map_p = NULL;
|
||||
|
||||
if (lit_table_size < 2 * sizeof (uint32_t))
|
||||
{
|
||||
/* Buffer is not sufficent. */
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t string_count = ((uint32_t *) buffer_p)[0];
|
||||
uint32_t number_count = ((uint32_t *) buffer_p)[1];
|
||||
buffer_p += 2 * sizeof (uint32_t);
|
||||
|
||||
uint32_t total_count = string_count + number_count;
|
||||
lit_mem_to_snapshot_id_map_entry_t *map_p;
|
||||
|
||||
*out_map_len_p = total_count;
|
||||
|
||||
if (total_count == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
map_p = jmem_heap_alloc_block (total_count * sizeof (lit_mem_to_snapshot_id_map_entry_t));
|
||||
*out_map_p = map_p;
|
||||
|
||||
if (ecma_load_literals_from_buffer (buffer_p, lit_table_size, map_p, string_count, number_count))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
jmem_heap_free_block (map_p, total_count * sizeof (lit_mem_to_snapshot_id_map_entry_t));
|
||||
*out_map_p = NULL;
|
||||
return false;
|
||||
} /* ecma_load_literals_from_snapshot */
|
||||
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
62
third_party/jerryscript/jerry-core/ecma/base/ecma-literal-storage.h
vendored
Normal file
62
third_party/jerryscript/jerry-core/ecma/base/ecma-literal-storage.h
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* Copyright 2016 Samsung Electronics Co., Ltd.
|
||||
* Copyright 2016 University of Szeged.
|
||||
*
|
||||
* 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_LIT_STORAGE_H
|
||||
#define ECMA_LIT_STORAGE_H
|
||||
|
||||
#include "ecma-globals.h"
|
||||
#include "jmem-allocator.h"
|
||||
#include "lit-globals.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmalitstorage Literal storage
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Snapshot literal - offset map
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
jmem_cpointer_t literal_id; /**< literal id */
|
||||
jmem_cpointer_t literal_offset; /**< literal offset */
|
||||
} lit_mem_to_snapshot_id_map_entry_t;
|
||||
|
||||
extern void ecma_finalize_lit_storage (void);
|
||||
|
||||
extern jmem_cpointer_t ecma_find_or_create_literal_string (const lit_utf8_byte_t *, lit_utf8_size_t);
|
||||
extern jmem_cpointer_t ecma_find_or_create_literal_number (ecma_number_t);
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_SAVE
|
||||
extern bool
|
||||
ecma_save_literals_for_snapshot (uint8_t *, size_t, size_t *,
|
||||
lit_mem_to_snapshot_id_map_entry_t **, uint32_t *, uint32_t *);
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_SAVE */
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
|
||||
extern bool
|
||||
ecma_load_literals_from_snapshot (const uint8_t *, uint32_t,
|
||||
lit_mem_to_snapshot_id_map_entry_t **, uint32_t *);
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* !ECMA_LIT_STORAGE_H */
|
519
third_party/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.c
vendored
Normal file
519
third_party/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.c
vendored
Normal file
|
@ -0,0 +1,519 @@
|
|||
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
|
||||
* Copyright 2016 University of Szeged.
|
||||
*
|
||||
* 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-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-property-hashmap.h"
|
||||
#include "jrt-libc-includes.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmapropertyhashmap Property hashmap
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE
|
||||
|
||||
/**
|
||||
* Compute the total size of the property hashmap.
|
||||
*/
|
||||
#define ECMA_PROPERTY_HASHMAP_GET_TOTAL_SIZE(max_property_count) \
|
||||
(sizeof (ecma_property_hashmap_t) + (max_property_count * sizeof (jmem_cpointer_t)) + (max_property_count >> 3))
|
||||
|
||||
/**
|
||||
* Number of items in the stepping table.
|
||||
*/
|
||||
#define ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS 8
|
||||
|
||||
/**
|
||||
* Stepping values for searching items in the hashmap.
|
||||
*/
|
||||
static const uint8_t ecma_property_hashmap_steps[ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS] JERRY_CONST_DATA =
|
||||
{
|
||||
3, 5, 7, 11, 13, 17, 19, 23
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the value of a bit in a bitmap.
|
||||
*/
|
||||
#define ECMA_PROPERTY_HASHMAP_GET_BIT(byte_p, index) \
|
||||
((byte_p)[(index) >> 3] & (1 << ((index) & 0x7)))
|
||||
|
||||
/**
|
||||
* Clear the value of a bit in a bitmap.
|
||||
*/
|
||||
#define ECMA_PROPERTY_HASHMAP_CLEAR_BIT(byte_p, index) \
|
||||
((byte_p)[(index) >> 3] = (uint8_t) ((byte_p)[(index) >> 3] & ~(1 << ((index) & 0x7))))
|
||||
|
||||
/**
|
||||
* Set the value of a bit in a bitmap.
|
||||
*/
|
||||
#define ECMA_PROPERTY_HASHMAP_SET_BIT(byte_p, index) \
|
||||
((byte_p)[(index) >> 3] = (uint8_t) ((byte_p)[(index) >> 3] | (1 << ((index) & 0x7))))
|
||||
|
||||
#endif /* !CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */
|
||||
|
||||
/**
|
||||
* Create a new property hashmap for the object.
|
||||
* The object must not have a property hashmap.
|
||||
*/
|
||||
void
|
||||
ecma_property_hashmap_create (ecma_object_t *object_p) /**< object */
|
||||
{
|
||||
#ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE
|
||||
JERRY_ASSERT (ecma_get_property_list (object_p) != NULL);
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (ecma_get_property_list (object_p)));
|
||||
|
||||
uint32_t named_property_count = 0;
|
||||
|
||||
ecma_property_header_t *prop_iter_p = ecma_get_property_list (object_p);
|
||||
|
||||
while (prop_iter_p != NULL)
|
||||
{
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));
|
||||
|
||||
for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
|
||||
{
|
||||
ecma_property_types_t type = ECMA_PROPERTY_GET_TYPE (prop_iter_p->types[i]);
|
||||
|
||||
if (type == ECMA_PROPERTY_TYPE_NAMEDDATA || type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
|
||||
{
|
||||
named_property_count++;
|
||||
}
|
||||
}
|
||||
prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t,
|
||||
prop_iter_p->next_property_cp);
|
||||
}
|
||||
|
||||
/* The max_property_count must be power of 2. */
|
||||
uint32_t max_property_count = ECMA_PROPERTY_HASMAP_MINIMUM_SIZE;
|
||||
|
||||
/* At least 1/3 items must be NULL. */
|
||||
while (max_property_count < (named_property_count + (named_property_count >> 1)))
|
||||
{
|
||||
max_property_count <<= 1;
|
||||
}
|
||||
|
||||
size_t total_size = ECMA_PROPERTY_HASHMAP_GET_TOTAL_SIZE (max_property_count);
|
||||
|
||||
ecma_property_hashmap_t *hashmap_p = (ecma_property_hashmap_t *) jmem_heap_alloc_block_null_on_error (total_size);
|
||||
|
||||
if (hashmap_p == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
memset (hashmap_p, 0, total_size);
|
||||
|
||||
hashmap_p->header.types[0] = ECMA_PROPERTY_TYPE_HASHMAP;
|
||||
hashmap_p->header.next_property_cp = object_p->property_list_or_bound_object_cp;
|
||||
hashmap_p->max_property_count = max_property_count;
|
||||
hashmap_p->null_count = max_property_count - named_property_count;
|
||||
|
||||
jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1);
|
||||
uint8_t *bits_p = (uint8_t *) (pair_list_p + max_property_count);
|
||||
uint32_t mask = max_property_count - 1;
|
||||
|
||||
uint8_t shift_counter = 0;
|
||||
|
||||
if (max_property_count <= LIT_STRING_HASH_LIMIT)
|
||||
{
|
||||
hashmap_p->header.types[1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (max_property_count > LIT_STRING_HASH_LIMIT)
|
||||
{
|
||||
shift_counter++;
|
||||
max_property_count >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
hashmap_p->header.types[1] = shift_counter;
|
||||
|
||||
prop_iter_p = ecma_get_property_list (object_p);
|
||||
ECMA_SET_POINTER (object_p->property_list_or_bound_object_cp, hashmap_p);
|
||||
|
||||
while (prop_iter_p != NULL)
|
||||
{
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));
|
||||
|
||||
for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
|
||||
{
|
||||
ecma_property_types_t type = ECMA_PROPERTY_GET_TYPE (prop_iter_p->types[i]);
|
||||
|
||||
if (!(type == ECMA_PROPERTY_TYPE_NAMEDDATA || type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ecma_property_pair_t *property_pair_p = (ecma_property_pair_t *) prop_iter_p;
|
||||
ecma_string_t *name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_pair_p->names_cp[i]);
|
||||
|
||||
uint32_t entry_index = name_p->hash;
|
||||
uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)];
|
||||
|
||||
if (mask < LIT_STRING_HASH_LIMIT)
|
||||
{
|
||||
entry_index &= mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry_index <<= shift_counter;
|
||||
JERRY_ASSERT (entry_index <= mask);
|
||||
}
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
/* Because max_property_count (power of 2) and step (a prime
|
||||
* number) are relative primes, all entries of the hasmap are
|
||||
* visited exactly once before the start entry index is reached
|
||||
* again. Furthermore because at least one NULL is present in
|
||||
* the hashmap, the while loop must be terminated before the
|
||||
* the starting index is reached again. */
|
||||
uint32_t start_entry_index = entry_index;
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
while (pair_list_p[entry_index] != ECMA_NULL_POINTER)
|
||||
{
|
||||
entry_index = (entry_index + step) & mask;
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (entry_index != start_entry_index);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
}
|
||||
|
||||
ECMA_SET_POINTER (pair_list_p[entry_index], property_pair_p);
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
ECMA_PROPERTY_HASHMAP_SET_BIT (bits_p, entry_index);
|
||||
}
|
||||
}
|
||||
|
||||
prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t,
|
||||
prop_iter_p->next_property_cp);
|
||||
}
|
||||
#else /* CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */
|
||||
JERRY_UNUSED (object_p);
|
||||
#endif /* !CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */
|
||||
} /* ecma_property_hashmap_create */
|
||||
|
||||
/**
|
||||
* Free the hashmap of the object.
|
||||
* The object must have a property hashmap.
|
||||
*/
|
||||
void
|
||||
ecma_property_hashmap_free (ecma_object_t *object_p) /**< object */
|
||||
{
|
||||
#ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE
|
||||
/* Property hash must be exists and must be the first property. */
|
||||
ecma_property_header_t *property_p = ecma_get_property_list (object_p);
|
||||
|
||||
JERRY_ASSERT (property_p != NULL
|
||||
&& ECMA_PROPERTY_GET_TYPE (property_p->types[0]) == ECMA_PROPERTY_TYPE_HASHMAP);
|
||||
|
||||
ecma_property_hashmap_t *hashmap_p = (ecma_property_hashmap_t *) property_p;
|
||||
|
||||
object_p->property_list_or_bound_object_cp = property_p->next_property_cp;
|
||||
|
||||
jmem_heap_free_block (hashmap_p,
|
||||
ECMA_PROPERTY_HASHMAP_GET_TOTAL_SIZE (hashmap_p->max_property_count));
|
||||
#else /* CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */
|
||||
JERRY_UNUSED (object_p);
|
||||
#endif /* !CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */
|
||||
} /* ecma_property_hashmap_free */
|
||||
|
||||
/**
|
||||
* Insert named property into the hashmap.
|
||||
*/
|
||||
void
|
||||
ecma_property_hashmap_insert (ecma_object_t *object_p, /**< object */
|
||||
ecma_string_t *name_p, /**< name of the property */
|
||||
ecma_property_pair_t *property_pair_p, /**< property pair */
|
||||
int property_index) /**< property index in the pair (0 or 1) */
|
||||
{
|
||||
#ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE
|
||||
ecma_property_hashmap_t *hashmap_p = ECMA_GET_NON_NULL_POINTER (ecma_property_hashmap_t,
|
||||
object_p->property_list_or_bound_object_cp);
|
||||
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (hashmap_p->header.types[0]) == ECMA_PROPERTY_TYPE_HASHMAP);
|
||||
|
||||
/* The NULLs are reduced below 1/8 of the hashmap. */
|
||||
if (hashmap_p->null_count < (hashmap_p->max_property_count >> 3))
|
||||
{
|
||||
ecma_property_hashmap_free (object_p);
|
||||
ecma_property_hashmap_create (object_p);
|
||||
return;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (property_index < ECMA_PROPERTY_PAIR_ITEM_COUNT);
|
||||
|
||||
uint32_t entry_index = name_p->hash;
|
||||
uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)];
|
||||
uint32_t mask = hashmap_p->max_property_count - 1;
|
||||
|
||||
if (mask < LIT_STRING_HASH_LIMIT)
|
||||
{
|
||||
entry_index &= mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry_index <<= hashmap_p->header.types[1];
|
||||
}
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
/* See the comment for this variable in ecma_property_hashmap_create. */
|
||||
uint32_t start_entry_index = entry_index;
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1);
|
||||
|
||||
while (pair_list_p[entry_index] != ECMA_NULL_POINTER)
|
||||
{
|
||||
entry_index = (entry_index + step) & mask;
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (entry_index != start_entry_index);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
}
|
||||
|
||||
ECMA_SET_POINTER (pair_list_p[entry_index], property_pair_p);
|
||||
|
||||
uint8_t *bits_p = (uint8_t *) (pair_list_p + hashmap_p->max_property_count);
|
||||
bits_p += (entry_index >> 3);
|
||||
mask = (uint32_t) (1 << (entry_index & 0x7));
|
||||
|
||||
if (!(*bits_p & mask))
|
||||
{
|
||||
/* Deleted entries also has ECMA_NULL_POINTER
|
||||
* value, but they are not NULL values. */
|
||||
hashmap_p->null_count--;
|
||||
JERRY_ASSERT (hashmap_p->null_count > 0);
|
||||
}
|
||||
|
||||
if (property_index == 0)
|
||||
{
|
||||
*bits_p = (uint8_t) ((*bits_p) & ~mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
*bits_p = (uint8_t) ((*bits_p) | mask);
|
||||
}
|
||||
#else /* CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */
|
||||
JERRY_UNUSED (object_p);
|
||||
JERRY_UNUSED (name_p);
|
||||
JERRY_UNUSED (property_pair_p);
|
||||
JERRY_UNUSED (property_index);
|
||||
#endif /* !CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */
|
||||
} /* ecma_property_hashmap_insert */
|
||||
|
||||
/**
|
||||
* Delete named property from the hashmap.
|
||||
*/
|
||||
void
|
||||
ecma_property_hashmap_delete (ecma_object_t *object_p, /**< object */
|
||||
ecma_string_t *name_p, /**< name of the property */
|
||||
ecma_property_t *property_p) /**< property */
|
||||
{
|
||||
#ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE
|
||||
ecma_property_hashmap_t *hashmap_p = ECMA_GET_NON_NULL_POINTER (ecma_property_hashmap_t,
|
||||
object_p->property_list_or_bound_object_cp);
|
||||
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (hashmap_p->header.types[0]) == ECMA_PROPERTY_TYPE_HASHMAP);
|
||||
|
||||
uint32_t entry_index = name_p->hash;
|
||||
uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)];
|
||||
uint32_t mask = hashmap_p->max_property_count - 1;
|
||||
jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1);
|
||||
uint8_t *bits_p = (uint8_t *) (pair_list_p + hashmap_p->max_property_count);
|
||||
|
||||
if (mask < LIT_STRING_HASH_LIMIT)
|
||||
{
|
||||
entry_index &= mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry_index <<= hashmap_p->header.types[1];
|
||||
JERRY_ASSERT (entry_index <= mask);
|
||||
}
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
/* See the comment for this variable in ecma_property_hashmap_create. */
|
||||
uint32_t start_entry_index = entry_index;
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (pair_list_p[entry_index] != ECMA_NULL_POINTER)
|
||||
{
|
||||
size_t offset = 0;
|
||||
if (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index))
|
||||
{
|
||||
offset = 1;
|
||||
}
|
||||
|
||||
ecma_property_pair_t *property_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_property_pair_t,
|
||||
pair_list_p[entry_index]);
|
||||
|
||||
if ((property_pair_p->header.types + offset) == property_p)
|
||||
{
|
||||
JERRY_ASSERT (ecma_compare_ecma_strings (ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_pair_p->names_cp[offset]),
|
||||
name_p));
|
||||
|
||||
pair_list_p[entry_index] = ECMA_NULL_POINTER;
|
||||
ECMA_PROPERTY_HASHMAP_SET_BIT (bits_p, entry_index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Must be a deleted entry. */
|
||||
JERRY_ASSERT (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index));
|
||||
}
|
||||
|
||||
entry_index = (entry_index + step) & mask;
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (entry_index != start_entry_index);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
}
|
||||
#else /* CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */
|
||||
JERRY_UNUSED (object_p);
|
||||
JERRY_UNUSED (name_p);
|
||||
JERRY_UNUSED (property_p);
|
||||
#endif /* !CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */
|
||||
} /* ecma_property_hashmap_delete */
|
||||
|
||||
#ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE
|
||||
/**
|
||||
* Find a named property.
|
||||
*
|
||||
* @return pointer to the property if found or NULL otherwise
|
||||
*/
|
||||
ecma_property_t *
|
||||
ecma_property_hashmap_find (ecma_property_hashmap_t *hashmap_p, /**< hashmap */
|
||||
ecma_string_t *name_p, /**< property name */
|
||||
ecma_string_t **property_real_name_p) /**< [out] property real name */
|
||||
{
|
||||
#ifndef JERRY_NDEBUG
|
||||
/* A sanity check in debug mode: a named property must be present
|
||||
* in both the property hashmap and in the property chain, or missing
|
||||
* from both data collection. The following code checks the property
|
||||
* chain, and sets the property_found variable. */
|
||||
bool property_found = false;
|
||||
ecma_property_header_t *prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t,
|
||||
hashmap_p->header.next_property_cp);
|
||||
|
||||
while (prop_iter_p != NULL && !property_found)
|
||||
{
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));
|
||||
|
||||
ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p;
|
||||
|
||||
for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
|
||||
{
|
||||
if (prop_pair_p->names_cp[i] != ECMA_NULL_POINTER)
|
||||
{
|
||||
ecma_string_t *property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
prop_pair_p->names_cp[i]);
|
||||
|
||||
if (ecma_compare_ecma_strings (name_p, property_name_p))
|
||||
{
|
||||
property_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t,
|
||||
prop_iter_p->next_property_cp);
|
||||
}
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
uint32_t entry_index = name_p->hash;
|
||||
uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)];
|
||||
uint32_t mask = hashmap_p->max_property_count - 1;
|
||||
jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1);
|
||||
uint8_t *bits_p = (uint8_t *) (pair_list_p + hashmap_p->max_property_count);
|
||||
|
||||
if (mask < LIT_STRING_HASH_LIMIT)
|
||||
{
|
||||
entry_index &= mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry_index <<= hashmap_p->header.types[1];
|
||||
JERRY_ASSERT (entry_index <= mask);
|
||||
}
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
/* See the comment for this variable in ecma_property_hashmap_create. */
|
||||
uint32_t start_entry_index = entry_index;
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (pair_list_p[entry_index] != ECMA_NULL_POINTER)
|
||||
{
|
||||
size_t offset = 0;
|
||||
if (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index))
|
||||
{
|
||||
offset = 1;
|
||||
}
|
||||
|
||||
ecma_property_pair_t *property_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_property_pair_t,
|
||||
pair_list_p[entry_index]);
|
||||
|
||||
ecma_string_t *property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_pair_p->names_cp[offset]);
|
||||
|
||||
if (ecma_compare_ecma_strings (name_p, property_name_p))
|
||||
{
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (property_found);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
*property_real_name_p = property_name_p;
|
||||
return property_pair_p->header.types + offset;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index))
|
||||
{
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (!property_found);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
return NULL;
|
||||
}
|
||||
/* Otherwise it is a deleted entry. */
|
||||
}
|
||||
|
||||
entry_index = (entry_index + step) & mask;
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (entry_index != start_entry_index);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
}
|
||||
} /* ecma_property_hashmap_find */
|
||||
#endif /* !CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
70
third_party/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.h
vendored
Normal file
70
third_party/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.h
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
/* Copyright 2016 Samsung Electronics Co., Ltd.
|
||||
* Copyright 2016 University of Szeged.
|
||||
*
|
||||
* 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_PROPERTY_HASHMAP_H
|
||||
#define ECMA_PROPERTY_HASHMAP_H
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmapropertyhashmap Property hashmap
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Recommended minimum number of items in a property cache.
|
||||
*/
|
||||
#define ECMA_PROPERTY_HASMAP_MINIMUM_SIZE 32
|
||||
|
||||
/**
|
||||
* Property hash.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ecma_property_header_t header; /**< header of the property */
|
||||
uint32_t max_property_count; /**< maximum property count (power of 2) */
|
||||
uint32_t null_count; /**< number of NULLs in the map */
|
||||
|
||||
/*
|
||||
* The hash is followed by max_property_count ecma_cpointer_t
|
||||
* compressed pointers and (max_property_count + 7) / 8 bytes
|
||||
* which stores a flag for each compressed pointer.
|
||||
*
|
||||
* If the compressed pointer is equal to ECMA_NULL_POINTER
|
||||
* - flag is cleared if the entry is NULL
|
||||
* - flag is set if the entry is deleted
|
||||
*
|
||||
* If the compressed pointer is not equal to ECMA_NULL_POINTER
|
||||
* - flag is cleared if the first entry of a property pair is referenced
|
||||
* - flag is set if the second entry of a property pair is referenced
|
||||
*/
|
||||
} ecma_property_hashmap_t;
|
||||
|
||||
extern void ecma_property_hashmap_create (ecma_object_t *);
|
||||
extern void ecma_property_hashmap_free (ecma_object_t *);
|
||||
extern void ecma_property_hashmap_insert (ecma_object_t *, ecma_string_t *, ecma_property_pair_t *, int);
|
||||
extern void ecma_property_hashmap_delete (ecma_object_t *, ecma_string_t *, ecma_property_t *);
|
||||
|
||||
#ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE
|
||||
extern ecma_property_t *ecma_property_hashmap_find (ecma_property_hashmap_t *, ecma_string_t *, ecma_string_t **);
|
||||
#endif /* !CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* !ECMA_PROPERTY_HASHMAP_H */
|
Loading…
Add table
Add a link
Reference in a new issue