Revision: 15201
Author:   [email protected]
Date:     Wed Jun 19 02:25:24 2013
Log:      Use type feedback for Array (non-constructor) call sites.

BUG=
[email protected]

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

Added:
 /branches/bleeding_edge/test/mjsunit/array-feedback.js
Modified:
 /branches/bleeding_edge/src/arm/stub-cache-arm.cc
 /branches/bleeding_edge/src/bootstrapper.cc
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/stub-cache.cc
 /branches/bleeding_edge/src/stub-cache.h
 /branches/bleeding_edge/src/x64/stub-cache-x64.cc

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/array-feedback.js Wed Jun 19 02:25:24 2013
@@ -0,0 +1,220 @@
+// Copyright 2012 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 --smi-only-arrays --expose-gc
+// Flags: --track-allocation-sites --noalways-opt
+
+// Test element kind of objects.
+// Since --smi-only-arrays affects builtins, its default setting at compile
+// time sticks if built with snapshot.  If --smi-only-arrays is deactivated
+// by default, only a no-snapshot build actually has smi-only arrays enabled
+// in this test case.  Depending on whether smi-only arrays are actually
+// enabled, this test takes the appropriate code path to check smi-only arrays.
+
+// support_smi_only_arrays = %HasFastSmiElements(new Array(1,2,3,4,5,6,7,8));
+support_smi_only_arrays = true;
+optimize_constructed_arrays = true;
+
+if (support_smi_only_arrays) {
+  print("Tests include smi-only arrays.");
+} else {
+  print("Tests do NOT include smi-only arrays.");
+}
+
+if (optimize_constructed_arrays) {
+  print("Tests include constructed array optimizations.");
+} else {
+  print("Tests do NOT include constructed array optimizations.");
+}
+
+var elements_kind = {
+  fast_smi_only            :  'fast smi only elements',
+  fast                     :  'fast elements',
+  fast_double              :  'fast double elements',
+  dictionary               :  'dictionary elements',
+  external_byte            :  'external byte elements',
+  external_unsigned_byte   :  'external unsigned byte elements',
+  external_short           :  'external short elements',
+  external_unsigned_short  :  'external unsigned short elements',
+  external_int             :  'external int elements',
+  external_unsigned_int    :  'external unsigned int elements',
+  external_float           :  'external float elements',
+  external_double          :  'external double elements',
+  external_pixel           :  'external pixel elements'
+}
+
+function getKind(obj) {
+  if (%HasFastSmiElements(obj)) return elements_kind.fast_smi_only;
+  if (%HasFastObjectElements(obj)) return elements_kind.fast;
+  if (%HasFastDoubleElements(obj)) return elements_kind.fast_double;
+  if (%HasDictionaryElements(obj)) return elements_kind.dictionary;
+}
+
+function isHoley(obj) {
+  if (%HasFastHoleyElements(obj)) return true;
+  return false;
+}
+
+function assertKind(expected, obj, name_opt) {
+  if (!support_smi_only_arrays &&
+      expected == elements_kind.fast_smi_only) {
+    expected = elements_kind.fast;
+  }
+  assertEquals(expected, getKind(obj), name_opt);
+}
+
+if (support_smi_only_arrays && optimize_constructed_arrays) {
+
+  // Verify that basic elements kind feedback works for non-constructor
+  // array calls (as long as the call is made through an IC, and not
+  // a CallStub).
+  (function (){
+    function create0() {
+      return Array();
+    }
+
+    // Calls through ICs need warm up through uninitialized, then
+    // premonomorphic first.
+    create0();
+    create0();
+    a = create0();
+    assertKind(elements_kind.fast_smi_only, a);
+    a[0] = 3.5;
+    b = create0();
+    assertKind(elements_kind.fast_double, b);
+
+    function create1(arg) {
+      return Array(arg);
+    }
+
+    create1(0);
+    create1(0);
+    a = create1(0);
+    assertFalse(isHoley(a));
+    assertKind(elements_kind.fast_smi_only, a);
+    a[0] = "hello";
+    b = create1(10);
+    assertTrue(isHoley(b));
+    assertKind(elements_kind.fast, b);
+
+    a = create1(100000);
+    assertKind(elements_kind.dictionary, a);
+
+    function create3(arg1, arg2, arg3) {
+      return Array(arg1, arg2, arg3);
+    }
+
+    create3();
+    create3();
+    a = create3(1,2,3);
+    a[0] = 3.5;
+    b = create3(1,2,3);
+    assertKind(elements_kind.fast_double, b);
+    assertFalse(isHoley(b));
+  })();
+
+
+  // Verify that keyed calls work
+  (function (){
+    function create0(name) {
+      return this[name]();
+    }
+
+    name = "Array";
+    create0(name);
+    create0(name);
+    a = create0(name);
+    a[0] = 3.5;
+    b = create0(name);
+    assertKind(elements_kind.fast_double, b);
+  })();
+
+
+  // Verify that the IC can't be spoofed by patching
+  (function (){
+    function create0() {
+      return Array();
+    }
+
+    create0();
+    create0();
+    a = create0();
+    assertKind(elements_kind.fast_smi_only, a);
+    var oldArray = this.Array;
+    this.Array = function() { return ["hi"]; };
+    b = create0();
+    assertEquals(["hi"], b);
+    this.Array = oldArray;
+  })();
+
+  // Verify that calls are still made through an IC after crankshaft,
+  // though the type information is reset.
+  // TODO(mvstanton): instead, consume the type feedback gathered up
+  // until crankshaft time.
+  (function (){
+    function create0() {
+      return Array();
+    }
+
+    create0();
+    create0();
+    a = create0();
+    a[0] = 3.5;
+    %OptimizeFunctionOnNextCall(create0);
+    create0();
+    create0();
+    b = create0();
+    assertKind(elements_kind.fast_smi_only, b);
+    b[0] = 3.5;
+    c = create0();
+    assertKind(elements_kind.fast_double, c);
+    assertTrue(2 != %GetOptimizationStatus(create0));
+  })();
+
+
+  // Verify that cross context calls work
+  (function (){
+    var realmA = Realm.current();
+    var realmB = Realm.create();
+    assertEquals(0, realmA);
+    assertEquals(1, realmB);
+
+    function instanceof_check(type) {
+      assertTrue(type() instanceof type);
+      assertTrue(type(5) instanceof type);
+      assertTrue(type(1,2,3) instanceof type);
+    }
+
+    var realmBArray = Realm.eval(realmB, "Array");
+    instanceof_check(Array);
+    instanceof_check(Array);
+    instanceof_check(Array);
+    instanceof_check(realmBArray);
+    instanceof_check(realmBArray);
+    instanceof_check(realmBArray);
+  })();
+}
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Mon Jun 17 06:50:56 2013 +++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Wed Jun 19 02:25:24 2013
@@ -1696,6 +1696,54 @@
   // Return the generated code.
   return GetCode(Code::FIELD, name);
 }
+
+
+Handle<Code> CallStubCompiler::CompileArrayCodeCall(
+    Handle<Object> object,
+    Handle<JSObject> holder,
+    Handle<Cell> cell,
+    Handle<JSFunction> function,
+    Handle<String> name,
+    Code::StubType type) {
+  Label miss;
+
+  // Check that function is still array
+  const int argc = arguments().immediate();
+  GenerateNameCheck(name, &miss);
+  Register receiver = r1;
+
+  if (cell.is_null()) {
+    __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
+
+    // Check that the receiver isn't a smi.
+    __ JumpIfSmi(receiver, &miss);
+
+    // Check that the maps haven't changed.
+ CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, r3, r0,
+                    r4, name, &miss);
+  } else {
+    ASSERT(cell->value() == *function);
+ GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
+                                &miss);
+    GenerateLoadFunctionFromCell(cell, function, &miss);
+  }
+
+  Handle<Smi> kind(Smi::FromInt(GetInitialFastElementsKind()), isolate());
+  Handle<Cell> kind_feedback_cell =
+      isolate()->factory()->NewCell(kind);
+  __ mov(r0, Operand(argc));
+  __ mov(r2, Operand(kind_feedback_cell));
+  __ mov(r1, Operand(function));
+
+  ArrayConstructorStub stub(isolate());
+  __ TailCallStub(&stub);
+
+  __ bind(&miss);
+  GenerateMissBranch();
+
+  // Return the generated code.
+  return GetCode(type, name);
+}


 Handle<Code> CallStubCompiler::CompileArrayPushCall(
@@ -1703,7 +1751,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- r2    : name
   //  -- lr    : return address
@@ -1947,7 +1996,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return GetCode(function);
+  return GetCode(type, name);
 }


@@ -1956,7 +2005,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- r2    : name
   //  -- lr    : return address
@@ -2029,7 +2079,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return GetCode(function);
+  return GetCode(type, name);
 }


@@ -2038,7 +2088,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- r2                     : function name
   //  -- lr                     : return address
@@ -2111,7 +2162,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return GetCode(function);
+  return GetCode(type, name);
 }


@@ -2120,7 +2171,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- r2                     : function name
   //  -- lr                     : return address
@@ -2194,7 +2246,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return GetCode(function);
+  return GetCode(type, name);
 }


@@ -2203,7 +2255,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- r2                     : function name
   //  -- lr                     : return address
@@ -2266,7 +2319,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+  return GetCode(type, name);
 }


@@ -2275,7 +2328,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- r2                     : function name
   //  -- lr                     : return address
@@ -2374,7 +2428,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+  return GetCode(type, name);
 }


@@ -2383,7 +2437,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- r2                     : function name
   //  -- lr                     : return address
@@ -2472,7 +2527,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+  return GetCode(type, name);
 }


@@ -2653,7 +2708,8 @@
   if (HasCustomCallGenerator(function)) {
     Handle<Code> code = CompileCustomCall(object, holder,
                                           Handle<Cell>::null(),
- function, Handle<String>::cast(name)); + function, Handle<String>::cast(name),
+                                          Code::CONSTANT_FUNCTION);
     // A null handle means bail out to the regular compiler code below.
     if (!code.is_null()) return code;
   }
@@ -2719,7 +2775,8 @@
   // -----------------------------------
   if (HasCustomCallGenerator(function)) {
     Handle<Code> code = CompileCustomCall(
-        object, holder, cell, function, Handle<String>::cast(name));
+        object, holder, cell, function, Handle<String>::cast(name),
+        Code::NORMAL);
     // A null handle means bail out to the regular compiler code below.
     if (!code.is_null()) return code;
   }
=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Tue Jun 18 00:51:50 2013
+++ /branches/bleeding_edge/src/bootstrapper.cc Wed Jun 19 02:25:24 2013
@@ -859,6 +859,7 @@
                         isolate->initial_object_prototype(),
                         Builtins::kArrayCode, true, true);
     array_function->shared()->DontAdaptArguments();
+    array_function->shared()->set_function_data(Smi::FromInt(kArrayCode));

     // This seems a bit hackish, but we need to make sure Array.length
     // is 1.
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Wed Jun 19 00:48:41 2013
+++ /branches/bleeding_edge/src/hydrogen.cc     Wed Jun 19 02:25:24 2013
@@ -8748,8 +8748,16 @@
           graph()->MarkRecursive();
         }

-        call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(),
+        if (CallStubCompiler::HasCustomCallGenerator(expr->target())) {
+          // When the target has a custom call IC generator, use the IC,
+          // because it is likely to generate better code.
+          HValue* context = environment()->LookupContext();
+          call = PreProcessCall(
+ new(zone()) HCallNamed(context, var->name(), argument_count));
+        } else {
+ call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), argument_count));
+        }
       } else {
         HValue* context = environment()->LookupContext();
         HGlobalObject* receiver = new(zone()) HGlobalObject(context);
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Mon Jun 17 06:50:56 2013 +++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Wed Jun 19 02:25:24 2013
@@ -1694,6 +1694,52 @@
   // Return the generated code.
   return GetCode(Code::FIELD, name);
 }
+
+
+Handle<Code> CallStubCompiler::CompileArrayCodeCall(
+    Handle<Object> object,
+    Handle<JSObject> holder,
+    Handle<Cell> cell,
+    Handle<JSFunction> function,
+    Handle<String> name,
+    Code::StubType type) {
+  Label miss;
+
+  // Check that function is still array
+  const int argc = arguments().immediate();
+  GenerateNameCheck(name, &miss);
+
+  if (cell.is_null()) {
+    // Get the receiver from the stack.
+    __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
+
+    // Check that the receiver isn't a smi.
+    __ JumpIfSmi(edx, &miss);
+ CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
+                    name, &miss);
+  } else {
+    ASSERT(cell->value() == *function);
+ GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
+                                &miss);
+    GenerateLoadFunctionFromCell(cell, function, &miss);
+  }
+
+  Handle<Smi> kind(Smi::FromInt(GetInitialFastElementsKind()), isolate());
+  Handle<Cell> kind_feedback_cell =
+      isolate()->factory()->NewCell(kind);
+  __ mov(eax, Immediate(argc));
+  __ mov(ebx, kind_feedback_cell);
+  __ mov(edi, function);
+
+  ArrayConstructorStub stub(isolate());
+  __ TailCallStub(&stub);
+
+  __ bind(&miss);
+  GenerateMissBranch();
+
+  // Return the generated code.
+  return GetCode(type, name);
+}


 Handle<Code> CallStubCompiler::CompileArrayPushCall(
@@ -1701,7 +1747,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- ecx                 : name
   //  -- esp[0]              : return address
@@ -1950,7 +1997,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return GetCode(function);
+  return GetCode(type, name);
 }


@@ -1959,7 +2006,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- ecx                 : name
   //  -- esp[0]              : return address
@@ -2032,7 +2080,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return GetCode(function);
+  return GetCode(type, name);
 }


@@ -2041,7 +2089,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- ecx                 : function name
   //  -- esp[0]              : return address
@@ -2116,7 +2165,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return GetCode(function);
+  return GetCode(type, name);
 }


@@ -2125,7 +2174,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- ecx                 : function name
   //  -- esp[0]              : return address
@@ -2202,7 +2252,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return GetCode(function);
+  return GetCode(type, name);
 }


@@ -2211,7 +2261,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- ecx                 : function name
   //  -- esp[0]              : return address
@@ -2278,7 +2329,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+  return GetCode(type, name);
 }


@@ -2287,7 +2338,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- ecx                 : name
   //  -- esp[0]              : return address
@@ -2409,7 +2461,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+  return GetCode(type, name);
 }


@@ -2418,7 +2470,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- ecx                 : name
   //  -- esp[0]              : return address
@@ -2515,7 +2568,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+  return GetCode(type, name);
 }


@@ -2706,7 +2759,8 @@
   if (HasCustomCallGenerator(function)) {
     Handle<Code> code = CompileCustomCall(object, holder,
                                           Handle<Cell>::null(),
- function, Handle<String>::cast(name)); + function, Handle<String>::cast(name),
+                                          Code::CONSTANT_FUNCTION);
     // A null handle means bail out to the regular compiler code below.
     if (!code.is_null()) return code;
   }
@@ -2797,7 +2851,8 @@

   if (HasCustomCallGenerator(function)) {
     Handle<Code> code = CompileCustomCall(
-        object, holder, cell, function, Handle<String>::cast(name));
+        object, holder, cell, function, Handle<String>::cast(name),
+        Code::NORMAL);
     // A null handle means bail out to the regular compiler code below.
     if (!code.is_null()) return code;
   }
=======================================
--- /branches/bleeding_edge/src/objects.h       Fri Jun 14 09:06:12 2013
+++ /branches/bleeding_edge/src/objects.h       Wed Jun 19 02:25:24 2013
@@ -5860,8 +5860,8 @@
   V(Math, min, MathMin)                             \
   V(Math, imul, MathImul)

-
 enum BuiltinFunctionId {
+  kArrayCode,
 #define DECLARE_FUNCTION_ID(ignored1, ignore2, name)    \
   k##name,
   FUNCTIONS_WITH_ID_LIST(DECLARE_FUNCTION_ID)
=======================================
--- /branches/bleeding_edge/src/stub-cache.cc   Fri Jun 14 09:06:12 2013
+++ /branches/bleeding_edge/src/stub-cache.cc   Wed Jun 19 02:25:24 2013
@@ -644,7 +644,10 @@
   PROFILE(isolate_,
CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
   GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
-  JSObject::UpdateMapCodeCache(stub_holder, name, code);
+
+  if (CallStubCompiler::CanBeCached(function)) {
+    JSObject::UpdateMapCodeCache(stub_holder, name, code);
+  }
   return code;
 }

@@ -753,7 +756,9 @@
   PROFILE(isolate(),
CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
   GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
-  JSObject::UpdateMapCodeCache(stub_holder, name, code);
+  if (CallStubCompiler::CanBeCached(function)) {
+    JSObject::UpdateMapCodeCache(stub_holder, name, code);
+  }
   return code;
 }

@@ -1972,6 +1977,18 @@
   CallOptimization optimization(function);
   return optimization.is_simple_api_call();
 }
+
+
+bool CallStubCompiler::CanBeCached(Handle<JSFunction> function) {
+  if (function->shared()->HasBuiltinFunctionId()) {
+    BuiltinFunctionId id = function->shared()->builtin_function_id();
+#define CALL_GENERATOR_CASE(name) if (id == k##name) return false;
+    SITE_SPECIFIC_CALL_GENERATORS(CALL_GENERATOR_CASE)
+#undef CALL_GENERATOR_CASE
+  }
+
+  return true;
+}


 Handle<Code> CallStubCompiler::CompileCustomCall(
@@ -1979,7 +1996,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> fname) {
+    Handle<String> fname,
+    Code::StubType type) {
   ASSERT(HasCustomCallGenerator(function));

   if (function->shared()->HasBuiltinFunctionId()) {
@@ -1990,7 +2008,8 @@
                                                    holder,      \
                                                    cell,        \
                                                    function,    \
-                                                   fname);      \
+                                                   fname,       \
+                                                   type);       \
     }
     CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
 #undef CALL_GENERATOR_CASE
=======================================
--- /branches/bleeding_edge/src/stub-cache.h    Fri Jun 14 09:06:12 2013
+++ /branches/bleeding_edge/src/stub-cache.h    Wed Jun 19 02:25:24 2013
@@ -969,7 +969,12 @@
   V(StringCharAt)                               \
   V(StringFromCharCode)                         \
   V(MathFloor)                                  \
-  V(MathAbs)
+  V(MathAbs)                                    \
+  V(ArrayCode)
+
+
+#define SITE_SPECIFIC_CALL_GENERATORS(V)        \
+  V(ArrayCode)


 class CallOptimization;
@@ -1012,6 +1017,7 @@
                                  Handle<Name> name);

   static bool HasCustomCallGenerator(Handle<JSFunction> function);
+  static bool CanBeCached(Handle<JSFunction> function);

  private:
   // Compiles a custom call constant/global IC.  For constant calls cell is
@@ -1021,14 +1027,16 @@
                                  Handle<JSObject> holder,
                                  Handle<Cell> cell,
                                  Handle<JSFunction> function,
-                                 Handle<String> name);
+                                 Handle<String> name,
+                                 Code::StubType type);

 #define DECLARE_CALL_GENERATOR(name)                                    \
   Handle<Code> Compile##name##Call(Handle<Object> object,               \
                                    Handle<JSObject> holder,             \
                                    Handle<Cell> cell,                   \
                                    Handle<JSFunction> function,         \
-                                   Handle<String> fname);
+                                   Handle<String> fname,                \
+                                   Code::StubType type);
   CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
 #undef DECLARE_CALL_GENERATOR

=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Mon Jun 17 06:50:56 2013 +++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Wed Jun 19 02:25:24 2013
@@ -1610,6 +1610,52 @@
   // Return the generated code.
   return GetCode(Code::FIELD, name);
 }
+
+
+Handle<Code> CallStubCompiler::CompileArrayCodeCall(
+    Handle<Object> object,
+    Handle<JSObject> holder,
+    Handle<Cell> cell,
+    Handle<JSFunction> function,
+    Handle<String> name,
+    Code::StubType type) {
+  Label miss;
+
+  // Check that function is still array
+  const int argc = arguments().immediate();
+  GenerateNameCheck(name, &miss);
+
+  if (cell.is_null()) {
+    // Get the receiver from the stack.
+    __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
+
+    // Check that the receiver isn't a smi.
+    __ JumpIfSmi(rdx, &miss);
+ CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
+                    name, &miss);
+  } else {
+    ASSERT(cell->value() == *function);
+ GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
+                                &miss);
+    GenerateLoadFunctionFromCell(cell, function, &miss);
+  }
+
+  Handle<Smi> kind(Smi::FromInt(GetInitialFastElementsKind()), isolate());
+  Handle<Cell> kind_feedback_cell =
+      isolate()->factory()->NewCell(kind);
+  __ movq(rax, Immediate(argc));
+  __ Move(rbx, kind_feedback_cell);
+  __ Move(rdi, function);
+
+  ArrayConstructorStub stub(isolate());
+  __ TailCallStub(&stub);
+
+  __ bind(&miss);
+  GenerateMissBranch();
+
+  // Return the generated code.
+  return GetCode(type, name);
+}


 Handle<Code> CallStubCompiler::CompileArrayPushCall(
@@ -1617,7 +1663,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- rcx                 : name
   //  -- rsp[0]              : return address
@@ -1858,7 +1905,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return GetCode(function);
+  return GetCode(type, name);
 }


@@ -1867,7 +1914,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- rcx                 : name
   //  -- rsp[0]              : return address
@@ -1939,7 +1987,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return GetCode(function);
+  return GetCode(type, name);
 }


@@ -1948,7 +1996,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- rcx                 : function name
   //  -- rsp[0]              : return address
@@ -2019,7 +2068,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return GetCode(function);
+  return GetCode(type, name);
 }


@@ -2028,7 +2077,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- rcx                 : function name
   //  -- rsp[0]              : return address
@@ -2099,7 +2149,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return GetCode(function);
+  return GetCode(type, name);
 }


@@ -2108,7 +2158,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- rcx                 : function name
   //  -- rsp[0]              : return address
@@ -2170,7 +2221,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+  return GetCode(type, name);
 }


@@ -2179,7 +2230,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // TODO(872): implement this.
   return Handle<Code>::null();
 }
@@ -2190,7 +2242,8 @@
     Handle<JSObject> holder,
     Handle<Cell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<String> name,
+    Code::StubType type) {
   // ----------- S t a t e -------------
   //  -- rcx                 : function name
   //  -- rsp[0]              : return address
@@ -2286,7 +2339,7 @@
   GenerateMissBranch();

   // Return the generated code.
-  return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+  return GetCode(type, name);
 }


@@ -2477,7 +2530,8 @@
   if (HasCustomCallGenerator(function)) {
     Handle<Code> code = CompileCustomCall(object, holder,
                                           Handle<PropertyCell>::null(),
- function, Handle<String>::cast(name)); + function, Handle<String>::cast(name),
+                                          Code::CONSTANT_FUNCTION);
     // A null handle means bail out to the regular compiler code below.
     if (!code.is_null()) return code;
   }
@@ -2571,7 +2625,8 @@

   if (HasCustomCallGenerator(function)) {
     Handle<Code> code = CompileCustomCall(
-        object, holder, cell, function, Handle<String>::cast(name));
+        object, holder, cell, function, Handle<String>::cast(name),
+        Code::NORMAL);
     // A null handle means bail out to the regular compiler code below.
     if (!code.is_null()) return 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