Reviewers: Toon Verwaest,

Message:
Hi Toon,
Could you look over the CL from Kasperl, with an ARM port by myself? Thanks,
--Michael


Description:
Add a premonomorphic state to the call target cache.

From a CL by kasperl: https://codereview.chromium.org/162903004/

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

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files (+91, -7 lines):
  M src/arm/code-stubs-arm.cc
  M src/ia32/code-stubs-ia32.cc
  M src/objects-inl.h
  M src/objects.h
  M src/runtime.cc
  M src/x64/code-stubs-x64.cc
  M test/cctest/test-heap.cc
  M test/mjsunit/allocation-site-info.js
  M test/mjsunit/array-constructor-feedback.js


Index: src/arm/code-stubs-arm.cc
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 282a6d87562981a3368c8a8c3e7a26e044afc443..b548c23d070532bf3c8c2e75f1dfdcf24e8dad94 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -3017,6 +3017,8 @@ static void GenerateRecordCallTarget(MacroAssembler* masm) {
             masm->isolate()->heap()->undefined_value());
   ASSERT_EQ(*TypeFeedbackInfo::UninitializedSentinel(masm->isolate()),
             masm->isolate()->heap()->the_hole_value());
+  ASSERT_EQ(*TypeFeedbackInfo::PremonomorphicSentinel(masm->isolate()),
+            masm->isolate()->heap()->null_value());

   // Load the cache state into r4.
   __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
@@ -3043,10 +3045,26 @@ static void GenerateRecordCallTarget(MacroAssembler* masm) {

   __ bind(&miss);

-  // A monomorphic miss (i.e, here the cache is not uninitialized) goes
-  // megamorphic.
+  // A monomorphic miss (i.e, here the cache is not uninitialized or
+  // pre-monomorphic) goes megamorphic.
+  Label not_uninitialized;
   __ CompareRoot(r4, Heap::kTheHoleValueRootIndex);
+  __ b(ne, &not_uninitialized);
+
+  // PremonomorphicSentinel is an immortal immovable object (null) so no
+  // write-barrier is needed.
+  __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
+  __ LoadRoot(ip, Heap::kNullValueRootIndex);
+  __ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize));
+  __ jmp(&done);
+
+  // If the cache isn't uninitialized, it is either premonomorphic or
+  // monomorphic. If it is premonomorphic, we initialize it thus making
+  // it monomorphic. Otherwise, we go megamorphic.
+  __ bind(&not_uninitialized);
+  __ CompareRoot(r4, Heap::kNullValueRootIndex);
   __ b(eq, &initialize);
+
   // MegamorphicSentinel is an immortal immovable object (undefined) so no
   // write-barrier is needed.
   __ bind(&megamorphic);
Index: src/ia32/code-stubs-ia32.cc
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index eddd571e6638ca55c503c9b6673edd23696831af..5a5705752cce644e3067507d7c2b15732a6b4552 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -2362,10 +2362,26 @@ static void GenerateRecordCallTarget(MacroAssembler* masm) {

   __ bind(&miss);

-  // A monomorphic miss (i.e, here the cache is not uninitialized) goes
-  // megamorphic.
+  // A monomorphic miss (i.e, here the cache is not uninitialized or
+  // pre-monomorphic) goes megamorphic.
+  Label not_uninitialized;
   __ cmp(ecx, Immediate(TypeFeedbackInfo::UninitializedSentinel(isolate)));
+  __ j(not_equal, &not_uninitialized);
+
+  // PremonomorphicSentinel is an immortal immovable object (null) so no
+  // write-barrier is needed.
+  __ mov(FieldOperand(ebx, edx, times_half_pointer_size,
+                      FixedArray::kHeaderSize),
+         Immediate(TypeFeedbackInfo::PremonomorphicSentinel(isolate)));
+  __ jmp(&done, Label::kFar);
+
+  // If the cache isn't uninitialized, it is either premonomorphic or
+  // monomorphic. If it is premonomorphic, we initialize it thus making
+  // it monomorphic. Otherwise, we go megamorphic.
+  __ bind(&not_uninitialized);
+ __ cmp(ecx, Immediate(TypeFeedbackInfo::PremonomorphicSentinel(isolate)));
   __ j(equal, &initialize);
+
   // MegamorphicSentinel is an immortal immovable object (undefined) so no
   // write-barrier is needed.
   __ bind(&megamorphic);
Index: src/objects-inl.h
diff --git a/src/objects-inl.h b/src/objects-inl.h
index c916fc2be680ea91eddaf8ca80d21fc81747e3f7..cf3ab6b252672087ef79d557e1920bb92c4f5b20 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -6542,6 +6542,11 @@ Handle<Object> TypeFeedbackInfo::UninitializedSentinel(Isolate* isolate) {
 }


+Handle<Object> TypeFeedbackInfo::PremonomorphicSentinel(Isolate* isolate) {
+  return isolate->factory()->null_value();
+}
+
+
 Handle<Object> TypeFeedbackInfo::MegamorphicSentinel(Isolate* isolate) {
   return isolate->factory()->undefined_value();
 }
Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index bb98576eaff4464640b90cd20eeb28ee1d2309d9..9b292318f8b2fb40b750e7b75978d1a629c0da5c 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -8180,6 +8180,9 @@ class TypeFeedbackInfo: public Struct {
   // The object that indicates an uninitialized cache.
   static inline Handle<Object> UninitializedSentinel(Isolate* isolate);

+  // The object that indicates a cache in pre-monomorphic state.
+  static inline Handle<Object> PremonomorphicSentinel(Isolate* isolate);
+
   // The object that indicates a megamorphic state.
   static inline Handle<Object> MegamorphicSentinel(Isolate* isolate);

Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index 3ab39abfcc7676d288c57bba9ff0d81672e6a51c..a7ed3a243b60393aec0b3ae6452e6626ab23a66c 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -14762,6 +14762,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConstructor) {

   Handle<AllocationSite> site;
   if (!type_info.is_null() &&
+      *type_info != isolate->heap()->null_value() &&
       *type_info != isolate->heap()->undefined_value()) {
     site = Handle<AllocationSite>::cast(type_info);
     ASSERT(!site->SitePointsToLiteral());
Index: src/x64/code-stubs-x64.cc
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 0637bd2fb928ac1d0f4bea03afab158eedf85d4e..d9ffc455474ad9bec069096e0011387d1c6db4f2 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -2201,10 +2201,25 @@ static void GenerateRecordCallTarget(MacroAssembler* masm) {

   __ bind(&miss);

-  // A monomorphic miss (i.e, here the cache is not uninitialized) goes
-  // megamorphic.
+  // A monomorphic miss (i.e, here the cache is not uninitialized or
+  // pre-monomorphic) goes megamorphic.
+  Label not_uninitialized;
   __ Cmp(rcx, TypeFeedbackInfo::UninitializedSentinel(isolate));
+  __ j(not_equal, &not_uninitialized);
+
+  // PremonomorphicSentinel is an immortal immovable object (null) so no
+  // write-barrier is needed.
+ __ Move(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize),
+          TypeFeedbackInfo::PremonomorphicSentinel(isolate));
+  __ jmp(&done);
+
+  // If the cache isn't uninitialized, it is either premonomorphic or
+  // monomorphic. If it is premonomorphic, we initialize it thus making
+  // it monomorphic. Otherwise, we go megamorphic.
+  __ bind(&not_uninitialized);
+  __ Cmp(rcx, TypeFeedbackInfo::PremonomorphicSentinel(isolate));
   __ j(equal, &initialize);
+
   // MegamorphicSentinel is an immortal immovable object (undefined) so no
   // write-barrier is needed.
   __ bind(&megamorphic);
Index: test/cctest/test-heap.cc
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index ff9e51a621ab7f4c634d4de79722134265c8eabf..2cc9ecac3990ce440e18b1946f12ee22b855bcb6 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -2848,7 +2848,9 @@ TEST(IncrementalMarkingClearsTypeFeedbackInfo) {
   // originating from two different native contexts.
   CcTest::global()->Set(v8_str("fun1"), fun1);
   CcTest::global()->Set(v8_str("fun2"), fun2);
-  CompileRun("function f(a, b) { a(); b(); } f(fun1, fun2);");
+  CompileRun("function f(a, b) { a(); b(); }"
+             "f(fun1, fun2);"  // Run twice to skip premonomorphic state.
+             "f(fun1, fun2)");

   Handle<JSFunction> f =
       v8::Utils::OpenHandle(
Index: test/mjsunit/allocation-site-info.js
diff --git a/test/mjsunit/allocation-site-info.js b/test/mjsunit/allocation-site-info.js index cd086d35060355e97a37f7f6aba8886d9660baea..51ca68749ccb9be9c10f30dc72cbcf0e8119616b 100644
--- a/test/mjsunit/allocation-site-info.js
+++ b/test/mjsunit/allocation-site-info.js
@@ -128,6 +128,7 @@ if (support_smi_only_arrays) {
   }

   // Case: [1,2,3] as allocation site
+  get_standard_literal();  // Skip premonomorphic state.
   obj = fastliteralcase(get_standard_literal(), 1);
   assertKind(elements_kind.fast_smi_only, obj);
   obj = fastliteralcase(get_standard_literal(), 1.5);
@@ -169,6 +170,7 @@ if (support_smi_only_arrays) {
     return literal;
   }

+  fastliteralcase_smifast(1);  // Skip premonomorphic state.
   obj = fastliteralcase_smifast(1);
   assertKind(elements_kind.fast_smi_only, obj);
   obj = fastliteralcase_smifast("carter");
@@ -183,6 +185,7 @@ if (support_smi_only_arrays) {
     return literal;
   }

+  fastliteralcase_smiholey(5, 1);  // Skip premonomorphic state.
   obj = fastliteralcase_smiholey(5, 1);
   assertKind(elements_kind.fast_smi_only, obj);
   assertHoley(obj);
@@ -197,6 +200,7 @@ if (support_smi_only_arrays) {
   }

   // Case: new Array() as allocation site, smi->double
+  newarraycase_smidouble(1);  // Skip premonomorphic state.
   obj = newarraycase_smidouble(1);
   assertKind(elements_kind.fast_smi_only, obj);
   obj = newarraycase_smidouble(1.5);
@@ -211,6 +215,7 @@ if (support_smi_only_arrays) {
   }

   // Case: new Array() as allocation site, smi->fast
+  newarraycase_smiobj(1);  // Skip premonomorphic state.
   obj = newarraycase_smiobj(1);
   assertKind(elements_kind.fast_smi_only, obj);
   obj = newarraycase_smiobj("gloria");
@@ -225,6 +230,7 @@ if (support_smi_only_arrays) {
   }

   // Case: new Array(length) as allocation site
+  newarraycase_length_smidouble(1);  // Skip premonomorphic state.
   obj = newarraycase_length_smidouble(1);
   assertKind(elements_kind.fast_smi_only, obj);
   obj = newarraycase_length_smidouble(1.5);
@@ -248,6 +254,7 @@ if (support_smi_only_arrays) {
   }

   // Case: new Array(<length>) as allocation site, smi->fast
+  newarraycase_length_smiobj(1);  // Skip premonomorphic state.
   obj = newarraycase_length_smiobj(1);
   assertKind(elements_kind.fast_smi_only, obj);
   obj = newarraycase_length_smiobj("gloria");
@@ -261,6 +268,7 @@ if (support_smi_only_arrays) {
     return a;
   }

+  newarraycase_list_smidouble(1);  // Skip premonomorphic state.
   obj = newarraycase_list_smidouble(1);
   assertKind(elements_kind.fast_smi_only, obj);
   obj = newarraycase_list_smidouble(1.5);
@@ -274,6 +282,7 @@ if (support_smi_only_arrays) {
     return a;
   }

+  newarraycase_list_smiobj(1);  // Skip premonomorphic state.
   obj = newarraycase_list_smiobj(1);
   assertKind(elements_kind.fast_smi_only, obj);
   obj = newarraycase_list_smiobj("coates");
@@ -293,6 +302,7 @@ if (support_smi_only_arrays) {
       return a;
     }

+    foo(0); foo(1);  // Skip premonomorphic state.
     for (i = 0; i < 2; i++) {
       a = foo(i);
       b = foo(i);
@@ -313,6 +323,7 @@ if (support_smi_only_arrays) {
     return a;
   }

+  newarraycase_onearg(5, 3.5);  // Skip premonomorphic state.
   obj = newarraycase_onearg(5, 3.5);
   assertKind(elements_kind.fast_double, obj);
   obj = newarraycase_onearg(10, 5);
@@ -388,6 +399,7 @@ if (support_smi_only_arrays) {
      return literal;
    }

+   get_nested_literal();  // Skip premonomorphic state.
    obj = get_nested_literal();
    assertKind(elements_kind.fast, obj);
    obj[0][0] = 3.5;
@@ -403,6 +415,7 @@ if (support_smi_only_arrays) {
      return literal;
    }

+   get_deep_nested_literal();  // Skip premonomorphic state.
    obj = get_deep_nested_literal();
    assertKind(elements_kind.fast_smi_only, obj[1][0]);
    obj[0][0] = 3.5;
@@ -428,6 +441,7 @@ if (support_smi_only_arrays) {
       return literal;
     }

+    get_object_literal();  // Skip premonomorphic state.
     obj = get_object_literal();
     assertKind(elements_kind.fast_smi_only, obj.array);
     obj.array[1] = 3.5;
@@ -443,6 +457,7 @@ if (support_smi_only_arrays) {
       return literal;
     }

+    get_nested_object_literal();  // Skip premonomorphic state.
     obj = get_nested_object_literal();
     assertKind(elements_kind.fast, obj.array);
     assertKind(elements_kind.fast_smi_only, obj.array[1]);
@@ -462,6 +477,7 @@ if (support_smi_only_arrays) {
       return literal;
     }

+    get_nested_literal();  // Skip premonomorphic state.
     obj = get_nested_literal();
     assertKind(elements_kind.fast, obj);
     obj[0][0] = 3.5;
@@ -477,6 +493,7 @@ if (support_smi_only_arrays) {
       return literal;
     }

+    get_deep_nested_literal();  // Skip premonomorphic state.
     obj = get_deep_nested_literal();
     assertKind(elements_kind.fast_smi_only, obj[1][0]);
     obj[0][0] = 3.5;
Index: test/mjsunit/array-constructor-feedback.js
diff --git a/test/mjsunit/array-constructor-feedback.js b/test/mjsunit/array-constructor-feedback.js index 7cd421bd1b86c16f7f3e096dc7be639f7d262022..2c0d9c15fa6a1965a4ec55c81e2fd0ebd1ea455c 100644
--- a/test/mjsunit/array-constructor-feedback.js
+++ b/test/mjsunit/array-constructor-feedback.js
@@ -89,6 +89,7 @@ if (support_smi_only_arrays) {
       return new t(len);
     }

+    bar(Array, 10);  // Skip premonomorphic state.
     a = bar(Array, 10);
     a[0] = 3.5;
     b = bar(Array, 1);
@@ -108,6 +109,8 @@ if (support_smi_only_arrays) {
     function bar0(t) {
       return new t();
     }
+
+    bar0(Array);  // Skip premonomorphic state.
     a = bar0(Array);
     a[0] = 3.5;
     b = bar0(Array);
@@ -139,6 +142,8 @@ if (support_smi_only_arrays) {
     function bar(len) {
       return new Array(len);
     }
+
+    bar(10);  // Skip premonomorphic state.
     a = bar(10);
     a[0] = "a string";
     a = bar(10);
@@ -190,6 +195,8 @@ if (support_smi_only_arrays) {
     function bar() {
       return new Array();
     }
+
+    bar();  // Skip premonomorphic state.
     a = bar();
     bar();
     %OptimizeFunctionOnNextCall(bar);


--
--
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