/** * If the property's name is one of built-in properties of the object * that is not instantiated yet, instantiate the property and * return pointer to the instantiated property. * * @return pointer property, if one was instantiated, * NULL - otherwise. */ ecma_property_t * ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object */ ecma_string_t *string_p) /**< property's name */ { JERRY_ASSERT (ecma_get_object_is_builtin (object_p)); ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION && ecma_builtin_function_is_routine (object_p)) { if (ecma_string_is_length (string_p)) { /* * Lazy instantiation of 'length' property * * Note: * We don't need to mark that the property was already lazy instantiated, * as it is non-configurable and so can't be deleted */ ecma_property_t *len_prop_p = ecma_create_named_data_property (object_p, string_p, ECMA_PROPERTY_FIXED); ecma_set_named_data_property_value (len_prop_p, ecma_make_integer_value (ext_obj_p->u.built_in.length)); JERRY_ASSERT (!ecma_is_property_configurable (len_prop_p)); return len_prop_p; } return NULL; } lit_magic_string_id_t magic_string_id; if (!ecma_is_string_magic (string_p, &magic_string_id)) { return NULL; } ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) ext_obj_p->u.built_in.id; JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id)); const ecma_builtin_property_descriptor_t *property_list_p = ecma_builtin_property_list_references[builtin_id]; const ecma_builtin_property_descriptor_t *curr_property_p = property_list_p; while (curr_property_p->magic_string_id != magic_string_id) { if (curr_property_p->magic_string_id == LIT_MAGIC_STRING__COUNT) { return NULL; } curr_property_p++; } uint32_t index = (uint32_t) (curr_property_p - property_list_p); JERRY_ASSERT (index < 64); if (likely (index < 32)) { uint32_t bit_for_index = (uint32_t) 1u << index; if (ext_obj_p->u.built_in.instantiated_bitset & bit_for_index) { /* This property was instantiated before. */ return NULL; } ext_obj_p->u.built_in.instantiated_bitset |= bit_for_index; } else { uint32_t bit_for_index = (uint32_t) 1u << (index - 32); ecma_value_t *mask_prop_p = ecma_find_internal_property (object_p, ECMA_INTERNAL_PROPERTY_INSTANTIATED_MASK_32_63); uint32_t instantiated_bitset; if (mask_prop_p == NULL) { mask_prop_p = ecma_create_internal_property (object_p, ECMA_INTERNAL_PROPERTY_INSTANTIATED_MASK_32_63); instantiated_bitset = 0; } else { instantiated_bitset = *mask_prop_p; if (instantiated_bitset & bit_for_index) { /* This property was instantiated before. */ return NULL; } } *mask_prop_p = (instantiated_bitset | bit_for_index); } ecma_value_t value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); switch (curr_property_p->type) { case ECMA_BUILTIN_PROPERTY_SIMPLE: { value = ecma_make_simple_value (curr_property_p->value); break; } case ECMA_BUILTIN_PROPERTY_NUMBER: { ecma_number_t num = 0.0; if (curr_property_p->value < ECMA_BUILTIN_NUMBER_MAX) { num = curr_property_p->value; } else if (curr_property_p->value < ECMA_BUILTIN_NUMBER_NAN) { static const ecma_number_t builtin_number_list[] = { ECMA_NUMBER_MAX_VALUE, ECMA_NUMBER_MIN_VALUE, ECMA_NUMBER_E, ECMA_NUMBER_PI, ECMA_NUMBER_LN10, ECMA_NUMBER_LN2, ECMA_NUMBER_LOG2E, ECMA_NUMBER_LOG10E, ECMA_NUMBER_SQRT2, ECMA_NUMBER_SQRT_1_2 }; num = builtin_number_list[curr_property_p->value - ECMA_BUILTIN_NUMBER_MAX]; } else { switch (curr_property_p->value) { case ECMA_BUILTIN_NUMBER_NAN: { num = ecma_number_make_nan (); break; } case ECMA_BUILTIN_NUMBER_POSITIVE_INFINITY: { num = ecma_number_make_infinity (false); break; } case ECMA_BUILTIN_NUMBER_NEGATIVE_INFINITY: { num = ecma_number_make_infinity (true); break; } default: { JERRY_UNREACHABLE (); break; } } } value = ecma_make_number_value (num); break; } case ECMA_BUILTIN_PROPERTY_STRING: { value = ecma_make_string_value (ecma_get_magic_string (curr_property_p->value)); break; } case ECMA_BUILTIN_PROPERTY_OBJECT: { value = ecma_make_object_value (ecma_builtin_get (curr_property_p->value)); break; } case ECMA_BUILTIN_PROPERTY_ROUTINE: { ecma_object_t *func_obj_p; func_obj_p = ecma_builtin_make_function_object_for_routine (builtin_id, ECMA_GET_ROUTINE_ID (curr_property_p->value), ECMA_GET_ROUTINE_LENGTH (curr_property_p->value)); value = ecma_make_object_value (func_obj_p); break; } default: { JERRY_UNREACHABLE (); return NULL; } } ecma_property_t *prop_p = ecma_create_named_data_property (object_p, string_p, curr_property_p->attributes); ecma_set_named_data_property_value (prop_p, value); /* Reference count of objects must be decreased. */ if (ecma_is_value_object (value)) { ecma_free_value (value); } return prop_p; } /* ecma_builtin_try_to_instantiate_property */
/** * The Math object's 'min' routine * * See also: * ECMA-262 v5, 15.8.2.12 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_math_object_min (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */ const ecma_value_t args[], /**< arguments list */ ecma_length_t args_number) /**< number of arguments */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_number_t ret_num = ecma_number_make_infinity (false); bool is_NaN = false; for (ecma_length_t arg_index = 0; arg_index < args_number && ecma_is_value_empty (ret_value); arg_index++) { ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, args[arg_index], ret_value); if (!is_NaN) { if (unlikely (ecma_number_is_nan (arg_num))) { ret_num = arg_num; is_NaN = true; } else if (ecma_number_is_zero (arg_num) /* both numbers are zeroes */ && ecma_number_is_zero (ret_num)) { if (ecma_number_is_negative (arg_num)) { ret_num = arg_num; } } else if (ecma_number_is_infinity (arg_num)) { if (ecma_number_is_negative (arg_num)) { ret_num = arg_num; } } else if (ecma_number_is_infinity (ret_num)) { if (!ecma_number_is_negative (ret_num)) { ret_num = arg_num; } } else { JERRY_ASSERT (!ecma_number_is_nan (arg_num) && !ecma_number_is_infinity (arg_num)); JERRY_ASSERT (!ecma_number_is_nan (ret_num) && !ecma_number_is_infinity (ret_num)); if (arg_num < ret_num) { ret_num = arg_num; } } } ECMA_OP_TO_NUMBER_FINALIZE (arg_num); } if (ecma_is_value_empty (ret_value)) { ecma_number_t *num_p = ecma_alloc_number (); *num_p = ret_num; ret_value = ecma_make_number_value (num_p); } return ret_value; } /* ecma_builtin_math_object_min */