From ed14474f375eb9caac66f4a9435029c124135488 Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Thu, 28 May 2015 20:49:55 +0300 Subject: [PATCH] Fixing retrieval of [[Class]] properties for built-in function objects, optimizing memory related to [[Class]] property. - introduced ecma_object_get_class_name interface; - removed creation of [[Class]] internal property for types of objects that unambiguously determine the [[Class]] value. Related issue: #112 JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan r.ayrapetyan@samsung.com --- .../ecma-builtin-array-prototype.cpp | 2 +- .../builtin-objects/ecma-builtin-array.cpp | 5 +- .../ecma-builtin-boolean-prototype.cpp | 4 +- .../builtin-objects/ecma-builtin-helpers.cpp | 4 +- .../ecma-builtin-number-prototype.cpp | 8 +- .../ecma-builtin-string-prototype.cpp | 4 +- .../builtin-objects/ecma-builtins-internal.h | 1 - .../ecma/builtin-objects/ecma-builtins.cpp | 35 ++- .../ecma/builtin-objects/ecma-builtins.h | 1 - .../ecma/builtin-objects/ecma-builtins.inc.h | 31 --- .../ecma/operations/ecma-array-object.cpp | 7 +- .../ecma/operations/ecma-function-object.cpp | 27 ++- .../operations/ecma-objects-arguments.cpp | 7 + .../ecma/operations/ecma-objects-general.cpp | 15 +- jerry-core/ecma/operations/ecma-objects.cpp | 200 +++++++++++++++++- jerry-core/ecma/operations/ecma-objects.h | 2 + .../ecma/operations/ecma-string-object.cpp | 7 +- tests/jerry/regression-test-issue-112.js | 16 ++ 18 files changed, 284 insertions(+), 92 deletions(-) create mode 100644 tests/jerry/regression-test-issue-112.js diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp index 5114e02927..577e3a6ab3 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp @@ -139,7 +139,7 @@ ecma_builtin_array_prototype_object_concat (ecma_value_t this_arg, /**< this arg { /* 5.b */ if (ecma_is_value_object (args[arg_index]) && - (ecma_get_object_type (ecma_get_object_from_value (args[arg_index])) == ECMA_OBJECT_TYPE_ARRAY)) + (ecma_object_get_class_name (ecma_get_object_from_value (args[arg_index])) == ECMA_MAGIC_STRING_ARRAY_UL)) { /* 5.b.ii */ ECMA_TRY_CATCH (arg_len_value, diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-array.cpp b/jerry-core/ecma/builtin-objects/ecma-builtin-array.cpp index ccf4b41a0d..8cbe0326cc 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array.cpp @@ -63,10 +63,7 @@ ecma_builtin_array_object_is_array (ecma_value_t this_arg __attr_unused___, /**< { ecma_object_t *obj_p = ecma_get_object_from_value (arg); - ecma_property_t *class_prop_p = ecma_get_internal_property (obj_p, - ECMA_INTERNAL_PROPERTY_CLASS); - - if (class_prop_p->u.internal_property.value == ECMA_MAGIC_STRING_ARRAY_UL) + if (ecma_object_get_class_name (obj_p) == ECMA_MAGIC_STRING_ARRAY_UL) { is_array = ECMA_SIMPLE_VALUE_TRUE; } diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.cpp b/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.cpp index b424e4b3e1..cb9697c261 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.cpp @@ -102,9 +102,7 @@ ecma_builtin_boolean_prototype_object_value_of (ecma_value_t this_arg) /**< this { ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); - ecma_property_t *class_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS); - - if (class_prop_p->u.internal_property.value == ECMA_MAGIC_STRING_BOOLEAN_UL) + if (ecma_object_get_class_name (obj_p) == ECMA_MAGIC_STRING_BOOLEAN_UL) { ecma_property_t *prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_BOOLEAN_VALUE); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.cpp b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.cpp index 9bb38c27dc..7efa100603 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.cpp @@ -71,9 +71,7 @@ ecma_builtin_helper_object_to_string (const ecma_value_t this_arg) /**< this arg ecma_object_t *obj_p = ecma_get_object_from_completion_value (obj_this); - ecma_property_t *class_prop_p = ecma_get_internal_property (obj_p, - ECMA_INTERNAL_PROPERTY_CLASS); - type_string = (ecma_magic_string_id_t) class_prop_p->u.internal_property.value; + type_string = ecma_object_get_class_name (obj_p); ecma_free_completion_value (obj_this); } diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.cpp b/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.cpp index 4fa7526812..38b995d8e1 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.cpp @@ -70,9 +70,7 @@ ecma_builtin_number_prototype_object_to_string (ecma_value_t this_arg, /**< this { ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); - ecma_property_t *class_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS); - - if (class_prop_p->u.internal_property.value == ECMA_MAGIC_STRING_NUMBER_UL) + if (ecma_object_get_class_name (obj_p) == ECMA_MAGIC_STRING_NUMBER_UL) { ecma_property_t *prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE); @@ -137,9 +135,7 @@ ecma_builtin_number_prototype_object_value_of (ecma_value_t this_arg) /**< this { ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); - ecma_property_t *class_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS); - - if (class_prop_p->u.internal_property.value == ECMA_MAGIC_STRING_NUMBER_UL) + if (ecma_object_get_class_name (obj_p) == ECMA_MAGIC_STRING_NUMBER_UL) { ecma_property_t *prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.cpp b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.cpp index 7c86e5618b..96f9c1326c 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.cpp @@ -64,9 +64,7 @@ ecma_builtin_string_prototype_object_to_string (ecma_value_t this_arg) /**< this { ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); - ecma_property_t *class_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS); - - if (class_prop_p->u.internal_property.value == ECMA_MAGIC_STRING_STRING_UL) + if (ecma_object_get_class_name (obj_p) == ECMA_MAGIC_STRING_STRING_UL) { ecma_property_t *prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h b/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h index fdc5f87342..6c90b948bc 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h @@ -57,7 +57,6 @@ ecma_builtin_bin_search_for_magic_string_id_in_array (const ecma_magic_string_id #define BUILTIN(builtin_id, \ object_type, \ - object_class, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.cpp b/jerry-core/ecma/builtin-objects/ecma-builtins.cpp index 93596108d1..5b7d121940 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.cpp @@ -54,12 +54,16 @@ ecma_builtin_is (ecma_object_t *obj_p, /**< pointer to an object */ JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); - if (unlikely (ecma_builtin_objects[builtin_id] == NULL)) + if (ecma_builtin_objects[builtin_id] == NULL) { - ecma_instantiate_builtin (builtin_id); + /* If a built-in object is not instantiated, + * the specified object cannot be the built-in object */ + return false; + } + else + { + return (obj_p == ecma_builtin_objects[builtin_id]); } - - return (obj_p == ecma_builtin_objects[builtin_id]); } /* ecma_builtin_is */ /** @@ -94,14 +98,15 @@ static ecma_object_t* ecma_builtin_init_object (ecma_builtin_id_t obj_builtin_id, /**< built-in ID */ ecma_object_t* prototype_obj_p, /**< prototype object */ ecma_object_type_t obj_type, /**< object's type */ - ecma_magic_string_id_t obj_class, /**< object's class */ bool is_extensible) /**< value of object's [[Extensible]] property */ { ecma_object_t *object_obj_p = ecma_create_object (prototype_obj_p, is_extensible, obj_type); - ecma_property_t *class_prop_p = ecma_create_internal_property (object_obj_p, - ECMA_INTERNAL_PROPERTY_CLASS); - class_prop_p->u.internal_property.value = obj_class; + /* + * [[Class]] property of built-in object is not stored explicitly. + * + * See also: ecma_object_get_class_name + */ ecma_property_t *built_in_id_prop_p = ecma_create_internal_property (object_obj_p, ECMA_INTERNAL_PROPERTY_BUILT_IN_ID); @@ -183,7 +188,6 @@ ecma_instantiate_builtin (ecma_builtin_id_t id) /**< built-in id */ { #define BUILTIN(builtin_id, \ object_type, \ - object_class, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ @@ -211,11 +215,10 @@ ecma_instantiate_builtin (ecma_builtin_id_t id) /**< built-in id */ JERRY_ASSERT (prototype_obj_p != NULL); \ } \ \ - ecma_object_t *builtin_obj_p = ecma_builtin_init_object (builtin_id, \ - prototype_obj_p, \ - object_type, \ - object_class, \ - is_extensible); \ + ecma_object_t *builtin_obj_p = ecma_builtin_init_object (builtin_id, \ + prototype_obj_p, \ + object_type, \ + is_extensible); \ ecma_builtin_objects[builtin_id] = builtin_obj_p; \ \ break; \ @@ -274,7 +277,6 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * { #define BUILTIN(builtin_id, \ object_type, \ - object_class, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ @@ -411,7 +413,6 @@ ecma_builtin_dispatch_call (ecma_object_t *obj_p, /**< built-in object */ { #define BUILTIN(builtin_id, \ object_type, \ - object_class, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ @@ -474,7 +475,6 @@ ecma_builtin_dispatch_construct (ecma_object_t *obj_p, /**< built-in object */ { #define BUILTIN(builtin_id, \ object_type, \ - object_class, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ @@ -530,7 +530,6 @@ ecma_builtin_dispatch_routine (ecma_builtin_id_t builtin_object_id, /**< built-i { #define BUILTIN(builtin_id, \ object_type, \ - object_class, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.h b/jerry-core/ecma/builtin-objects/ecma-builtins.h index 73e8093dbe..e0904c2644 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.h @@ -25,7 +25,6 @@ typedef enum { #define BUILTIN(builtin_id, \ object_type, \ - object_class, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h index 393466fa13..d89e3a744c 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h @@ -19,7 +19,6 @@ /* The Object.prototype object (15.2.4) */ BUILTIN (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, ECMA_OBJECT_TYPE_GENERAL, - ECMA_MAGIC_STRING_OBJECT_UL, ECMA_BUILTIN_ID__COUNT /* no prototype */, true, true, @@ -28,7 +27,6 @@ BUILTIN (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, /* The Object object (15.2.1) */ BUILTIN (ECMA_BUILTIN_ID_OBJECT, ECMA_OBJECT_TYPE_FUNCTION, - ECMA_MAGIC_STRING_OBJECT_UL, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, true, true, @@ -38,7 +36,6 @@ BUILTIN (ECMA_BUILTIN_ID_OBJECT, /* The Array.prototype object (15.4.4) */ BUILTIN (ECMA_BUILTIN_ID_ARRAY_PROTOTYPE, ECMA_OBJECT_TYPE_ARRAY, - ECMA_MAGIC_STRING_ARRAY_UL, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, true, true, @@ -47,7 +44,6 @@ BUILTIN (ECMA_BUILTIN_ID_ARRAY_PROTOTYPE, /* The Array object (15.4.1) */ BUILTIN (ECMA_BUILTIN_ID_ARRAY, ECMA_OBJECT_TYPE_FUNCTION, - ECMA_MAGIC_STRING_ARRAY_UL, ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, true, true, @@ -58,7 +54,6 @@ BUILTIN (ECMA_BUILTIN_ID_ARRAY, /* The String.prototype object (15.5.4) */ BUILTIN (ECMA_BUILTIN_ID_STRING_PROTOTYPE, ECMA_OBJECT_TYPE_GENERAL, - ECMA_MAGIC_STRING_STRING_UL, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, true, true, @@ -67,7 +62,6 @@ BUILTIN (ECMA_BUILTIN_ID_STRING_PROTOTYPE, /* The String object (15.5.1) */ BUILTIN (ECMA_BUILTIN_ID_STRING, ECMA_OBJECT_TYPE_FUNCTION, - ECMA_MAGIC_STRING_STRING_UL, ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, true, true, @@ -78,7 +72,6 @@ BUILTIN (ECMA_BUILTIN_ID_STRING, /* The Boolean.prototype object (15.6.4) */ BUILTIN (ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE, ECMA_OBJECT_TYPE_GENERAL, - ECMA_MAGIC_STRING_BOOLEAN_UL, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, true, true, @@ -87,7 +80,6 @@ BUILTIN (ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE, /* The Boolean object (15.6.1) */ BUILTIN (ECMA_BUILTIN_ID_BOOLEAN, ECMA_OBJECT_TYPE_FUNCTION, - ECMA_MAGIC_STRING_BOOLEAN_UL, ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, true, true, @@ -98,7 +90,6 @@ BUILTIN (ECMA_BUILTIN_ID_BOOLEAN, /* The Number.prototype object (15.7.4) */ BUILTIN (ECMA_BUILTIN_ID_NUMBER_PROTOTYPE, ECMA_OBJECT_TYPE_GENERAL, - ECMA_MAGIC_STRING_NUMBER_UL, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, true, true, @@ -107,7 +98,6 @@ BUILTIN (ECMA_BUILTIN_ID_NUMBER_PROTOTYPE, /* The Number object (15.7.1) */ BUILTIN (ECMA_BUILTIN_ID_NUMBER, ECMA_OBJECT_TYPE_FUNCTION, - ECMA_MAGIC_STRING_NUMBER_UL, ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, true, true, @@ -117,7 +107,6 @@ BUILTIN (ECMA_BUILTIN_ID_NUMBER, /* The Function.prototype object (15.3.4) */ BUILTIN (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, ECMA_OBJECT_TYPE_FUNCTION, - ECMA_MAGIC_STRING_FUNCTION_UL, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, true, true, @@ -126,7 +115,6 @@ BUILTIN (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, /* The Function object (15.3.1) */ BUILTIN (ECMA_BUILTIN_ID_FUNCTION, ECMA_OBJECT_TYPE_FUNCTION, - ECMA_MAGIC_STRING_FUNCTION_UL, ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, true, true, @@ -136,7 +124,6 @@ BUILTIN (ECMA_BUILTIN_ID_FUNCTION, /* The Math object (15.8) */ BUILTIN (ECMA_BUILTIN_ID_MATH, ECMA_OBJECT_TYPE_GENERAL, - ECMA_MAGIC_STRING_MATH_UL, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, true, true, @@ -147,7 +134,6 @@ BUILTIN (ECMA_BUILTIN_ID_MATH, /* The Error.prototype object (15.11.4) */ BUILTIN (ECMA_BUILTIN_ID_ERROR_PROTOTYPE, ECMA_OBJECT_TYPE_GENERAL, - ECMA_MAGIC_STRING_ERROR_UL, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, true, true, @@ -156,7 +142,6 @@ BUILTIN (ECMA_BUILTIN_ID_ERROR_PROTOTYPE, /* The Error object (15.11.1) */ BUILTIN (ECMA_BUILTIN_ID_ERROR, ECMA_OBJECT_TYPE_FUNCTION, - ECMA_MAGIC_STRING_ERROR_UL, ECMA_BUILTIN_ID_ERROR_PROTOTYPE, true, true, @@ -165,7 +150,6 @@ BUILTIN (ECMA_BUILTIN_ID_ERROR, /* The EvalError.prototype object (15.11.6.1) */ BUILTIN (ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE, ECMA_OBJECT_TYPE_GENERAL, - ECMA_MAGIC_STRING_ERROR_UL, ECMA_BUILTIN_ID_ERROR_PROTOTYPE, true, true, @@ -174,7 +158,6 @@ BUILTIN (ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE, /* The EvalError object (15.11.6.1) */ BUILTIN (ECMA_BUILTIN_ID_EVAL_ERROR, ECMA_OBJECT_TYPE_FUNCTION, - ECMA_MAGIC_STRING_ERROR_UL, ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE, true, true, @@ -183,7 +166,6 @@ BUILTIN (ECMA_BUILTIN_ID_EVAL_ERROR, /* The RangeError.prototype object (15.11.6.2) */ BUILTIN (ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE, ECMA_OBJECT_TYPE_GENERAL, - ECMA_MAGIC_STRING_ERROR_UL, ECMA_BUILTIN_ID_ERROR_PROTOTYPE, true, true, @@ -192,7 +174,6 @@ BUILTIN (ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE, /* The RangeError object (15.11.6.2) */ BUILTIN (ECMA_BUILTIN_ID_RANGE_ERROR, ECMA_OBJECT_TYPE_FUNCTION, - ECMA_MAGIC_STRING_ERROR_UL, ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE, true, true, @@ -201,7 +182,6 @@ BUILTIN (ECMA_BUILTIN_ID_RANGE_ERROR, /* The ReferenceError.prototype object (15.11.6.3) */ BUILTIN (ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE, ECMA_OBJECT_TYPE_GENERAL, - ECMA_MAGIC_STRING_ERROR_UL, ECMA_BUILTIN_ID_ERROR_PROTOTYPE, true, true, @@ -210,7 +190,6 @@ BUILTIN (ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE, /* The ReferenceError object (15.11.6.3) */ BUILTIN (ECMA_BUILTIN_ID_REFERENCE_ERROR, ECMA_OBJECT_TYPE_FUNCTION, - ECMA_MAGIC_STRING_ERROR_UL, ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE, true, true, @@ -219,7 +198,6 @@ BUILTIN (ECMA_BUILTIN_ID_REFERENCE_ERROR, /* The SyntaxError.prototype object (15.11.6.4) */ BUILTIN (ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE, ECMA_OBJECT_TYPE_GENERAL, - ECMA_MAGIC_STRING_ERROR_UL, ECMA_BUILTIN_ID_ERROR_PROTOTYPE, true, true, @@ -228,7 +206,6 @@ BUILTIN (ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE, /* The SyntaxError object (15.11.6.4) */ BUILTIN (ECMA_BUILTIN_ID_SYNTAX_ERROR, ECMA_OBJECT_TYPE_FUNCTION, - ECMA_MAGIC_STRING_ERROR_UL, ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE, true, true, @@ -237,7 +214,6 @@ BUILTIN (ECMA_BUILTIN_ID_SYNTAX_ERROR, /* The TypeError.prototype object (15.11.6.5) */ BUILTIN (ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE, ECMA_OBJECT_TYPE_GENERAL, - ECMA_MAGIC_STRING_ERROR_UL, ECMA_BUILTIN_ID_ERROR_PROTOTYPE, true, true, @@ -246,7 +222,6 @@ BUILTIN (ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE, /* The TypeError object (15.11.6.5) */ BUILTIN (ECMA_BUILTIN_ID_TYPE_ERROR, ECMA_OBJECT_TYPE_FUNCTION, - ECMA_MAGIC_STRING_ERROR_UL, ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE, true, true, @@ -255,7 +230,6 @@ BUILTIN (ECMA_BUILTIN_ID_TYPE_ERROR, /* The URIError.prototype object (15.11.6.6) */ BUILTIN (ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE, ECMA_OBJECT_TYPE_GENERAL, - ECMA_MAGIC_STRING_ERROR_UL, ECMA_BUILTIN_ID_ERROR_PROTOTYPE, true, true, @@ -264,7 +238,6 @@ BUILTIN (ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE, /* The URIError object (15.11.6.6) */ BUILTIN (ECMA_BUILTIN_ID_URI_ERROR, ECMA_OBJECT_TYPE_FUNCTION, - ECMA_MAGIC_STRING_ERROR_UL, ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE, true, true, @@ -274,7 +247,6 @@ BUILTIN (ECMA_BUILTIN_ID_URI_ERROR, /**< The [[ThrowTypeError]] object (13.2.3) */ BUILTIN (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER, ECMA_OBJECT_TYPE_FUNCTION, - ECMA_MAGIC_STRING_FUNCTION_UL, ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, false, true, @@ -284,7 +256,6 @@ BUILTIN (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER, /* The CompactProfileError object defined in the Compact Profile */ BUILTIN (ECMA_BUILTIN_ID_COMPACT_PROFILE_ERROR, ECMA_OBJECT_TYPE_FUNCTION, - ECMA_MAGIC_STRING_COMPACT_PROFILE_ERROR_UL, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, false, true, @@ -294,7 +265,6 @@ BUILTIN (ECMA_BUILTIN_ID_COMPACT_PROFILE_ERROR, /* The Global object (15.1) */ BUILTIN (ECMA_BUILTIN_ID_GLOBAL, ECMA_OBJECT_TYPE_GENERAL, - ECMA_MAGIC_STRING_OBJECT_UL, ECMA_BUILTIN_ID__COUNT /* no prototype */, true, true, @@ -303,7 +273,6 @@ BUILTIN (ECMA_BUILTIN_ID_GLOBAL, /* Jerry's dynamic extension proxy object */ BUILTIN (ECMA_BUILTIN_ID_JERRY, ECMA_OBJECT_TYPE_GENERAL, - ECMA_MAGIC_STRING_OBJECT_UL, ECMA_BUILTIN_ID__COUNT, /* no prototype */ false, false, diff --git a/jerry-core/ecma/operations/ecma-array-object.cpp b/jerry-core/ecma/operations/ecma-array-object.cpp index 32ea8797fe..b4ece8e354 100644 --- a/jerry-core/ecma/operations/ecma-array-object.cpp +++ b/jerry-core/ecma/operations/ecma-array-object.cpp @@ -110,8 +110,11 @@ ecma_op_create_array_object (const ecma_value_t *arguments_list_p, /**< list of ecma_object_t *obj_p = ecma_create_object (array_prototype_obj_p, true, ECMA_OBJECT_TYPE_ARRAY); ecma_deref_object (array_prototype_obj_p); - ecma_property_t *class_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS); - class_prop_p->u.internal_property.value = ECMA_MAGIC_STRING_ARRAY_UL; + /* + * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_ARRAY type. + * + * See also: ecma_object_get_class_name + */ ecma_string_t *length_magic_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING_LENGTH); ecma_number_t *length_num_p = ecma_alloc_number (); diff --git a/jerry-core/ecma/operations/ecma-function-object.cpp b/jerry-core/ecma/operations/ecma-function-object.cpp index 034f4bfcc2..b306d6bbec 100644 --- a/jerry-core/ecma/operations/ecma-function-object.cpp +++ b/jerry-core/ecma/operations/ecma-function-object.cpp @@ -161,8 +161,11 @@ ecma_op_create_function_object (ecma_string_t* formal_parameter_list_p[], /**< f */ // 3. - ecma_property_t *class_prop_p = ecma_create_internal_property (f, ECMA_INTERNAL_PROPERTY_CLASS); - class_prop_p->u.internal_property.value = ECMA_MAGIC_STRING_FUNCTION_UL; + /* + * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_FUNCTION type. + * + * See also: ecma_object_get_class_name + */ // 9. ecma_property_t *scope_prop_p = ecma_create_internal_property (f, ECMA_INTERNAL_PROPERTY_SCOPE); @@ -305,8 +308,11 @@ ecma_op_create_external_function_object (ecma_external_pointer_t code_p) /**< po ecma_deref_object (prototype_obj_p); - ecma_property_t *class_prop_p = ecma_create_internal_property (function_obj_p, ECMA_INTERNAL_PROPERTY_CLASS); - class_prop_p->u.internal_property.value = ECMA_MAGIC_STRING_FUNCTION_UL; + /* + * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION type. + * + * See also: ecma_object_get_class_name + */ bool is_created = ecma_create_external_pointer_property (function_obj_p, ECMA_INTERNAL_PROPERTY_NATIVE_CODE, @@ -674,12 +680,17 @@ ecma_op_function_construct_simple_or_external (ecma_object_t *func_obj_p, /**< F // 1., 2., 4. ecma_object_t *obj_p = ecma_create_object (prototype_p, true, ECMA_OBJECT_TYPE_GENERAL); - // 3. - ecma_property_t *class_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS); - class_prop_p->u.internal_property.value = ECMA_MAGIC_STRING_OBJECT_UL; - ecma_deref_object (prototype_p); + // 3. + /* + * [[Class]] property of ECMA_OBJECT_TYPE_GENERAL type objects + * without ECMA_INTERNAL_PROPERTY_CLASS internal property + * is "Object". + * + * See also: ecma_object_get_class_name. + */ + // 8. ECMA_TRY_CATCH (call_completion, ecma_op_function_call (func_obj_p, diff --git a/jerry-core/ecma/operations/ecma-objects-arguments.cpp b/jerry-core/ecma/operations/ecma-objects-arguments.cpp index 505ad1628f..3224d3606f 100644 --- a/jerry-core/ecma/operations/ecma-objects-arguments.cpp +++ b/jerry-core/ecma/operations/ecma-objects-arguments.cpp @@ -190,6 +190,13 @@ ecma_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function */ // 12. ecma_set_object_type (obj_p, ECMA_OBJECT_TYPE_ARGUMENTS); + /* + * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_ARGUMENTS type. + * + * See also: ecma_object_get_class_name + */ + ecma_delete_property (obj_p, class_prop_p); + ecma_property_t *parameters_map_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP); ECMA_SET_POINTER (parameters_map_prop_p->u.internal_property.value, map_p); diff --git a/jerry-core/ecma/operations/ecma-objects-general.cpp b/jerry-core/ecma/operations/ecma-objects-general.cpp index ccff89266d..c9a193f6fa 100644 --- a/jerry-core/ecma/operations/ecma-objects-general.cpp +++ b/jerry-core/ecma/operations/ecma-objects-general.cpp @@ -66,8 +66,13 @@ ecma_op_create_object_object_noarg (void) ecma_deref_object (object_prototype_p); - ecma_property_t *class_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS); - class_prop_p->u.internal_property.value = ECMA_MAGIC_STRING_OBJECT_UL; + /* + * [[Class]] property of ECMA_OBJECT_TYPE_GENERAL type objects + * without ECMA_INTERNAL_PROPERTY_CLASS internal property + * is "Object". + * + * See also: ecma_object_get_class_name + */ return obj_p; } /* ecma_op_create_object_object_noarg */ @@ -503,11 +508,7 @@ ecma_op_general_object_default_value (ecma_object_t *obj_p, /**< the object */ if (hint == ECMA_PREFERRED_TYPE_NO) { - ecma_property_t *class_prop_p = ecma_get_internal_property (obj_p, - ECMA_INTERNAL_PROPERTY_CLASS); - ecma_magic_string_id_t obj_class = (ecma_magic_string_id_t) class_prop_p->u.internal_property.value; - - if (obj_class == ECMA_MAGIC_STRING_DATE_UL) + if (ecma_object_get_class_name (obj_p) == ECMA_MAGIC_STRING_DATE_UL) { hint = ECMA_PREFERRED_TYPE_STRING; } diff --git a/jerry-core/ecma/operations/ecma-objects.cpp b/jerry-core/ecma/operations/ecma-objects.cpp index b812876c72..7440aa489d 100644 --- a/jerry-core/ecma/operations/ecma-objects.cpp +++ b/jerry-core/ecma/operations/ecma-objects.cpp @@ -504,8 +504,6 @@ ecma_op_object_has_instance (ecma_object_t *obj_p, /**< the object */ JERRY_UNREACHABLE (); } /* ecma_op_object_has_instance */ - - /** * Object's isPrototypeOf operation * @@ -533,6 +531,204 @@ ecma_op_object_is_prototype_of (ecma_object_t *base_p, /** < base object */ } while (true); } /* ecma_op_object_is_prototype_of */ +/** + * Get [[Class]] string of specified object + * + * @return class name magic string + */ +ecma_magic_string_id_t +ecma_object_get_class_name (ecma_object_t *obj_p) /**< object */ +{ + ecma_object_type_t type = ecma_get_object_type (obj_p); + + switch (type) + { + case ECMA_OBJECT_TYPE_ARRAY: + { + return ECMA_MAGIC_STRING_ARRAY_UL; + } + case ECMA_OBJECT_TYPE_STRING: + { + return ECMA_MAGIC_STRING_STRING_UL; + } + case ECMA_OBJECT_TYPE_ARGUMENTS: + { + return ECMA_MAGIC_STRING_ARGUMENTS_UL; + } + case ECMA_OBJECT_TYPE_EXTENSION: + { + return ECMA_MAGIC_STRING_OBJECT_UL; + } + case ECMA_OBJECT_TYPE_FUNCTION: + { + ecma_magic_string_id_t class_name; + + if (ecma_get_object_is_builtin (obj_p)) + { + ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (obj_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; + + switch (builtin_id) + { + case ECMA_BUILTIN_ID_OBJECT: + { + class_name = ECMA_MAGIC_STRING_OBJECT_UL; + break; + } +#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_ARRAY_BUILTIN + case ECMA_BUILTIN_ID_ARRAY: + { + class_name = ECMA_MAGIC_STRING_ARRAY_UL; + break; + } +#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_ARRAY_BUILTIN */ +#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_STRING_BUILTIN + case ECMA_BUILTIN_ID_STRING: + { + class_name = ECMA_MAGIC_STRING_STRING_UL; + break; + } +#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_STRING_BUILTIN */ +#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_BOOLEAN_BUILTIN + case ECMA_BUILTIN_ID_BOOLEAN: + { + class_name = ECMA_MAGIC_STRING_BOOLEAN_UL; + break; + } +#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_BOOLEAN_BUILTIN */ +#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN + case ECMA_BUILTIN_ID_NUMBER: + { + class_name = ECMA_MAGIC_STRING_NUMBER_UL; + break; + } +#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN */ + case ECMA_BUILTIN_ID_FUNCTION: + { + class_name = ECMA_MAGIC_STRING_FUNCTION_UL; + break; + } +#ifdef CONFIG_ECMA_COMPACT_PROFILE + case ECMA_BUILTIN_ID_COMPACT_PROFILE_ERROR: + { + class_name = ECMA_MAGIC_STRING_COMPACT_PROFILE_ERROR_UL; + break; + } +#endif /* CONFIG_ECMA_COMPACT_PROFILE */ +#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_ERROR_BUILTINS + case ECMA_BUILTIN_ID_ERROR: + case ECMA_BUILTIN_ID_EVAL_ERROR: + case ECMA_BUILTIN_ID_RANGE_ERROR: + case ECMA_BUILTIN_ID_REFERENCE_ERROR: + case ECMA_BUILTIN_ID_SYNTAX_ERROR: + case ECMA_BUILTIN_ID_TYPE_ERROR: + case ECMA_BUILTIN_ID_URI_ERROR: + { + class_name = ECMA_MAGIC_STRING_ERROR_UL; + break; + } +#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_ERROR_BUILTINS */ + default: + { + JERRY_ASSERT (builtin_id == ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); + + class_name = ECMA_MAGIC_STRING_FUNCTION_UL; + break; + } + } + } + else + { + class_name = ECMA_MAGIC_STRING_FUNCTION_UL; + } + + return class_name; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION: + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + return ECMA_MAGIC_STRING_FUNCTION_UL; + } + default: + { + JERRY_ASSERT (type == ECMA_OBJECT_TYPE_GENERAL); + + if (ecma_get_object_is_builtin (obj_p)) + { + ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (obj_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; + + switch (builtin_id) + { + case ECMA_BUILTIN_ID_OBJECT_PROTOTYPE: + { + return ECMA_MAGIC_STRING_OBJECT_UL; + } +#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_STRING_BUILTIN + case ECMA_BUILTIN_ID_STRING_PROTOTYPE: + { + return ECMA_MAGIC_STRING_STRING_UL; + } +#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_STRING_BUILTIN */ +#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_BOOLEAN_BUILTIN + case ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE: + { + return ECMA_MAGIC_STRING_BOOLEAN_UL; + } +#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_BOOLEAN_BUILTIN */ +#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN + case ECMA_BUILTIN_ID_NUMBER_PROTOTYPE: + { + return ECMA_MAGIC_STRING_NUMBER_UL; + } +#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN */ +#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_MATH_BUILTIN + case ECMA_BUILTIN_ID_MATH: + { + return ECMA_MAGIC_STRING_MATH_UL; + } +#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_MATH_BUILTIN */ +#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_ERROR_BUILTINS + case ECMA_BUILTIN_ID_ERROR_PROTOTYPE: + case ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE: + case ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE: + case ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE: + case ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE: + case ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE: + case ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE: + { + return ECMA_MAGIC_STRING_ERROR_UL; + } +#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_ERROR_BUILTINS */ + default: + { + JERRY_ASSERT (ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_GLOBAL) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_JERRY)); + + return ECMA_MAGIC_STRING_OBJECT_UL; + } + } + } + else + { + ecma_property_t *class_name_prop_p = ecma_find_internal_property (obj_p, + ECMA_INTERNAL_PROPERTY_CLASS); + + if (class_name_prop_p == NULL) + { + return ECMA_MAGIC_STRING_OBJECT_UL; + } + else + { + return (ecma_magic_string_id_t) class_name_prop_p->u.internal_property.value; + } + } + } + } +} /* ecma_object_get_class_name */ /** * @} diff --git a/jerry-core/ecma/operations/ecma-objects.h b/jerry-core/ecma/operations/ecma-objects.h index 08d4b90b2a..bd514bd83e 100644 --- a/jerry-core/ecma/operations/ecma-objects.h +++ b/jerry-core/ecma/operations/ecma-objects.h @@ -47,6 +47,8 @@ extern ecma_completion_value_t ecma_op_object_has_instance (ecma_object_t *obj_p ecma_value_t value); extern bool ecma_op_object_is_prototype_of (ecma_object_t *base_p, ecma_object_t *target_p); +extern ecma_magic_string_id_t ecma_object_get_class_name (ecma_object_t *obj_p); + /** * @} * @} diff --git a/jerry-core/ecma/operations/ecma-string-object.cpp b/jerry-core/ecma/operations/ecma-string-object.cpp index 740162246a..a92cfad11f 100644 --- a/jerry-core/ecma/operations/ecma-string-object.cpp +++ b/jerry-core/ecma/operations/ecma-string-object.cpp @@ -88,8 +88,11 @@ ecma_op_create_string_object (const ecma_value_t *arguments_list_p, /**< list of ECMA_OBJECT_TYPE_STRING); ecma_deref_object (prototype_obj_p); - ecma_property_t *class_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS); - class_prop_p->u.internal_property.value = ECMA_MAGIC_STRING_STRING_UL; + /* + * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_STRING type. + * + * See also: ecma_object_get_class_name + */ ecma_property_t *prim_value_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE); diff --git a/tests/jerry/regression-test-issue-112.js b/tests/jerry/regression-test-issue-112.js new file mode 100644 index 0000000000..3eccc0b78a --- /dev/null +++ b/tests/jerry/regression-test-issue-112.js @@ -0,0 +1,16 @@ +// Copyright 2015 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +delete Function.prototype.toString; +assert (Math.cos + 1 === '[object Function]1');