Reviewers: Igor Sheludko,

Message:
PTAL

Description:
Support strict and aliased arguments in Array.prototype.slice

BUG=

Please review this at https://codereview.chromium.org/772533003/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+67, -5 lines):
  M src/builtins.cc
  M src/elements.cc


Index: src/builtins.cc
diff --git a/src/builtins.cc b/src/builtins.cc
index b8d0b42d50e8f757497c12696d5112b1d03043b8..cca9547ef24b00b330aa0f7907506030f4d3e52a 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -574,19 +574,25 @@ BUILTIN(ArraySlice) {
     } else {
       // Array.slice(arguments, ...) is quite a common idiom (notably more
       // than 50% of invocations in Web apps).  Treat it in C++ as well.
-      Map* arguments_map =
+      Map* sloppy_arguments_map =
           isolate->context()->native_context()->sloppy_arguments_map();
+      Map* strict_arguments_map =
+          isolate->context()->native_context()->strict_arguments_map();
+      Map* aliased_arguments_map =
+          isolate->context()->native_context()->aliased_arguments_map();

       bool is_arguments_object_with_fast_elements =
           receiver->IsJSObject() &&
-          JSObject::cast(*receiver)->map() == arguments_map;
+          (JSObject::cast(*receiver)->map() == sloppy_arguments_map ||
+           JSObject::cast(*receiver)->map() == strict_arguments_map ||
+           JSObject::cast(*receiver)->map() == aliased_arguments_map);
       if (!is_arguments_object_with_fast_elements) {
         AllowHeapAllocation allow_allocation;
         return CallJsBuiltin(isolate, "ArraySlice", args);
       }
       JSObject* object = JSObject::cast(*receiver);

-      if (!object->HasFastElements()) {
+ if (!object->HasFastElements() && !object->HasSloppyArgumentsElements()) {
         AllowHeapAllocation allow_allocation;
         return CallJsBuiltin(isolate, "ArraySlice", args);
       }
@@ -597,7 +603,8 @@ BUILTIN(ArraySlice) {
         return CallJsBuiltin(isolate, "ArraySlice", args);
       }
       len = Smi::cast(len_obj)->value();
-      if (len > object->elements()->length()) {
+      if (object->map() == sloppy_arguments_map &&
+          len > object->elements()->length()) {
         AllowHeapAllocation allow_allocation;
         return CallJsBuiltin(isolate, "ArraySlice", args);
       }
@@ -660,6 +667,16 @@ BUILTIN(ArraySlice) {
   Handle<FixedArrayBase> elms(object->elements(), isolate);

   ElementsKind kind = object->GetElementsKind();
+  if (kind == SLOPPY_ARGUMENTS_ELEMENTS) {
+    Handle<FixedArray> arguments(
+        FixedArray::cast(FixedArray::cast(*elms)->get(1)));
+    if (arguments->IsDictionary()) {
+      AllowHeapAllocation allow_allocation;
+      return CallJsBuiltin(isolate, "ArraySlice", args);
+    }
+    kind = FAST_HOLEY_ELEMENTS;
+  }
+
   if (IsHoleyElementsKind(kind)) {
     DisallowHeapAllocation no_gc;
     bool packed = true;
Index: src/elements.cc
diff --git a/src/elements.cc b/src/elements.cc
index 0d4e2cb76fcbb956ba81f45ca6f5e5e0549b6551..20a9ceaf52a303d4b04a45935696c54851e1259c 100644
--- a/src/elements.cc
+++ b/src/elements.cc
@@ -1680,7 +1680,52 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
                                FixedArrayBase* to, ElementsKind from_kind,
                                uint32_t to_start, int packed_size,
                                int copy_size) {
-    UNREACHABLE();
+    DCHECK_LE(0, copy_size);
+    if (copy_size == 0) return;
+    Isolate* isolate = from->GetIsolate();
+    FixedArray* parameter_map = FixedArray::cast(from);
+    FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
+    // Since we may need to call back into JS if arguments is a dictionary,
+    // disallow copying it here.
+    DCHECK(!arguments->IsDictionary());
+    Context* context = Context::cast(parameter_map->get(0));
+    Object* the_hole = isolate->heap()->the_hole_value();
+
+    int max_copy_size = to->length() - to_start;
+    // Limit up to which we copy.
+    int copy_length = Min(max_copy_size, copy_size) + from_start;
+    // Portion of this limit that are mapped.
+    int mapped = Min(copy_length, parameter_map->length() - 2);
+    // Portion of the limit that is unmapped.
+    int actual = Min(copy_length, arguments->length());
+
+    // Copy arguments that may be mapped.
+    int limit = mapped - from_start;
+    int i;
+    for (i = 0; i < limit; i++) {
+      Object* probe = parameter_map->get(from_start + 2 + i);
+      Object* value;
+      if (probe->IsTheHole()) {
+        value = arguments->get(from_start + i);
+      } else {
+        int context_index = Smi::cast(probe)->value();
+        DCHECK(!context->get(context_index)->IsTheHole());
+        value = context->get(context_index);
+      }
+      FixedArray::cast(to)->set(to_start + i, value);
+    }
+
+    // Copy unmapped actual arguments.
+    limit = actual - from_start;
+    for (; i < limit; i++) {
+      Object* value = arguments->get(from_start + i);
+      FixedArray::cast(to)->set(to_start + i, value);
+    }
+
+ // Fill holes for "arguments" beyond the length of the actual arguments.
+    for (i += to_start; i < to->length(); i++) {
+      FixedArray::cast(to)->set(i, the_hole);
+    }
   }

   static uint32_t GetCapacityImpl(Handle<FixedArrayBase> backing_store) {


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to