Lazy instantiation of built-in function object's 'length' properties.

JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan r.ayrapetyan@samsung.com
This commit is contained in:
Ruben Ayrapetyan
2015-09-04 17:53:53 +03:00
parent bcf3396f26
commit 50fdccc8c9
6 changed files with 107 additions and 56 deletions
+1 -1
View File
@@ -346,7 +346,7 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* 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_FREE_CALLBACK: /* an object's native free callback */
case ECMA_INTERNAL_PROPERTY_BUILT_IN_ID: /* an integer */ case ECMA_INTERNAL_PROPERTY_BUILT_IN_ID: /* an integer */
case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_ID: /* an integer */ case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_DESC: /* an integer */
case ECMA_INTERNAL_PROPERTY_EXTENSION_ID: /* 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_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_NON_INSTANTIATED_BUILT_IN_MASK_32_63: /* an integer (bit-mask) */
+2 -2
View File
@@ -240,8 +240,8 @@ typedef enum
/** Implementation-defined identifier of built-in routine /** Implementation-defined identifier of built-in routine
that corresponds to a built-in function object that corresponds to a built-in function object
([[Built-in routine ID]]) */ ([[Built-in routine's description]]) */
ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_ID, ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_DESC,
/** Identifier of implementation-defined extension object */ /** Identifier of implementation-defined extension object */
ECMA_INTERNAL_PROPERTY_EXTENSION_ID, ECMA_INTERNAL_PROPERTY_EXTENSION_ID,
+1 -1
View File
@@ -796,7 +796,7 @@ ecma_free_internal_property (ecma_property_t *property_p) /**< the property */
case ECMA_INTERNAL_PROPERTY_CODE_BYTECODE: /* compressed pointer to a bytecode array */ case ECMA_INTERNAL_PROPERTY_CODE_BYTECODE: /* compressed pointer to a bytecode array */
case ECMA_INTERNAL_PROPERTY_CODE_FLAGS_AND_OFFSET: /* an integer */ case ECMA_INTERNAL_PROPERTY_CODE_FLAGS_AND_OFFSET: /* an integer */
case ECMA_INTERNAL_PROPERTY_BUILT_IN_ID: /* an integer */ case ECMA_INTERNAL_PROPERTY_BUILT_IN_ID: /* an integer */
case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_ID: /* an integer */ case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_DESC: /* an integer */
case ECMA_INTERNAL_PROPERTY_EXTENSION_ID: /* 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_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_NON_INSTANTIATED_BUILT_IN_MASK_32_63: /* an integer (bit-mask) */
@@ -24,32 +24,44 @@
#include "ecma-globals.h" #include "ecma-globals.h"
/** /**
* Position of built-in object's id field in [[Built-in routine ID]] internal property * Position of built-in object's id field in [[Built-in routine's description]] internal property
*/ */
#define ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_POS (0) #define ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_POS (0)
/** /**
* Width of built-in object's id field in [[Built-in routine ID]] internal property * Width of built-in object's id field in [[Built-in routine's description]] internal property
*/ */
#define ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_WIDTH (16) #define ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_WIDTH (8)
/** /**
* Position of built-in routine's id field in [[Built-in routine ID]] internal property * Position of built-in routine's id field in [[Built-in routine's description]] internal property
*/ */
#define ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_POS \ #define ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_POS \
(ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_POS + \ (ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_POS + \
ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_WIDTH) ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_WIDTH)
/** /**
* Width of built-in routine's id field in [[Built-in routine ID]] internal property * Width of built-in routine's id field in [[Built-in routine's description]] internal property
*/ */
#define ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_WIDTH (16) #define ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_WIDTH (16)
/**
* Position of built-in routine's length field in [[Built-in routine's description]] internal property
*/
#define ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_POS \
(ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_POS + \
ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_WIDTH)
/**
* Width of built-in routine's id field in [[Built-in routine's description]] internal property
*/
#define ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_WIDTH (8)
/* ecma-builtins.c */ /* ecma-builtins.c */
extern ecma_object_t* extern ecma_object_t*
ecma_builtin_make_function_object_for_routine (ecma_builtin_id_t builtin_id, ecma_builtin_make_function_object_for_routine (ecma_builtin_id_t builtin_id,
uint16_t routine_id, uint16_t routine_id,
ecma_number_t length_prop_num_value); uint8_t length_prop_num_value);
extern int32_t extern int32_t
ecma_builtin_bin_search_for_magic_string_id_in_array (const lit_magic_string_id_t ids[], ecma_builtin_bin_search_for_magic_string_id_in_array (const lit_magic_string_id_t ids[],
ecma_length_t array_length, ecma_length_t array_length,
@@ -291,43 +291,91 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object *
{ {
JERRY_ASSERT (ecma_get_object_is_builtin (object_p)); JERRY_ASSERT (ecma_get_object_is_builtin (object_p));
ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (object_p, const ecma_object_type_t type = ecma_get_object_type (object_p);
ECMA_INTERNAL_PROPERTY_BUILT_IN_ID);
ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_id_prop_p->u.internal_property.value;
JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id)); if (type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION)
switch (builtin_id)
{ {
ecma_string_t* magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
bool is_length_property = ecma_compare_ecma_strings (string_p, magic_string_length_p);
ecma_deref_ecma_string (magic_string_length_p);
if (is_length_property)
{
/*
* 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 *desc_prop_p = ecma_get_internal_property (object_p,
ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_DESC);
uint64_t builtin_routine_desc = desc_prop_p->u.internal_property.value;
JERRY_STATIC_ASSERT (sizeof (uint8_t) * JERRY_BITSINBYTE == ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_WIDTH);
uint8_t length_prop_value = (uint8_t) jrt_extract_bit_field (builtin_routine_desc,
ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_POS,
ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_WIDTH);
ecma_property_t *len_prop_p = ecma_create_named_data_property (object_p,
string_p,
false, false, false);
ecma_number_t *len_p = ecma_alloc_number ();
*len_p = length_prop_value;
ecma_set_named_data_property_value (len_prop_p, ecma_make_number_value (len_p));
JERRY_ASSERT (!ecma_is_property_configurable (len_prop_p));
return len_prop_p;
}
return NULL;
}
else
{
ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (object_p,
ECMA_INTERNAL_PROPERTY_BUILT_IN_ID);
ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_id_prop_p->u.internal_property.value;
JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id));
switch (builtin_id)
{
#define BUILTIN(builtin_id, \ #define BUILTIN(builtin_id, \
object_type, \ object_type, \
object_prototype_builtin_id, \ object_prototype_builtin_id, \
is_extensible, \ is_extensible, \
is_static, \ is_static, \
lowercase_name) \ lowercase_name) \
case builtin_id: \ case builtin_id: \
{ \ { \
return ecma_builtin_ ## lowercase_name ## _try_to_instantiate_property (object_p, \ return ecma_builtin_ ## lowercase_name ## _try_to_instantiate_property (object_p, \
string_p); \ string_p); \
} }
#include "ecma-builtins.inc.h" #include "ecma-builtins.inc.h"
case ECMA_BUILTIN_ID__COUNT: case ECMA_BUILTIN_ID__COUNT:
{ {
JERRY_UNREACHABLE (); JERRY_UNREACHABLE ();
} }
default: default:
{ {
#ifdef CONFIG_ECMA_COMPACT_PROFILE #ifdef CONFIG_ECMA_COMPACT_PROFILE
JERRY_UNREACHABLE (); JERRY_UNREACHABLE ();
#else /* CONFIG_ECMA_COMPACT_PROFILE */ #else /* CONFIG_ECMA_COMPACT_PROFILE */
JERRY_UNIMPLEMENTED ("The built-in is not implemented."); JERRY_UNIMPLEMENTED ("The built-in is not implemented.");
#endif /* !CONFIG_ECMA_COMPACT_PROFILE */ #endif /* !CONFIG_ECMA_COMPACT_PROFILE */
}
} }
}
JERRY_UNREACHABLE (); JERRY_UNREACHABLE ();
}
} /* ecma_builtin_try_to_instantiate_property */ } /* ecma_builtin_try_to_instantiate_property */
/** /**
@@ -343,9 +391,8 @@ ecma_builtin_make_function_object_for_routine (ecma_builtin_id_t builtin_id, /**
with the routine */ with the routine */
uint16_t routine_id, /**< builtin-wide identifier of the built-in uint16_t routine_id, /**< builtin-wide identifier of the built-in
object's routine property */ object's routine property */
ecma_number_t length_prop_num_value) /**< ecma-number - value uint8_t length_prop_value) /**< value of 'length' property
of 'length' property of function object to create */
of function object to create */
{ {
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE);
@@ -363,23 +410,16 @@ ecma_builtin_make_function_object_for_routine (ecma_builtin_id_t builtin_id, /**
routine_id, routine_id,
ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_POS, ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_POS,
ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_WIDTH); ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_WIDTH);
ecma_property_t *routine_id_prop_p = ecma_create_internal_property (func_obj_p, packed_value = jrt_set_bit_field_value (packed_value,
ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_ID); length_prop_value,
ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_POS,
ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_WIDTH);
ecma_property_t *routine_desc_prop_p = ecma_create_internal_property (func_obj_p,
ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_DESC);
JERRY_ASSERT ((uint32_t) packed_value == packed_value); JERRY_ASSERT ((uint32_t) packed_value == packed_value);
routine_id_prop_p->u.internal_property.value = (uint32_t) packed_value; routine_desc_prop_p->u.internal_property.value = (uint32_t) packed_value;
ecma_string_t* magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
ecma_property_t *len_prop_p = ecma_create_named_data_property (func_obj_p,
magic_string_length_p,
false, false, false);
ecma_deref_ecma_string (magic_string_length_p);
ecma_number_t* len_p = ecma_alloc_number ();
*len_p = length_prop_num_value;
ecma_set_named_data_property_value (len_prop_p, ecma_make_number_value (len_p));
return func_obj_p; return func_obj_p;
} /* ecma_builtin_make_function_object_for_routine */ } /* ecma_builtin_make_function_object_for_routine */
@@ -414,16 +454,16 @@ ecma_builtin_dispatch_call (ecma_object_t *obj_p, /**< built-in object */
if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION) if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION)
{ {
ecma_property_t *id_prop_p = ecma_get_internal_property (obj_p, ecma_property_t *desc_prop_p = ecma_get_internal_property (obj_p,
ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_ID); ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_DESC);
uint64_t packed_built_in_and_routine_id = id_prop_p->u.internal_property.value; uint64_t builtin_routine_desc = desc_prop_p->u.internal_property.value;
uint64_t built_in_id_field = jrt_extract_bit_field (packed_built_in_and_routine_id, uint64_t built_in_id_field = jrt_extract_bit_field (builtin_routine_desc,
ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_POS, ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_POS,
ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_WIDTH); ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_WIDTH);
JERRY_ASSERT (built_in_id_field < ECMA_BUILTIN_ID__COUNT); JERRY_ASSERT (built_in_id_field < ECMA_BUILTIN_ID__COUNT);
uint64_t routine_id_field = jrt_extract_bit_field (packed_built_in_and_routine_id, uint64_t routine_id_field = jrt_extract_bit_field (builtin_routine_desc,
ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_POS, ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_POS,
ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_WIDTH); ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_WIDTH);
JERRY_ASSERT ((uint16_t) routine_id_field == routine_id_field); JERRY_ASSERT ((uint16_t) routine_id_field == routine_id_field);
+1 -2
View File
@@ -145,8 +145,7 @@ ecma_op_object_get_own_property_longpath (ecma_object_t *obj_p, /**< the object
if (unlikely (prop_p == NULL)) if (unlikely (prop_p == NULL))
{ {
if (is_builtin if (is_builtin)
&& type != ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION)
{ {
prop_p = ecma_builtin_try_to_instantiate_property (obj_p, property_name_p); prop_p = ecma_builtin_try_to_instantiate_property (obj_p, property_name_p);
} }