/** * Find internal property in the object's property set. * * @return pointer to the property, if it is found, * NULL - otherwise. */ ecma_property_t * ecma_find_internal_property (ecma_object_t *object_p, /**< object descriptor */ ecma_internal_property_id_t property_id) /**< internal property identifier */ { JERRY_ASSERT (object_p != NULL); JERRY_ASSERT (property_id != ECMA_INTERNAL_PROPERTY_PROTOTYPE && property_id != ECMA_INTERNAL_PROPERTY_EXTENSIBLE); 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)); if (ECMA_PROPERTY_GET_TYPE (&prop_iter_p->types[0]) == ECMA_PROPERTY_TYPE_INTERNAL && ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (prop_iter_p->types + 0) == property_id) { return prop_iter_p->types + 0; } if (ECMA_PROPERTY_GET_TYPE (&prop_iter_p->types[1]) == ECMA_PROPERTY_TYPE_INTERNAL && ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (prop_iter_p->types + 1) == property_id) { return prop_iter_p->types + 1; } prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t, prop_iter_p->next_property_cp); } return NULL; } /* ecma_find_internal_property */
/** * Free memory associated with external pointer stored in the property * * Note: * property identifier should be one of the following: * - ECMA_INTERNAL_PROPERTY_NATIVE_CODE; * - 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_CODE || 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); if (sizeof (ecma_external_pointer_t) == sizeof (uint32_t)) { /* no additional memory was allocated for the pointer storage */ } else { 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); } } /* ecma_free_external_pointer_in_property */
/** * 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 */
/** * 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 */
/** * Free the internal property and values it references. */ static void ecma_free_internal_property (ecma_property_t *property_p) /**< the property */ { JERRY_ASSERT (property_p != NULL && ECMA_PROPERTY_GET_TYPE (property_p) == 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: /* ecma-value property except object */ { JERRY_ASSERT (!ecma_is_value_object (property_value)); ecma_free_value (property_value); break; } case ECMA_INTERNAL_PROPERTY_DATE_FLOAT: /* pointer to a ecma_number_t */ { ecma_number_t *num_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_number_t, property_value); ecma_dealloc_number (num_p); break; } case ECMA_INTERNAL_PROPERTY_NATIVE_CODE: /* an external pointer */ case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* an external pointer */ case ECMA_INTERNAL_PROPERTY_FREE_CALLBACK: /* an external pointer */ { ecma_free_external_pointer_in_property (property_p); break; } case ECMA_INTERNAL_PROPERTY_SCOPE: /* a lexical environment */ case ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP: /* an object */ case ECMA_INTERNAL_PROPERTY_CLASS: /* an enum */ case ECMA_INTERNAL_PROPERTY_BUILT_IN_ID: /* an integer */ case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_DESC: /* an integer */ case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_0_31: /* an integer (bit-mask) */ case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_32_63: /* an integer (bit-mask) */ case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION: { break; } case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS: { ecma_free_value_if_not_object (property_value); break; } case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS: { if (property_value != ECMA_NULL_POINTER) { ecma_free_values_collection (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_header_t, property_value), false); } break; } case ECMA_INTERNAL_PROPERTY__COUNT: /* not a real internal property type, * but number of the real internal property types */ { JERRY_UNREACHABLE (); break; } case ECMA_INTERNAL_PROPERTY_CODE_BYTECODE: /* compressed pointer to a bytecode array */ { ecma_bytecode_deref (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, property_value)); break; } case ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE: /* compressed pointer to a regexp bytecode array */ { ecma_compiled_code_t *bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, property_value); if (bytecode_p != NULL) { ecma_bytecode_deref (bytecode_p); } break; } } } /* ecma_free_internal_property */
/** * 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_get_named_data_property_value (property_p); if (ecma_is_value_object (value)) { ecma_object_t *value_obj_p = ecma_get_object_from_value (value); ecma_gc_set_object_visited (value_obj_p, true); } break; } case ECMA_PROPERTY_TYPE_NAMEDACCESSOR: { ecma_object_t *getter_obj_p = ecma_get_named_accessor_property_getter (property_p); ecma_object_t *setter_obj_p = ecma_get_named_accessor_property_setter (property_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_NUMBER_INDEXED_ARRAY_VALUES: /* a collection of ecma values */ case ECMA_INTERNAL_PROPERTY_STRING_INDEXED_ARRAY_VALUES: /* a collection of ecma values */ { JERRY_UNIMPLEMENTED ("Indexed array storage is not implemented yet."); } case ECMA_INTERNAL_PROPERTY_PROTOTYPE: /* the property's value is located in ecma_object_t * (see above in the routine) */ case ECMA_INTERNAL_PROPERTY_EXTENSIBLE: /* the property's value is located in ecma_object_t * (see above in the routine) */ case ECMA_INTERNAL_PROPERTY__COUNT: /* not a real internal property type, * but number of the real internal property types */ { JERRY_UNREACHABLE (); } case ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE: /* compressed pointer to a ecma_string_t */ case ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE: /* compressed pointer to a ecma_number_t */ case ECMA_INTERNAL_PROPERTY_PRIMITIVE_BOOLEAN_VALUE: /* a simple boolean value */ case ECMA_INTERNAL_PROPERTY_CLASS: /* an enum */ case ECMA_INTERNAL_PROPERTY_CODE_BYTECODE: /* compressed pointer to a bytecode array */ case ECMA_INTERNAL_PROPERTY_NATIVE_CODE: /* an external pointer */ 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_BUILT_IN_ID: /* an integer */ case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_DESC: /* an integer */ case ECMA_INTERNAL_PROPERTY_EXTENSION_ID: /* an integer */ case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_0_31: /* an integer (bit-mask) */ case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_32_63: /* an integer (bit-mask) */ case ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE: { 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_NON_NULL_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_NON_NULL_POINTER (ecma_object_t, property_value); ecma_gc_set_object_visited (obj_p, true); break; } } break; } default: { JERRY_UNREACHABLE (); break; } } } /* ecma_gc_mark_property */