From 3a788a24decc30ecd4340a8008b3ea75008f839b Mon Sep 17 00:00:00 2001
From: Zoltan Herczeg <zherczeg.u-szeged@partner.samsung.com>
Date: Tue, 21 Sep 2021 11:58:14 +0000
Subject: [PATCH] Implement built-in flag support for arguments

Duplicate check can be removed from property enumeration.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
---
 jerry-core/ecma/base/ecma-globals.h           |   7 +-
 .../ecma/operations/ecma-arguments-object.c   | 205 +++++++++---------
 .../ecma/operations/ecma-arguments-object.h   |   8 +-
 .../ecma/operations/ecma-objects-general.c    |  17 +-
 jerry-core/ecma/operations/ecma-objects.c     |  63 ++----
 5 files changed, 139 insertions(+), 161 deletions(-)

diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h
index 6a9918f4b0..6166c496c4 100644
--- a/jerry-core/ecma/base/ecma-globals.h
+++ b/jerry-core/ecma/base/ecma-globals.h
@@ -223,7 +223,7 @@ enum
   ECMA_VALUE_SPREAD_ELEMENT = ECMA_MAKE_VALUE (11), /**< a special value for spread elements in array initialization
                                                      *   or function call argument list */
   /* Other values */
-  ECMA_VALUE_INITIALIZED = ECMA_MAKE_VALUE (12), /**< represents initialized mapped arguments formal parameter */
+  ECMA_VALUE_ARGUMENT_NO_TRACK = ECMA_MAKE_VALUE (12), /**< represents not-tracked arguments formal parameter */
 #if JERRY_ESNEXT
   ECMA_VALUE_SYNC_ITERATOR = ECMA_MAKE_VALUE (13), /**< option for ecma_op_get_iterator: sync iterator is requested */
   ECMA_VALUE_ASYNC_ITERATOR = ECMA_MAKE_VALUE (14), /**< option for ecma_op_get_iterator: async iterator is requested */
@@ -2452,9 +2452,8 @@ typedef enum
   ECMA_ARGUMENTS_OBJECT_MAPPED = (1 << 0),               /* mapped arguments object */
   ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE = (1 << 1),      /* static mapped arguments object */
   ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED = (1 << 2),   /* 'callee' property has been lazy initialized */
-  ECMA_ARGUMENTS_OBJECT_CALLER_INITIALIZED = (1 << 3),   /* 'caller' property has been lazy initialized */
-  ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED = (1 << 4),   /* 'length' property has been lazy initialized */
-  ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED = (1 << 5), /* 'Symbol.iterator' property has been lazy initialized */
+  ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED = (1 << 3),   /* 'length' property has been lazy initialized */
+  ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED = (1 << 4), /* 'Symbol.iterator' property has been lazy initialized */
 } ecma_arguments_object_flags_t;
 
 /**
diff --git a/jerry-core/ecma/operations/ecma-arguments-object.c b/jerry-core/ecma/operations/ecma-arguments-object.c
index 9ae1cf2dd0..55698f6f17 100644
--- a/jerry-core/ecma/operations/ecma-arguments-object.c
+++ b/jerry-core/ecma/operations/ecma-arguments-object.c
@@ -88,7 +88,7 @@ ecma_op_create_arguments_object (vm_frame_ctx_shared_args_t *shared_p, /**< shar
 
   for (uint32_t i = shared_p->arg_list_len; i < saved_arg_count; i++)
   {
-    argv_p[i] = ECMA_VALUE_INITIALIZED;
+    argv_p[i] = ECMA_VALUE_UNDEFINED;
   }
 
   arguments_p->header.u.cls.u3.arguments_number = shared_p->arg_list_len;
@@ -137,7 +137,7 @@ ecma_op_create_arguments_object (vm_frame_ctx_shared_args_t *shared_p, /**< shar
 
         ecma_deref_ecma_string (prop_name_p);
 
-        prop_value_p->value = argv_p[i] == ECMA_VALUE_INITIALIZED ? ECMA_VALUE_UNDEFINED : argv_p[i];
+        prop_value_p->value = argv_p[i];
         argv_p[i] = ECMA_VALUE_EMPTY;
       }
     }
@@ -183,76 +183,40 @@ ecma_op_arguments_object_define_own_property (ecma_object_t *object_p, /**< the
 
   ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1);
 
-  if (!ecma_is_value_empty (argv_p[index]))
+  if (ecma_is_value_empty (argv_p[index]) || argv_p[index] == ECMA_VALUE_ARGUMENT_NO_TRACK)
   {
-    if (property_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED))
-    {
-      ecma_free_value_if_not_object (argv_p[index]);
-      argv_p[index] = ECMA_VALUE_EMPTY;
-    }
-    else
-    {
-      if (property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED)
-      {
-        ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index);
-        ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env);
-
-        ecma_value_t completion = ecma_op_set_mutable_binding (lex_env_p,
-                                                               name_p,
-                                                               property_desc_p->value,
-                                                               true);
-
-        JERRY_ASSERT (ecma_is_value_empty (completion));
-      }
-
-      if ((property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED)
-          && !(property_desc_p->flags & JERRY_PROP_IS_WRITABLE))
-      {
-        ecma_free_value_if_not_object (argv_p[index]);
-        argv_p[index] = ECMA_VALUE_EMPTY;
-      }
-    }
+    return ret_value;
   }
 
-  return ret_value;
-} /* ecma_op_arguments_object_define_own_property */
-
-/**
- * [[Delete]] ecma Arguments object's operation
- *
- * See also:
- *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
- *          ECMA-262 v5, 10.6
- *
- * @return ecma value
- *         Returned value must be freed with ecma_free_value
- */
-ecma_value_t
-ecma_op_arguments_object_delete (ecma_object_t *object_p, /**< the object */
-                                 ecma_string_t *property_name_p, /**< property name */
-                                 bool is_throw) /**< flag that controls failure handling */
-{
-  /* 3. */
-  ecma_value_t ret_value = ecma_op_general_object_delete (object_p, property_name_p, is_throw);
-
-  if (!ecma_is_value_true (ret_value)
-      || !(((ecma_extended_object_t *) object_p)->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED))
+  if (property_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED))
   {
+    ecma_free_value_if_not_object (argv_p[index]);
+    argv_p[index] = ECMA_VALUE_ARGUMENT_NO_TRACK;
     return ret_value;
   }
 
-  ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) object_p;
-  ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1);
-  uint32_t index = ecma_string_get_array_index (property_name_p);
+  if (property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED)
+  {
+    ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index);
+    ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env);
+
+    ecma_value_t completion = ecma_op_set_mutable_binding (lex_env_p,
+                                                           name_p,
+                                                           property_desc_p->value,
+                                                           true);
 
-  if (index < mapped_arguments_p->unmapped.header.u.cls.u2.formal_params_number)
+    JERRY_ASSERT (ecma_is_value_empty (completion));
+  }
+
+  if ((property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED)
+      && !(property_desc_p->flags & JERRY_PROP_IS_WRITABLE))
   {
     ecma_free_value_if_not_object (argv_p[index]);
-    argv_p[index] = ECMA_VALUE_EMPTY;
+    argv_p[index] = ECMA_VALUE_ARGUMENT_NO_TRACK;
   }
 
   return ret_value;
-} /* ecma_op_arguments_object_delete */
+} /* ecma_op_arguments_object_define_own_property */
 
 /**
  * Try to lazy instantiate the given property of a mapped/unmapped arguments object
@@ -269,7 +233,7 @@ ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object
   ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) object_p;
   ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1);
   ecma_property_value_t *prop_value_p;
-  ecma_property_t *prop_p = NULL;
+  ecma_property_t *prop_p;
   uint32_t arguments_number = arguments_p->header.u.cls.u3.arguments_number;
   uint8_t flags = arguments_p->header.u.cls.u1.arguments_flags;
 
@@ -283,57 +247,45 @@ ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object
   if (index != ECMA_STRING_NOT_ARRAY_INDEX)
   {
     if (index >= arguments_number
-        || ecma_is_value_empty (argv_p[index])
-        || argv_p[index] == ECMA_VALUE_INITIALIZED)
+        || ecma_is_value_empty (argv_p[index]))
     {
       return NULL;
     }
 
+    JERRY_ASSERT (argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK);
+
     prop_value_p = ecma_create_named_data_property (object_p,
                                                     property_name_p,
-                                                    ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
+                                                    ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_ENUMERABLE_WRITABLE,
                                                     &prop_p);
 
     /* Passing the reference */
     prop_value_p->value = argv_p[index];
 
-    /* Pevent reinitialization */
-    if ((flags & ECMA_ARGUMENTS_OBJECT_MAPPED)
-         && index < arguments_p->header.u.cls.u2.formal_params_number)
-    {
-      argv_p[index] = ECMA_VALUE_INITIALIZED;
-    }
-    else
-    {
-      argv_p[index] = ECMA_VALUE_EMPTY;
-    }
-
+    argv_p[index] = ECMA_VALUE_UNDEFINED;
     return prop_p;
   }
 
-  if (property_name_p == ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH)
+  if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)
       && !(flags & ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED))
   {
-    arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED;
-
     prop_value_p = ecma_create_named_data_property (object_p,
                                                     ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH),
-                                                    ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
+                                                    ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE,
                                                     &prop_p);
 
     prop_value_p->value = ecma_make_uint32_value (arguments_number);
+    return prop_p;
   }
 
-  if (property_name_p == ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE)
+  if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLEE)
       && !(flags & ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED))
   {
-    arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED;
-
     if (flags & ECMA_ARGUMENTS_OBJECT_MAPPED)
     {
       prop_value_p = ecma_create_named_data_property (object_p,
                                                       property_name_p,
-                                                      ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
+                                                      ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE,
                                                       &prop_p);
 
       prop_value_p->value = arguments_p->callee;
@@ -346,44 +298,37 @@ ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object
                                            ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE),
                                            thrower_p,
                                            thrower_p,
-                                           ECMA_PROPERTY_FIXED,
+                                           ECMA_PROPERTY_BUILT_IN_FIXED,
                                            &prop_p);
     }
     return prop_p;
   }
 
 #if !JERRY_ESNEXT
-  if (property_name_p == ecma_get_magic_string (LIT_MAGIC_STRING_CALLER)
-      && !(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_CALLER_INITIALIZED))
+  if (property_name_p == ecma_get_magic_string (LIT_MAGIC_STRING_CALLER))
   {
     if (arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED)
     {
       return NULL;
     }
 
-    arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_CALLER_INITIALIZED;
-
     ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER);
 
     ecma_create_named_accessor_property (object_p,
                                          ecma_get_magic_string (LIT_MAGIC_STRING_CALLER),
                                          thrower_p,
                                          thrower_p,
-                                         ECMA_PROPERTY_FIXED,
+                                         ECMA_PROPERTY_BUILT_IN_FIXED,
                                          &prop_p);
     return prop_p;
   }
 #else /* JERRY_ESNEXT */
-  ecma_string_t *symbol_p = ecma_op_get_global_symbol (LIT_GLOBAL_SYMBOL_ITERATOR);
-
-  if (property_name_p == symbol_p
+  if (ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_ITERATOR)
       && !(flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED))
   {
-    arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED;
-
     prop_value_p = ecma_create_named_data_property (object_p,
-                                                    symbol_p,
-                                                    ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
+                                                    property_name_p,
+                                                    ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE,
                                                     &prop_p);
 
     prop_value_p->value = ecma_op_object_get_by_magic_id (ecma_builtin_get (ECMA_BUILTIN_ID_INTRINSIC_OBJECT),
@@ -391,30 +336,82 @@ ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object
 
     JERRY_ASSERT (ecma_is_value_object (prop_value_p->value));
     ecma_deref_object (ecma_get_object_from_value (prop_value_p->value));
+    return prop_p;
   }
-
-  ecma_deref_ecma_string (symbol_p);
 #endif /* !JERRY_ESNEXT */
 
-  return prop_p;
+  return NULL;
 } /* ecma_op_arguments_object_try_to_lazy_instantiate_property */
 
+/**
+ * Delete configurable properties of arguments object
+ */
+void
+ecma_op_arguments_delete_built_in_property (ecma_object_t *object_p, /**< the object */
+                                            ecma_string_t *property_name_p) /**< property name */
+{
+  ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) object_p;
+
+  if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH))
+  {
+    JERRY_ASSERT (!(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED));
+
+    arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED;
+    return;
+  }
+
+  if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLEE))
+  {
+    JERRY_ASSERT (!(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED));
+    JERRY_ASSERT (arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED);
+
+    arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED;
+    return;
+  }
+
+#if JERRY_ESNEXT
+  if (ecma_prop_name_is_symbol (property_name_p))
+  {
+    JERRY_ASSERT (!(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED));
+    JERRY_ASSERT (ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_ITERATOR));
+
+    arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED;
+    return;
+  }
+#endif /* JERRY_ESNEXT */
+
+  uint32_t index = ecma_string_get_array_index (property_name_p);
+
+  ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1);
+
+  if (arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED)
+  {
+    argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) object_p) + 1);
+  }
+
+  JERRY_ASSERT (argv_p[index] == ECMA_VALUE_UNDEFINED
+                || argv_p[index] == ECMA_VALUE_ARGUMENT_NO_TRACK);
+
+  argv_p[index] = ECMA_VALUE_EMPTY;
+} /* ecma_op_arguments_delete_built_in_property */
+
 /**
  * List names of an arguments object's lazy instantiated properties
  */
 void
 ecma_op_arguments_object_list_lazy_property_names (ecma_object_t *obj_p, /**< arguments object */
                                                    ecma_collection_t *prop_names_p, /**< prop name collection */
-                                                   ecma_property_counter_t *prop_counter_p) /**< prop counter */
+                                                   ecma_property_counter_t *prop_counter_p) /**< property counters */
 {
   JERRY_ASSERT (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARGUMENTS));
 
   ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) obj_p;
 
-  ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1);
   uint32_t arguments_number = arguments_p->header.u.cls.u3.arguments_number;
   uint8_t flags = arguments_p->header.u.cls.u1.arguments_flags;
 
+  ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1);
+
   if (flags & ECMA_ARGUMENTS_OBJECT_MAPPED)
   {
     argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) obj_p) + 1);
@@ -443,19 +440,21 @@ ecma_op_arguments_object_list_lazy_property_names (ecma_object_t *obj_p, /**< ar
   }
 
 #if !JERRY_ESNEXT
-  if (!(flags & (ECMA_ARGUMENTS_OBJECT_CALLER_INITIALIZED | ECMA_ARGUMENTS_OBJECT_MAPPED)))
+  if (!(flags & ECMA_ARGUMENTS_OBJECT_MAPPED))
   {
     ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_CALLER));
     prop_counter_p->string_named_props++;
   }
-#else /* JERRY_ESNEXT */
+#endif /* !JERRY_ESNEXT */
+
+#if JERRY_ESNEXT
   if (!(flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED))
   {
     ecma_string_t *symbol_p = ecma_op_get_global_symbol (LIT_GLOBAL_SYMBOL_ITERATOR);
     ecma_collection_push_back (prop_names_p, ecma_make_symbol_value (symbol_p));
     prop_counter_p->symbol_named_props++;
   }
-#endif /* !JERRY_ESNEXT */
+#endif /* JERRY_ESNEXT */
 } /* ecma_op_arguments_object_list_lazy_property_names */
 
 /**
diff --git a/jerry-core/ecma/operations/ecma-arguments-object.h b/jerry-core/ecma/operations/ecma-arguments-object.h
index 46daed6846..cd1635d065 100644
--- a/jerry-core/ecma/operations/ecma-arguments-object.h
+++ b/jerry-core/ecma/operations/ecma-arguments-object.h
@@ -23,8 +23,6 @@
 ecma_value_t
 ecma_op_create_arguments_object (vm_frame_ctx_shared_args_t *shared_p, ecma_object_t *lex_env_p);
 
-ecma_value_t
-ecma_op_arguments_object_delete (ecma_object_t *object_p, ecma_string_t *property_name_p, bool is_throw);
 ecma_value_t
 ecma_op_arguments_object_define_own_property (ecma_object_t *object_p, ecma_string_t *property_name_p,
                                               const ecma_property_descriptor_t *property_desc_p);
@@ -34,8 +32,10 @@ ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object
                                                            ecma_string_t *property_name_p);
 
 void
-ecma_op_arguments_object_list_lazy_property_names (ecma_object_t *obj_p,
-                                                   ecma_collection_t *prop_names_p,
+ecma_op_arguments_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p);
+
+void
+ecma_op_arguments_object_list_lazy_property_names (ecma_object_t *obj_p, ecma_collection_t *prop_names_p,
                                                    ecma_property_counter_t *prop_counter_p);
 
 ecma_string_t *
diff --git a/jerry-core/ecma/operations/ecma-objects-general.c b/jerry-core/ecma/operations/ecma-objects-general.c
index e9ec143ab2..91df8c36c0 100644
--- a/jerry-core/ecma/operations/ecma-objects-general.c
+++ b/jerry-core/ecma/operations/ecma-objects-general.c
@@ -13,6 +13,7 @@
  * limitations under the License.
  */
 
+#include "ecma-arguments-object.h"
 #include "ecma-array-object.h"
 #include "ecma-builtins.h"
 #include "ecma-exceptions.h"
@@ -151,6 +152,12 @@ ecma_op_general_object_delete (ecma_object_t *obj_p, /**< the object */
         ecma_builtin_delete_built_in_property (obj_p, property_name_p);
         break;
       }
+      case ECMA_OBJECT_TYPE_CLASS:
+      {
+        JERRY_ASSERT (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARGUMENTS));
+        ecma_op_arguments_delete_built_in_property (obj_p, property_name_p);
+        break;
+      }
       case ECMA_OBJECT_TYPE_FUNCTION:
       {
         ecma_op_function_delete_built_in_property (obj_p, property_name_p);
@@ -168,7 +175,15 @@ ecma_op_general_object_delete (ecma_object_t *obj_p, /**< the object */
       }
     }
 #else /* !JERRY_ESNEXT */
-    ecma_builtin_delete_built_in_property (obj_p, property_name_p);
+    if (type == ECMA_OBJECT_TYPE_CLASS)
+    {
+      JERRY_ASSERT (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARGUMENTS));
+      ecma_op_arguments_delete_built_in_property (obj_p, property_name_p);
+    }
+    else
+    {
+      ecma_builtin_delete_built_in_property (obj_p, property_name_p);
+    }
 #endif /* JERRY_ESNEXT */
   }
 
diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c
index 846631d05a..cc6c156c07 100644
--- a/jerry-core/ecma/operations/ecma-objects.c
+++ b/jerry-core/ecma/operations/ecma-objects.c
@@ -390,7 +390,7 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */
 
       ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1);
 
-      if (!ecma_is_value_empty (argv_p[index]))
+      if (!ecma_is_value_empty (argv_p[index]) && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK)
       {
 #if JERRY_LCACHE
         /* Mapped arguments initialized properties MUST not be lcached */
@@ -585,7 +585,7 @@ ecma_op_object_find_own (ecma_value_t base_value, /**< base value */
 
             ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1);
 
-            if (!ecma_is_value_empty (argv_p[index]))
+            if (!ecma_is_value_empty (argv_p[index]) && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK)
             {
               ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index);
               ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env);
@@ -1428,7 +1428,7 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */
 
             ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1);
 
-            if (!ecma_is_value_empty (argv_p[index]))
+            if (!ecma_is_value_empty (argv_p[index]) && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK)
             {
               ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index);
               ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env);
@@ -1812,13 +1812,6 @@ ecma_op_object_delete (ecma_object_t *obj_p, /**< the object */
                 && !ecma_is_lexical_environment (obj_p));
   JERRY_ASSERT (property_name_p != NULL);
 
-  if (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARGUMENTS))
-  {
-    return ecma_op_arguments_object_delete (obj_p,
-                                            property_name_p,
-                                            is_strict);
-  }
-
 #if JERRY_BUILTIN_PROXY
   if (ECMA_OBJECT_IS_PROXY (obj_p))
   {
@@ -2279,27 +2272,6 @@ ecma_op_object_get_enumerable_property_names (ecma_object_t *obj_p, /**< routine
   return properties_p;
 } /* ecma_op_object_get_enumerable_property_names */
 
-/**
- * Helper method to check if a given property is already in the collection or not
- *
- * @return true - if the property is already in the collection
- *         false - otherwise
- */
-static bool
-ecma_object_prop_name_is_duplicated (ecma_collection_t *prop_names_p, /**< prop name collection */
-                                     ecma_string_t *name_p) /**< property name */
-{
-  for (uint64_t i = 0; i < prop_names_p->item_count; i++)
-  {
-    if (ecma_compare_ecma_strings (ecma_get_prop_name_from_value (prop_names_p->buffer_p[i]), name_p))
-    {
-      return true;
-    }
-  }
-
-  return false;
-} /* ecma_object_prop_name_is_duplicated */
-
 /**
  * Helper method for getting lazy instantiated properties for [[OwnPropertyKeys]]
  */
@@ -2574,29 +2546,22 @@ ecma_op_object_own_property_keys (ecma_object_t *obj_p) /**< object */
         ecma_string_t *name_p = ecma_string_from_property_name (*property_p,
                                                                 prop_pair_p->names_cp[i]);
 
-        if (!ecma_object_prop_name_is_duplicated (prop_names_p, name_p))
+        if (ecma_string_get_array_index (name_p) != ECMA_STRING_NOT_ARRAY_INDEX)
         {
-          if (ecma_string_get_array_index (name_p) != ECMA_STRING_NOT_ARRAY_INDEX)
-          {
-            prop_counter.array_index_named_props++;
-          }
-      #if JERRY_ESNEXT
-          else if (ecma_prop_name_is_symbol (name_p))
-          {
-            prop_counter.symbol_named_props++;
-          }
-      #endif /* JERRY_ESNEXT */
-          else
-          {
-            prop_counter.string_named_props++;
-          }
-
-          ecma_collection_push_back (prop_names_p, ecma_make_prop_name_value (name_p));
+          prop_counter.array_index_named_props++;
         }
+#if JERRY_ESNEXT
+        else if (ecma_prop_name_is_symbol (name_p))
+        {
+          prop_counter.symbol_named_props++;
+        }
+#endif /* JERRY_ESNEXT */
         else
         {
-          ecma_deref_ecma_string (name_p);
+          prop_counter.string_named_props++;
         }
+
+        ecma_collection_push_back (prop_names_p, ecma_make_prop_name_value (name_p));
       }
     }