Revision: 14630
Author:   [email protected]
Date:     Mon May 13 00:35:26 2013
Log:      Elide hole checks on KeyedLoads of holey double arrays

Improves NavierStokes by about 5%

[email protected]

Review URL: https://codereview.chromium.org/15014020
http://code.google.com/p/v8/source/detail?r=14630

Added:
 /branches/bleeding_edge/test/mjsunit/elide-double-hole-check-1.js
 /branches/bleeding_edge/test/mjsunit/elide-double-hole-check-2.js
 /branches/bleeding_edge/test/mjsunit/elide-double-hole-check-3.js
 /branches/bleeding_edge/test/mjsunit/elide-double-hole-check-4.js
 /branches/bleeding_edge/test/mjsunit/elide-double-hole-check-5.js
 /branches/bleeding_edge/test/mjsunit/elide-double-hole-check-6.js
 /branches/bleeding_edge/test/mjsunit/elide-double-hole-check-7.js
 /branches/bleeding_edge/test/mjsunit/elide-double-hole-check-8.js
 /branches/bleeding_edge/test/mjsunit/elide-double-hole-check-9.js
Modified:
 /branches/bleeding_edge/include/v8.h
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/bootstrapper.cc
 /branches/bleeding_edge/src/code-stubs-hydrogen.cc
 /branches/bleeding_edge/src/contexts.h
 /branches/bleeding_edge/src/heap.cc
 /branches/bleeding_edge/src/hydrogen-instructions.cc
 /branches/bleeding_edge/src/hydrogen-instructions.h
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/hydrogen.h
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/ic.cc
 /branches/bleeding_edge/src/isolate.cc
 /branches/bleeding_edge/src/isolate.h
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/elide-double-hole-check-1.js Mon May 13 00:35:26 2013
@@ -0,0 +1,52 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+function f1(a, i) {
+  return a[i]
+}
+
+var a1 = [,,,,,,,,,,,,,,,,,,0.5];
+assertEquals(undefined, f1(a1, 1));
+assertEquals(undefined, f1(a1, 1));
+%OptimizeFunctionOnNextCall(f1);
+assertEquals(undefined, f1(a1, 1));
+assertEquals(undefined, f1(a1, 1));
+
+function f2(a, i) {
+  return a[i] + 0.5;
+}
+var a2_b = [0.0,,];
+assertEquals(0.5, f2(a2_b, 0));
+assertEquals(0.5, f2(a2_b, 0));
+%OptimizeFunctionOnNextCall(f2);
+assertEquals(0.5, f2(a2_b, 0));
+assertEquals(NaN, f2(a2_b, 1));
+a2_b.__proto__ = [1.5,1.5,1.5];
+assertEquals(2, f2(a2_b, 1));
+assertEquals(0.5, f2(a2_b, 0));
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/elide-double-hole-check-2.js Mon May 13 00:35:26 2013
@@ -0,0 +1,41 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+function f(a, i) {
+  return a[i] + 0.5;
+}
+var arr = [0.0,,];
+assertEquals(0.5, f(arr, 0));
+assertEquals(0.5, f(arr, 0));
+%OptimizeFunctionOnNextCall(f);
+assertEquals(0.5, f(arr, 0));
+assertEquals(NaN, f(arr, 1));
+arr.__proto__ = [1.5,1.5,1.5];
+assertEquals(2, f(arr, 1));
+assertEquals(0.5, f(arr, 0));
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/elide-double-hole-check-3.js Mon May 13 00:35:26 2013
@@ -0,0 +1,39 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+function f(a, i) {
+  return a[i] + 0.5;
+}
+Array.prototype = [1.5,1.5,1.5];
+var arr = [0.0,,];
+assertEquals(0.5, f(arr, 0));
+assertEquals(0.5, f(arr, 0));
+%OptimizeFunctionOnNextCall(f);
+assertEquals(0.5, f(arr, 0));
+assertEquals(NaN, f(arr, 1));
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/elide-double-hole-check-4.js Mon May 13 00:35:26 2013
@@ -0,0 +1,39 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+function f1(a, i) {
+  return a[i] + 0.5;
+}
+var arr = [0.0,,2.5];
+assertEquals(0.5, f1(arr, 0));
+assertEquals(0.5, f1(arr, 0));
+%OptimizeFunctionOnNextCall(f1);
+assertEquals(0.5, f1(arr, 0));
+Array.prototype[1] = 1.5;
+assertEquals(2, f1(arr, 1));
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/elide-double-hole-check-5.js Mon May 13 00:35:26 2013
@@ -0,0 +1,40 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+function f1(a, i) {
+  return a[i] + 0.5;
+}
+var arr = [0.0,,2.5];
+assertEquals(0.5, f1(arr, 0));
+assertEquals(0.5, f1(arr, 0));
+Array.prototype[1] = 1.5;
+%OptimizeFunctionOnNextCall(f1);
+assertEquals(2, f1(arr, 1));
+assertEquals(2, f1(arr, 1));
+assertEquals(0.5, f1(arr, 0));
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/elide-double-hole-check-6.js Mon May 13 00:35:26 2013
@@ -0,0 +1,39 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+function f1(a, i) {
+  return a[i] + 0.5;
+}
+var arr = [0.0,,2.5];
+assertEquals(0.5, f1(arr, 0));
+assertEquals(0.5, f1(arr, 0));
+%OptimizeFunctionOnNextCall(f1);
+assertEquals(0.5, f1(arr, 0));
+Array.prototype.__proto__[1] = 1.5;
+assertEquals(2, f1(arr, 1));
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/elide-double-hole-check-7.js Mon May 13 00:35:26 2013
@@ -0,0 +1,40 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+function f1(a, i) {
+  return a[i] + 0.5;
+}
+var arr = [0.0,,2.5];
+assertEquals(0.5, f1(arr, 0));
+assertEquals(0.5, f1(arr, 0));
+Array.prototype.__proto__[1] = 1.5;
+assertEquals(2, f1(arr, 1));
+%OptimizeFunctionOnNextCall(f1);
+assertEquals(2, f1(arr, 1));
+assertEquals(0.5, f1(arr, 0));
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/elide-double-hole-check-8.js Mon May 13 00:35:26 2013
@@ -0,0 +1,40 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+function f1(a, i) {
+  return a[i] + 0.5;
+}
+var arr = [0.0,,2.5];
+assertEquals(0.5, f1(arr, 0));
+assertEquals(0.5, f1(arr, 0));
+%OptimizeFunctionOnNextCall(f1);
+assertEquals(0.5, f1(arr, 0));
+Array.prototype.__proto__ = new Object();
+Array.prototype.__proto__[1] = 1.5;
+assertEquals(2, f1(arr, 1));
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/elide-double-hole-check-9.js Mon May 13 00:35:26 2013
@@ -0,0 +1,49 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+var do_set = false;
+
+function set_proto_elements() {
+  try {} catch (e) {}  // Don't optimize or inline
+  if (do_set) Array.prototype[1] = 1.5;
+}
+
+function f(a, i) {
+  set_proto_elements();
+  return a[i] + 0.5;
+}
+
+var arr = [0.0,,2.5];
+assertEquals(0.5, f(arr, 0));
+assertEquals(0.5, f(arr, 0));
+%OptimizeFunctionOnNextCall(f);
+assertEquals(0.5, f(arr, 0));
+do_set = true;
+assertEquals(2, f(arr, 1));
+
=======================================
--- /branches/bleeding_edge/include/v8.h        Fri May 10 07:04:51 2013
+++ /branches/bleeding_edge/include/v8.h        Mon May 13 00:35:26 2013
@@ -5035,7 +5035,7 @@
   static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
   static const int kFixedArrayHeaderSize = 2 * kApiPointerSize;
   static const int kContextHeaderSize = 2 * kApiPointerSize;
-  static const int kContextEmbedderDataIndex = 63;
+  static const int kContextEmbedderDataIndex = 64;
   static const int kFullStringRepresentationMask = 0x07;
   static const int kStringEncodingMask = 0x4;
   static const int kExternalTwoByteRepresentationTag = 0x02;
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Fri May 10 10:17:50 2013 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Mon May 13 00:35:26 2013
@@ -95,6 +95,12 @@
     transition_maps_.at(i)->AddDependentCode(
         DependentCode::kTransitionGroup, code);
   }
+  if (graph()->depends_on_empty_array_proto_elements()) {
+    isolate()->initial_object_prototype()->map()->AddDependentCode(
+        DependentCode::kElementsCantBeAddedGroup, code);
+    isolate()->initial_array_prototype()->map()->AddDependentCode(
+        DependentCode::kElementsCantBeAddedGroup, code);
+  }
 }


=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Fri May 10 05:59:20 2013
+++ /branches/bleeding_edge/src/bootstrapper.cc Mon May 13 00:35:26 2013
@@ -475,6 +475,10 @@
         TENURED);

     native_context()->set_initial_object_prototype(*prototype);
+ // For bootstrapping set the array prototype to be the same as the object
+    // prototype, otherwise the missing initial_array_prototype will cause
+    // assertions during startup.
+    native_context()->set_initial_array_prototype(*prototype);
     SetPrototype(object_fun, prototype);
   }

@@ -2365,6 +2369,10 @@
   }

   SetObjectPrototype(global_proxy, inner_global);
+
+  native_context()->set_initial_array_prototype(
+      JSArray::cast(native_context()->array_function()->prototype()));
+
   return true;
 }

=======================================
--- /branches/bleeding_edge/src/code-stubs-hydrogen.cc Tue May 7 14:01:53 2013 +++ /branches/bleeding_edge/src/code-stubs-hydrogen.cc Mon May 13 00:35:26 2013
@@ -418,7 +418,7 @@
   HInstruction* load = BuildUncheckedMonomorphicElementAccess(
       GetParameter(0), GetParameter(1), NULL, NULL,
       casted_stub()->is_js_array(), casted_stub()->elements_kind(),
-      false, STANDARD_STORE, Representation::Tagged());
+      false, NEVER_RETURN_HOLE, STANDARD_STORE, Representation::Tagged());
   return load;
 }

@@ -463,7 +463,8 @@
   BuildUncheckedMonomorphicElementAccess(
       GetParameter(0), GetParameter(1), GetParameter(2), NULL,
       casted_stub()->is_js_array(), casted_stub()->elements_kind(),
-      true, casted_stub()->store_mode(), Representation::Tagged());
+      true, NEVER_RETURN_HOLE, casted_stub()->store_mode(),
+      Representation::Tagged());

   return GetParameter(2);
 }
=======================================
--- /branches/bleeding_edge/src/contexts.h      Fri May 10 05:59:20 2013
+++ /branches/bleeding_edge/src/contexts.h      Mon May 13 00:35:26 2013
@@ -112,6 +112,7 @@
   V(JSON_OBJECT_INDEX, JSObject, json_object) \
   V(REGEXP_FUNCTION_INDEX, JSFunction, regexp_function) \
   V(INITIAL_OBJECT_PROTOTYPE_INDEX, JSObject, initial_object_prototype) \
+  V(INITIAL_ARRAY_PROTOTYPE_INDEX, JSObject, initial_array_prototype) \
   V(CREATE_DATE_FUN_INDEX, JSFunction,  create_date_fun) \
   V(TO_NUMBER_FUN_INDEX, JSFunction, to_number_fun) \
   V(TO_STRING_FUN_INDEX, JSFunction, to_string_fun) \
@@ -258,6 +259,7 @@
     FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
     STRICT_MODE_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
     INITIAL_OBJECT_PROTOTYPE_INDEX,
+    INITIAL_ARRAY_PROTOTYPE_INDEX,
     BOOLEAN_FUNCTION_INDEX,
     NUMBER_FUNCTION_INDEX,
     STRING_FUNCTION_INDEX,
@@ -429,6 +431,10 @@
     ASSERT(IsNativeContext());                            \
     set(index, value);                                    \
   }                                                       \
+  bool is_##name(type* value) {                           \
+    ASSERT(IsNativeContext());                            \
+    return type::cast(get(index)) == value;               \
+  }                                                       \
   type* name() {                                          \
     ASSERT(IsNativeContext());                            \
     return type::cast(get(index));                        \
=======================================
--- /branches/bleeding_edge/src/heap.cc Tue May  7 14:01:53 2013
+++ /branches/bleeding_edge/src/heap.cc Mon May 13 00:35:26 2013
@@ -5177,15 +5177,8 @@
   Context* native_context = isolate()->context()->native_context();
   JSFunction* array_function = native_context->array_function();
   Map* map = array_function->initial_map();
-  Object* maybe_map_array = native_context->js_array_maps();
-  if (!maybe_map_array->IsUndefined()) {
-    Object* maybe_transitioned_map =
-        FixedArray::cast(maybe_map_array)->get(elements_kind);
-    if (!maybe_transitioned_map->IsUndefined()) {
-      map = Map::cast(maybe_transitioned_map);
-    }
-  }
-
+  Map* transition_map = isolate()->get_initial_js_array_map(elements_kind);
+  if (transition_map != NULL) map = transition_map;
   return AllocateJSObjectFromMap(map, pretenure);
 }

=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.cc Mon May 13 00:32:38 2013 +++ /branches/bleeding_edge/src/hydrogen-instructions.cc Mon May 13 00:35:26 2013
@@ -2682,7 +2682,12 @@
     return false;
   }

-  if (hole_mode() == ALLOW_RETURN_HOLE) return true;
+  if (hole_mode() == ALLOW_RETURN_HOLE) {
+    if (IsFastDoubleElementsKind(elements_kind())) {
+      return AllUsesCanTreatHoleAsNaN();
+    }
+    return true;
+  }

   if (IsFastDoubleElementsKind(elements_kind())) {
     return false;
@@ -2694,6 +2699,22 @@
       return false;
     }
   }
+
+  return true;
+}
+
+
+bool HLoadKeyed::AllUsesCanTreatHoleAsNaN() const {
+  if (!IsFastDoubleElementsKind(elements_kind())) {
+    return false;
+  }
+
+  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
+    HValue* use = it.value();
+    if (use->CheckFlag(HValue::kDeoptimizeOnUndefined)) {
+      return false;
+    }
+  }

   return true;
 }
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Fri May 10 10:17:50 2013 +++ /branches/bleeding_edge/src/hydrogen-instructions.h Mon May 13 00:35:26 2013
@@ -5492,6 +5492,7 @@
   virtual void PrintDataTo(StringStream* stream);

   bool UsesMustHandleHole() const;
+  bool AllUsesCanTreatHoleAsNaN() const;
   bool RequiresHoleCheck() const;

   virtual Range* InferRange(Zone* zone);
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Fri May 10 06:21:24 2013
+++ /branches/bleeding_edge/src/hydrogen.cc     Mon May 13 00:35:26 2013
@@ -1123,6 +1123,7 @@
     HValue* load_dependency,
     ElementsKind elements_kind,
     bool is_store,
+    LoadKeyedHoleMode load_mode,
     KeyedAccessStoreMode store_mode) {
   Zone* zone = this->zone();
   if (is_store) {
@@ -1149,7 +1150,8 @@
   return new(zone) HLoadKeyed(elements,
                               checked_key,
                               load_dependency,
-                              elements_kind);
+                              elements_kind,
+                              load_mode);
 }


@@ -1256,6 +1258,7 @@
     bool is_js_array,
     ElementsKind elements_kind,
     bool is_store,
+    LoadKeyedHoleMode load_mode,
     KeyedAccessStoreMode store_mode,
     Representation checked_index_representation) {
   ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array);
@@ -1361,7 +1364,7 @@
   }
   return AddInstruction(
       BuildFastElementAccess(elements, checked_key, val, mapcheck,
-                             elements_kind, is_store, store_mode));
+ elements_kind, is_store, load_mode, store_mode));
 }


@@ -2100,6 +2103,7 @@
       is_recursive_(false),
       use_optimistic_licm_(false),
       has_soft_deoptimize_(false),
+      depends_on_empty_array_proto_elements_(false),
       type_change_checksum_(0) {
   if (info->IsStub()) {
     HydrogenCodeStub* stub = info->code_stub();
@@ -7985,10 +7989,23 @@
   if (dependency) {
     mapcheck->ClearGVNFlag(kDependsOnElementsKind);
   }
+
+ // Loads from a "stock" fast holey double arrays can elide the hole check.
+  LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
+ if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) &&
+      isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
+ Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); + Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
+    AddInstruction(
+ new(zone()) HCheckPrototypeMaps(prototype, object_prototype, zone()));
+    load_mode = ALLOW_RETURN_HOLE;
+    graph()->MarkDependsOnEmptyArrayProtoElements();
+  }
+
   return BuildUncheckedMonomorphicElementAccess(
       object, key, val,
       mapcheck, map->instance_type() == JS_ARRAY_TYPE,
-      map->elements_kind(), is_store, store_mode);
+      map->elements_kind(), is_store, load_mode, store_mode);
 }


@@ -8043,7 +8060,7 @@
       object, key, val, check_maps,
       most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
       most_general_consolidated_map->elements_kind(),
-      false, STANDARD_STORE);
+      false, NEVER_RETURN_HOLE, STANDARD_STORE);
   return instr;
 }

@@ -8216,7 +8233,7 @@
         checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
         access = AddInstruction(BuildFastElementAccess(
             elements, checked_key, val, elements_kind_branch,
-            elements_kind, is_store, STANDARD_STORE));
+            elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE));
         if (!is_store) {
           Push(access);
         }
@@ -8234,7 +8251,7 @@
         checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
         access = AddInstruction(BuildFastElementAccess(
             elements, checked_key, val, elements_kind_branch,
-            elements_kind, is_store, STANDARD_STORE));
+            elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE));
       } else if (elements_kind == DICTIONARY_ELEMENTS) {
         if (is_store) {
access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
=======================================
--- /branches/bleeding_edge/src/hydrogen.h      Fri May 10 06:21:24 2013
+++ /branches/bleeding_edge/src/hydrogen.h      Mon May 13 00:35:26 2013
@@ -388,6 +388,14 @@
   bool is_recursive() const {
     return is_recursive_;
   }
+
+  void MarkDependsOnEmptyArrayProtoElements() {
+    depends_on_empty_array_proto_elements_ = true;
+  }
+
+  bool depends_on_empty_array_proto_elements() {
+    return depends_on_empty_array_proto_elements_;
+  }

   void RecordUint32Instruction(HInstruction* instr) {
     if (uint32_instructions_ == NULL) {
@@ -449,6 +457,7 @@
   bool is_recursive_;
   bool use_optimistic_licm_;
   bool has_soft_deoptimize_;
+  bool depends_on_empty_array_proto_elements_;
   int type_change_checksum_;

   DISALLOW_COPY_AND_ASSIGN(HGraph);
@@ -1002,6 +1011,7 @@
       HValue* dependency,
       ElementsKind elements_kind,
       bool is_store,
+      LoadKeyedHoleMode load_mode,
       KeyedAccessStoreMode store_mode);

   HValue* BuildCheckForCapacityGrow(HValue* object,
@@ -1024,6 +1034,7 @@
       bool is_js_array,
       ElementsKind elements_kind,
       bool is_store,
+      LoadKeyedHoleMode load_mode,
       KeyedAccessStoreMode store_mode,
Representation checked_index_representation = Representation::None());

=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Fri May 10 10:17:50 2013 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Mon May 13 00:35:26 2013
@@ -117,6 +117,12 @@
     transition_maps_.at(i)->AddDependentCode(
         DependentCode::kTransitionGroup, code);
   }
+  if (graph()->depends_on_empty_array_proto_elements()) {
+    isolate()->initial_object_prototype()->map()->AddDependentCode(
+        DependentCode::kElementsCantBeAddedGroup, code);
+    isolate()->initial_array_prototype()->map()->AddDependentCode(
+        DependentCode::kElementsCantBeAddedGroup, code);
+  }
 }


=======================================
--- /branches/bleeding_edge/src/ic.cc   Wed May  8 08:02:08 2013
+++ /branches/bleeding_edge/src/ic.cc   Mon May 13 00:35:26 2013
@@ -2020,7 +2020,14 @@

   bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() &&
       !(FLAG_harmony_observation && object->IsJSObject() &&
-          JSObject::cast(*object)->map()->is_observed());
+        JSObject::cast(*object)->map()->is_observed());
+  if (use_ic && !object->IsSmi()) {
+    // Don't use ICs for maps of the objects in Array's prototype chain. We
+ // expect to be able to trap element sets to objects with those maps in the
+    // runtime to enable optimization of element hole access.
+    Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
+    if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false;
+  }
   ASSERT(!(use_ic && object->IsJSGlobalProxy()));

   if (use_ic) {
=======================================
--- /branches/bleeding_edge/src/isolate.cc      Thu Apr 25 09:00:32 2013
+++ /branches/bleeding_edge/src/isolate.cc      Mon May 13 00:35:26 2013
@@ -2441,6 +2441,44 @@
   if (htracer() == NULL) set_htracer(new HTracer(id()));
   return htracer();
 }
+
+
+Map* Isolate::get_initial_js_array_map(ElementsKind kind) {
+  Context* native_context = context()->native_context();
+  Object* maybe_map_array = native_context->js_array_maps();
+  if (!maybe_map_array->IsUndefined()) {
+    Object* maybe_transitioned_map =
+        FixedArray::cast(maybe_map_array)->get(kind);
+    if (!maybe_transitioned_map->IsUndefined()) {
+      return Map::cast(maybe_transitioned_map);
+    }
+  }
+  return NULL;
+}
+
+
+bool Isolate::IsFastArrayConstructorPrototypeChainIntact() {
+  Map* root_array_map =
+      get_initial_js_array_map(GetInitialFastElementsKind());
+  ASSERT(root_array_map != NULL);
+ JSObject* initial_array_proto = JSObject::cast(*initial_array_prototype());
+
+  // Check that the array prototype hasn't been altered WRT empty elements.
+  if (root_array_map->prototype() != initial_array_proto) return false;
+  if (initial_array_proto->elements() != heap()->empty_fixed_array()) {
+    return false;
+  }
+
+ // Check that the object prototype hasn't been altered WRT empty elements. + JSObject* initial_object_proto = JSObject::cast(*initial_object_prototype());
+  Object* root_array_map_proto = initial_array_proto->GetPrototype();
+  if (root_array_map_proto != initial_object_proto) return false;
+  if (initial_object_proto->elements() != heap()->empty_fixed_array()) {
+    return false;
+  }
+
+  return initial_object_proto->GetPrototype()->IsNull();
+}


 CodeStubInterfaceDescriptor*
=======================================
--- /branches/bleeding_edge/src/isolate.h       Wed Apr 24 07:44:08 2013
+++ /branches/bleeding_edge/src/isolate.h       Mon May 13 00:35:26 2013
@@ -835,6 +835,9 @@
 #define NATIVE_CONTEXT_FIELD_ACCESSOR(index, type, name)            \
   Handle<type> name() {                                             \
     return Handle<type>(context()->native_context()->name(), this); \
+  }                                                                 \
+  bool is_##name(type* value) {                                     \
+    return context()->native_context()->is_##name(value);           \
   }
   NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELD_ACCESSOR)
 #undef NATIVE_CONTEXT_FIELD_ACCESSOR
@@ -1066,6 +1069,10 @@
     }
     date_cache_ = date_cache;
   }
+
+  Map* get_initial_js_array_map(ElementsKind kind);
+
+  bool IsFastArrayConstructorPrototypeChainIntact();

   CodeStubInterfaceDescriptor*
       code_stub_interface_descriptor(int index);
=======================================
--- /branches/bleeding_edge/src/objects.cc      Fri May 10 10:43:04 2013
+++ /branches/bleeding_edge/src/objects.cc      Mon May 13 00:35:26 2013
@@ -3018,6 +3018,20 @@
   if (to_map->elements_kind() == to_kind) return to_map;
   return NULL;
 }
+
+
+bool Map::IsMapInArrayPrototypeChain() {
+  Isolate* isolate = GetIsolate();
+  if (isolate->initial_array_prototype()->map() == this) {
+    return true;
+  }
+
+  if (isolate->initial_object_prototype()->map() == this) {
+    return true;
+  }
+
+  return false;
+}


 static MaybeObject* AddMissingElementsTransitions(Map* map,
@@ -11164,6 +11178,18 @@
                                       bool check_prototype) {
   ASSERT(HasFastSmiOrObjectElements() ||
          HasFastArgumentsElements());
+
+ // Array optimizations rely on the prototype lookups of Array objects always + // returning undefined. If there is a store to the initial prototype object,
+  // make sure all of these optimizations are invalidated.
+  Isolate* isolate(GetIsolate());
+  if (isolate->is_initial_object_prototype(this) ||
+      isolate->is_initial_array_prototype(this)) {
+    HandleScope scope(GetIsolate());
+    map()->dependent_code()->DeoptimizeDependentCodeGroup(
+        GetIsolate(),
+        DependentCode::kElementsCantBeAddedGroup);
+  }

   FixedArray* backing_store = FixedArray::cast(elements());
if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) {
=======================================
--- /branches/bleeding_edge/src/objects.h       Fri May 10 10:17:50 2013
+++ /branches/bleeding_edge/src/objects.h       Mon May 13 00:35:26 2013
@@ -4977,7 +4977,10 @@
     // described by this map changes shape (and transitions to a new map),
     // possibly invalidating the assumptions embedded in the code.
     kPrototypeCheckGroup,
-    kGroupCount = kPrototypeCheckGroup + 1
+ // Group of code that depends on elements not being added to objects with
+    // this map.
+    kElementsCantBeAddedGroup,
+    kGroupCount = kElementsCantBeAddedGroup + 1
   };

   // Array for holding the index of the first code object of each group.
@@ -5509,6 +5512,8 @@
   inline void AddDependentCode(DependentCode::DependencyGroup group,
                                Handle<Code> code);

+  bool IsMapInArrayPrototypeChain();
+
   // Dispatched behavior.
   DECLARE_PRINTER(Map)
   DECLARE_VERIFIER(Map)
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Fri May 10 10:17:50 2013 +++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Mon May 13 00:35:26 2013
@@ -100,6 +100,12 @@
     transition_maps_.at(i)->AddDependentCode(
         DependentCode::kTransitionGroup, code);
   }
+  if (graph()->depends_on_empty_array_proto_elements()) {
+    isolate()->initial_object_prototype()->map()->AddDependentCode(
+        DependentCode::kElementsCantBeAddedGroup, code);
+    isolate()->initial_array_prototype()->map()->AddDependentCode(
+        DependentCode::kElementsCantBeAddedGroup, code);
+  }
 }


--
--
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/groups/opt_out.


Reply via email to