Revision: 22914
Author:   [email protected]
Date:     Wed Aug  6 09:48:04 2014 UTC
Log:      Version 3.27.34.12 (merged r22693)

CallIC customization stubs must accept that a vector slot is cleared.
(also x87 and mips ports)

[email protected]
BUG=392114

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

Added:
 /branches/3.27/test/mjsunit/regress/regress-392114.js
Modified:
 /branches/3.27/src/arm/code-stubs-arm.cc
 /branches/3.27/src/arm64/code-stubs-arm64.cc
 /branches/3.27/src/ia32/code-stubs-ia32.cc
 /branches/3.27/src/ic.cc
 /branches/3.27/src/mips/code-stubs-mips.cc
 /branches/3.27/src/version.cc
 /branches/3.27/src/x64/code-stubs-x64.cc
 /branches/3.27/src/x87/code-stubs-x87.cc

=======================================
--- /dev/null
+++ /branches/3.27/test/mjsunit/regress/regress-392114.js Wed Aug 6 09:48:04 2014 UTC
@@ -0,0 +1,66 @@
+// Copyright 2014 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: --expose-debug-as debug --allow-natives-syntax
+
+Debug = debug.Debug;
+
+function dummy(x) {
+  return x + 100;
+}
+
+function create_closure() {
+  var f = function(arg) {
+    if (arg) { %DeoptimizeFunction(f); }
+    var a = Array(10);
+    for (var i = 0; i < a.length; i++) {
+      a[i] = i;
+    }
+  }
+  return f;
+}
+
+var c = create_closure();
+c();
+
+// c CallIC state now has custom Array handler installed.
+
+// Turn on the debugger.
+Debug.setListener(function () {});
+
+var d = create_closure();
+%OptimizeFunctionOnNextCall(d);
+// Thanks to the debugger, we recreate the full code too. We deopt and run
+// it, stomping on the unexpected AllocationSite in the type vector slot.
+d(true);
+
+// CallIC in c misinterprets type vector slot contents as an AllocationSite,
+// corrupting the heap.
+c();
+
+// CallIC MISS - crash due to corruption.
+dummy();
=======================================
--- /branches/3.27/src/arm/code-stubs-arm.cc    Wed Jun 18 14:15:57 2014 UTC
+++ /branches/3.27/src/arm/code-stubs-arm.cc    Wed Aug  6 09:48:04 2014 UTC
@@ -3081,9 +3081,14 @@

   __ mov(r0, Operand(arg_count()));
   __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
-  __ ldr(r2, FieldMemOperand(r4, FixedArray::kHeaderSize));
-  // Verify that r2 contains an AllocationSite
-  __ AssertUndefinedOrAllocationSite(r2, r4);
+  __ ldr(r4, FieldMemOperand(r4, FixedArray::kHeaderSize));
+
+  // Verify that r4 contains an AllocationSite
+  __ ldr(r5, FieldMemOperand(r4, HeapObject::kMapOffset));
+  __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex);
+  __ b(ne, &miss);
+
+  __ mov(r2, r4);
   ArrayConstructorStub stub(masm->isolate(), arg_count());
   __ TailCallStub(&stub);

@@ -3150,7 +3155,11 @@
   __ b(eq, &miss);

   if (!FLAG_trace_ic) {
-    // We are going megamorphic, and we don't want to visit the runtime.
+ // We are going megamorphic. If the feedback is a JSFunction, it is fine
+    // to handle it here. More complex cases are dealt with in the runtime.
+    __ AssertNotSmi(r4);
+    __ CompareObjectType(r4, r5, r5, JS_FUNCTION_TYPE);
+    __ b(ne, &miss);
     __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
     __ LoadRoot(ip, Heap::kMegamorphicSymbolRootIndex);
     __ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize));
=======================================
--- /branches/3.27/src/arm64/code-stubs-arm64.cc Wed Jun 18 14:15:57 2014 UTC +++ /branches/3.27/src/arm64/code-stubs-arm64.cc Wed Aug 6 09:48:04 2014 UTC
@@ -3374,15 +3374,19 @@
   __ Cmp(function, scratch);
   __ B(ne, &miss);

-  Register allocation_site = feedback_vector;
   __ Mov(x0, Operand(arg_count()));

   __ Add(scratch, feedback_vector,
          Operand::UntagSmiAndScale(index, kPointerSizeLog2));
- __ Ldr(allocation_site, FieldMemOperand(scratch, FixedArray::kHeaderSize));
+  __ Ldr(scratch, FieldMemOperand(scratch, FixedArray::kHeaderSize));

-  // Verify that x2 contains an AllocationSite
-  __ AssertUndefinedOrAllocationSite(allocation_site, scratch);
+  // Verify that scratch contains an AllocationSite
+  Register map = x5;
+  __ Ldr(map, FieldMemOperand(scratch, HeapObject::kMapOffset));
+  __ JumpIfNotRoot(map, Heap::kAllocationSiteMapRootIndex, &miss);
+
+  Register allocation_site = feedback_vector;
+  __ Mov(allocation_site, scratch);
   ArrayConstructorStub stub(masm->isolate(), arg_count());
   __ TailCallStub(&stub);

@@ -3458,7 +3462,10 @@
   __ JumpIfRoot(x4, Heap::kUninitializedSymbolRootIndex, &miss);

   if (!FLAG_trace_ic) {
-    // We are going megamorphic, and we don't want to visit the runtime.
+ // We are going megamorphic. If the feedback is a JSFunction, it is fine
+    // to handle it here. More complex cases are dealt with in the runtime.
+    __ AssertNotSmi(x4);
+    __ JumpIfNotObjectType(x4, x5, x5, JS_FUNCTION_TYPE, &miss);
     __ Add(x4, feedback_vector,
            Operand::UntagSmiAndScale(index, kPointerSizeLog2));
     __ LoadRoot(x5, Heap::kMegamorphicSymbolRootIndex);
=======================================
--- /branches/3.27/src/ia32/code-stubs-ia32.cc  Wed Jun 18 14:15:57 2014 UTC
+++ /branches/3.27/src/ia32/code-stubs-ia32.cc  Wed Aug  6 09:48:04 2014 UTC
@@ -2484,10 +2484,16 @@
   __ j(not_equal, &miss);

   __ mov(eax, arg_count());
-  __ mov(ebx, FieldOperand(ebx, edx, times_half_pointer_size,
+  __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size,
                            FixedArray::kHeaderSize));
+
   // Verify that ecx contains an AllocationSite
-  __ AssertUndefinedOrAllocationSite(ebx);
+  Factory* factory = masm->isolate()->factory();
+  __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
+         factory->allocation_site_map());
+  __ j(not_equal, &miss);
+
+  __ mov(ebx, ecx);
   ArrayConstructorStub stub(masm->isolate(), arg_count());
   __ TailCallStub(&stub);

@@ -2558,7 +2564,11 @@
   __ j(equal, &miss);

   if (!FLAG_trace_ic) {
-    // We are going megamorphic, and we don't want to visit the runtime.
+ // We are going megamorphic. If the feedback is a JSFunction, it is fine
+    // to handle it here. More complex cases are dealt with in the runtime.
+    __ AssertNotSmi(ecx);
+    __ CmpObjectType(ecx, JS_FUNCTION_TYPE, ecx);
+    __ j(not_equal, &miss);
     __ mov(FieldOperand(ebx, edx, times_half_pointer_size,
                         FixedArray::kHeaderSize),
            Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate)));
=======================================
--- /branches/3.27/src/ic.cc    Mon Jun 16 00:04:47 2014 UTC
+++ /branches/3.27/src/ic.cc    Wed Aug  6 09:48:04 2014 UTC
@@ -1855,8 +1855,13 @@
       isolate()->context()->native_context()->array_function(), isolate());
   if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) {
     // Alter the slot.
- Handle<AllocationSite> new_site = isolate()->factory()->NewAllocationSite();
-    vector->set(slot->value(), *new_site);
+    Object* feedback = vector->get(slot->value());
+    if (!feedback->IsAllocationSite()) {
+      Handle<AllocationSite> new_site =
+          isolate()->factory()->NewAllocationSite();
+      vector->set(slot->value(), *new_site);
+    }
+
     CallIC_ArrayStub stub(isolate(), state);
     set_target(*stub.GetCode());
     Handle<String> name;
@@ -1896,6 +1901,9 @@
   State state(target()->extra_ic_state());
   Object* feedback = vector->get(slot->value());

+  // Hand-coded MISS handling is easier if CallIC slots don't contain smis.
+  ASSERT(!feedback->IsSmi());
+
   if (feedback->IsJSFunction() || !function->IsJSFunction()) {
     // We are going generic.
     vector->set(slot->value(),
@@ -1904,9 +1912,14 @@

     TRACE_GENERIC_IC(isolate(), "CallIC", "megamorphic");
   } else {
-    // If we came here feedback must be the uninitialized sentinel,
-    // and we are going monomorphic.
- ASSERT(feedback == *TypeFeedbackInfo::UninitializedSentinel(isolate()));
+    // The feedback is either uninitialized or an allocation site.
+ // It might be an allocation site because if we re-compile the full code
+    // to add deoptimization support, we call with the default call-ic, and
+    // merely need to patch the target to match the feedback.
+    // TODO(mvstanton): the better approach is to dispense with patching
+    // altogether, which is in progress.
+ ASSERT(feedback == *TypeFeedbackInfo::UninitializedSentinel(isolate()) ||
+           feedback->IsAllocationSite());

     // Do we want to install a custom handler?
     if (FLAG_use_ic &&
=======================================
--- /branches/3.27/src/mips/code-stubs-mips.cc  Wed Jun 18 14:15:57 2014 UTC
+++ /branches/3.27/src/mips/code-stubs-mips.cc  Wed Aug  6 09:48:04 2014 UTC
@@ -3240,9 +3240,14 @@
   __ li(a0, Operand(arg_count()));
   __ sll(at, a3, kPointerSizeLog2 - kSmiTagSize);
   __ Addu(at, a2, Operand(at));
-  __ lw(a2, FieldMemOperand(at, FixedArray::kHeaderSize));
-  // Verify that a2 contains an AllocationSite
-  __ AssertUndefinedOrAllocationSite(a2, at);
+  __ lw(t0, FieldMemOperand(at, FixedArray::kHeaderSize));
+
+  // Verify that t0 contains an AllocationSite
+  __ lw(t1, FieldMemOperand(t0, HeapObject::kMapOffset));
+  __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex);
+  __ Branch(&miss, ne, t1, Operand(at));
+
+  __ mov(a2, t0);
   ArrayConstructorStub stub(masm->isolate(), arg_count());
   __ TailCallStub(&stub);

@@ -3309,7 +3314,11 @@
   __ Branch(&miss, eq, t0, Operand(at));

   if (!FLAG_trace_ic) {
-    // We are going megamorphic, and we don't want to visit the runtime.
+ // We are going megamorphic. If the feedback is a JSFunction, it is fine
+    // to handle it here. More complex cases are dealt with in the runtime.
+    __ AssertNotSmi(t0);
+    __ GetObjectType(t0, t1, t1);
+    __ Branch(&miss, ne, t1, Operand(JS_FUNCTION_TYPE));
     __ sll(t0, a3, kPointerSizeLog2 - kSmiTagSize);
     __ Addu(t0, a2, Operand(t0));
     __ LoadRoot(at, Heap::kMegamorphicSymbolRootIndex);
=======================================
--- /branches/3.27/src/version.cc       Mon Aug  4 14:18:05 2014 UTC
+++ /branches/3.27/src/version.cc       Wed Aug  6 09:48:04 2014 UTC
@@ -35,7 +35,7 @@
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     27
 #define BUILD_NUMBER      34
-#define PATCH_LEVEL       11
+#define PATCH_LEVEL       12
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
=======================================
--- /branches/3.27/src/x64/code-stubs-x64.cc    Wed Jun 18 14:15:57 2014 UTC
+++ /branches/3.27/src/x64/code-stubs-x64.cc    Wed Aug  6 09:48:04 2014 UTC
@@ -2378,12 +2378,16 @@
   __ cmpq(rdi, rcx);
   __ j(not_equal, &miss);

-  __ movq(rax, Immediate(arg_count()));
-  __ movp(rbx, FieldOperand(rbx, rdx, times_pointer_size,
+  __ movp(rax, Immediate(arg_count()));
+  __ movp(rcx, FieldOperand(rbx, rdx, times_pointer_size,
                             FixedArray::kHeaderSize));
-
   // Verify that ecx contains an AllocationSite
-  __ AssertUndefinedOrAllocationSite(rbx);
+  Factory* factory = masm->isolate()->factory();
+  __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset),
+         factory->allocation_site_map());
+  __ j(not_equal, &miss);
+
+  __ movp(rbx, rcx);
   ArrayConstructorStub stub(masm->isolate(), arg_count());
   __ TailCallStub(&stub);

@@ -2457,7 +2461,11 @@
   __ j(equal, &miss);

   if (!FLAG_trace_ic) {
-    // We are going megamorphic, and we don't want to visit the runtime.
+ // We are going megamorphic. If the feedback is a JSFunction, it is fine
+    // to handle it here. More complex cases are dealt with in the runtime.
+    __ AssertNotSmi(rcx);
+    __ CmpObjectType(rcx, JS_FUNCTION_TYPE, rcx);
+    __ j(not_equal, &miss);
     __ Move(FieldOperand(rbx, rdx, times_pointer_size,
                          FixedArray::kHeaderSize),
             TypeFeedbackInfo::MegamorphicSentinel(isolate));
=======================================
--- /branches/3.27/src/x87/code-stubs-x87.cc    Wed Jun 18 14:15:57 2014 UTC
+++ /branches/3.27/src/x87/code-stubs-x87.cc    Wed Aug  6 09:48:04 2014 UTC
@@ -2166,10 +2166,16 @@
   __ j(not_equal, &miss);

   __ mov(eax, arg_count());
-  __ mov(ebx, FieldOperand(ebx, edx, times_half_pointer_size,
+  __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size,
                            FixedArray::kHeaderSize));
+
   // Verify that ecx contains an AllocationSite
-  __ AssertUndefinedOrAllocationSite(ebx);
+  Factory* factory = masm->isolate()->factory();
+  __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
+         factory->allocation_site_map());
+  __ j(not_equal, &miss);
+
+  __ mov(ebx, ecx);
   ArrayConstructorStub stub(masm->isolate(), arg_count());
   __ TailCallStub(&stub);

@@ -2240,7 +2246,11 @@
   __ j(equal, &miss);

   if (!FLAG_trace_ic) {
-    // We are going megamorphic, and we don't want to visit the runtime.
+ // We are going megamorphic. If the feedback is a JSFunction, it is fine
+    // to handle it here. More complex cases are dealt with in the runtime.
+    __ AssertNotSmi(ecx);
+    __ CmpObjectType(ecx, JS_FUNCTION_TYPE, ecx);
+    __ j(not_equal, &miss);
     __ mov(FieldOperand(ebx, edx, times_half_pointer_size,
                         FixedArray::kHeaderSize),
            Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate)));

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