Revision: 12607
Author:   [email protected]
Date:     Tue Sep 25 10:29:23 2012
Log:      Merged r12531, r12562, r12563 into 3.12 branch.

Fix casting error for receiver of interceptors.

Fix LBoundsCheck on x64 to handle (stack slot + constant) correctly

Fix missing slot recodring during clearing of CallICs.

BUG=chromium:149912,150729,chromium:144230

[email protected]

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

Added:
 /branches/3.12/test/mjsunit/regress/regress-crbug-150729.js
Modified:
 /branches/3.12/src/ic-inl.h
 /branches/3.12/src/objects.cc
 /branches/3.12/src/objects.h
 /branches/3.12/src/version.cc
 /branches/3.12/src/x64/lithium-codegen-x64.cc
 /branches/3.12/test/cctest/test-api.cc
 /branches/3.12/test/cctest/test-heap.cc

=======================================
--- /dev/null
+++ /branches/3.12/test/mjsunit/regress/regress-crbug-150729.js Tue Sep 25 10:29:23 2012
@@ -0,0 +1,39 @@
+// 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
+
+var t = 0;
+function burn() {
+  i = [t, 1];
+  var M = [i[0], Math.cos(t) + i[7074959]];
+  t += .05;
+}
+for (var j = 0; j < 5; j++) {
+  if (j == 2) %OptimizeFunctionOnNextCall(burn);
+  burn();
+}
=======================================
--- /branches/3.12/src/ic-inl.h Tue Feb 21 02:08:21 2012
+++ /branches/3.12/src/ic-inl.h Tue Sep 25 10:29:23 2012
@@ -79,6 +79,7 @@

 void IC::SetTargetAtAddress(Address address, Code* target) {
   ASSERT(target->is_inline_cache_stub() || target->is_compare_ic_stub());
+  Heap* heap = target->GetHeap();
   Code* old_target = GetTargetAtAddress(address);
 #ifdef DEBUG
   // STORE_IC and KEYED_STORE_IC use Code::extra_ic_state() to mark
@@ -90,8 +91,15 @@
   }
 #endif
   Assembler::set_target_address_at(address, target->instruction_start());
-  target->GetHeap()->incremental_marking()->RecordCodeTargetPatch(address,
-                                                                  target);
+  if (heap->gc_state() == Heap::MARK_COMPACT &&
+      heap->mark_compact_collector()->is_compacting()) {
+    Code* host = heap->isolate()->inner_pointer_to_code_cache()->
+        GcSafeFindCodeForInnerPointer(address);
+    RelocInfo rinfo(address, RelocInfo::CODE_TARGET, 0, host);
+    heap->mark_compact_collector()->RecordRelocSlot(&rinfo, target);
+  } else {
+    heap->incremental_marking()->RecordCodeTargetPatch(address, target);
+  }
   PostPatching(address, target, old_target);
 }

=======================================
--- /branches/3.12/src/objects.cc       Wed Sep  5 13:04:15 2012
+++ /branches/3.12/src/objects.cc       Tue Sep 25 10:29:23 2012
@@ -650,11 +650,9 @@
           receiver, result->GetCallbackObject(), name);
     case HANDLER:
       return result->proxy()->GetPropertyWithHandler(receiver, name);
-    case INTERCEPTOR: {
-      JSObject* recvr = JSObject::cast(receiver);
+    case INTERCEPTOR:
       return result->holder()->GetPropertyWithInterceptor(
-          recvr, name, attributes);
-    }
+          receiver, name, attributes);
     case TRANSITION:
     case NONEXISTENT:
       UNREACHABLE();
@@ -10239,7 +10237,7 @@


 MaybeObject* JSObject::GetPropertyPostInterceptor(
-    JSReceiver* receiver,
+    Object* receiver,
     String* name,
     PropertyAttributes* attributes) {
   // Check local property in holder, ignore interceptor.
@@ -10257,7 +10255,7 @@


 MaybeObject* JSObject::GetLocalPropertyPostInterceptor(
-    JSReceiver* receiver,
+    Object* receiver,
     String* name,
     PropertyAttributes* attributes) {
   // Check local property in holder, ignore interceptor.
@@ -10271,13 +10269,13 @@


 MaybeObject* JSObject::GetPropertyWithInterceptor(
-    JSReceiver* receiver,
+    Object* receiver,
     String* name,
     PropertyAttributes* attributes) {
   Isolate* isolate = GetIsolate();
   InterceptorInfo* interceptor = GetNamedInterceptor();
   HandleScope scope(isolate);
-  Handle<JSReceiver> receiver_handle(receiver);
+  Handle<Object> receiver_handle(receiver);
   Handle<JSObject> holder_handle(this);
   Handle<String> name_handle(name);

=======================================
--- /branches/3.12/src/objects.h        Tue Aug 21 01:56:54 2012
+++ /branches/3.12/src/objects.h        Tue Sep 25 10:29:23 2012
@@ -1683,15 +1683,15 @@
       String* name,
       PropertyAttributes* attributes);
   MUST_USE_RESULT MaybeObject* GetPropertyWithInterceptor(
-      JSReceiver* receiver,
+      Object* receiver,
       String* name,
       PropertyAttributes* attributes);
   MUST_USE_RESULT MaybeObject* GetPropertyPostInterceptor(
-      JSReceiver* receiver,
+      Object* receiver,
       String* name,
       PropertyAttributes* attributes);
   MUST_USE_RESULT MaybeObject* GetLocalPropertyPostInterceptor(
-      JSReceiver* receiver,
+      Object* receiver,
       String* name,
       PropertyAttributes* attributes);

=======================================
--- /branches/3.12/src/version.cc       Fri Sep 21 03:40:37 2012
+++ /branches/3.12/src/version.cc       Tue Sep 25 10:29:23 2012
@@ -35,7 +35,7 @@
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     12
 #define BUILD_NUMBER      19
-#define PATCH_LEVEL       12
+#define PATCH_LEVEL       13
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
=======================================
--- /branches/3.12/src/x64/lithium-codegen-x64.cc       Wed Aug  1 04:14:42 2012
+++ /branches/3.12/src/x64/lithium-codegen-x64.cc       Tue Sep 25 10:29:23 2012
@@ -3643,11 +3643,17 @@
       __ cmpq(reg, reg2);
     }
   } else {
+    Operand length = ToOperand(instr->length());
     if (instr->index()->IsConstantOperand()) {
-      __ cmpq(ToOperand(instr->length()),
- Immediate(ToInteger32(LConstantOperand::cast(instr->index()))));
+      int constant_index =
+          ToInteger32(LConstantOperand::cast(instr->index()));
+      if (instr->hydrogen()->length()->representation().IsTagged()) {
+        __ Cmp(length, Smi::FromInt(constant_index));
+      } else {
+        __ cmpq(length, Immediate(constant_index));
+      }
     } else {
-      __ cmpq(ToOperand(instr->length()), ToRegister(instr->index()));
+      __ cmpq(length, ToRegister(instr->index()));
     }
   }
   DeoptimizeIf(below_equal, instr->environment());
=======================================
--- /branches/3.12/test/cctest/test-api.cc      Mon Sep 17 01:14:05 2012
+++ /branches/3.12/test/cctest/test-api.cc      Tue Sep 25 10:29:23 2012
@@ -17182,3 +17182,13 @@
   CompileRun("try { throw new Error(); } finally { gc(); }");
   CHECK(try_catch.HasCaught());
 }
+
+
+THREADED_TEST(Regress149912) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Handle<FunctionTemplate> templ = FunctionTemplate::New();
+  AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
+  context->Global()->Set(v8_str("Bug"), templ->GetFunction());
+  CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
+}
=======================================
--- /branches/3.12/test/cctest/test-heap.cc     Wed Aug  1 04:14:42 2012
+++ /branches/3.12/test/cctest/test-heap.cc     Tue Sep 25 10:29:23 2012
@@ -4,10 +4,12 @@

 #include "v8.h"

+#include "compilation-cache.h"
 #include "execution.h"
 #include "factory.h"
 #include "macro-assembler.h"
 #include "global-handles.h"
+#include "stub-cache.h"
 #include "cctest.h"

 using namespace v8::internal;
@@ -2025,3 +2027,62 @@
     CHECK_LE(hashtable->SizeFor(hashtable->length()), 13 * kPointerSize);
   }
 }
+
+
+TEST(Regression144230) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  // First make sure that the uninitialized CallIC stub is on a single page
+  // that will later be selected as an evacuation candidate.
+  {
+    v8::HandleScope inner_scope;
+    AlwaysAllocateScope always_allocate;
+    SimulateFullSpace(HEAP->code_space());
+ ISOLATE->stub_cache()->ComputeCallInitialize(9, RelocInfo::CODE_TARGET);
+  }
+
+  // Second compile a CallIC and execute it once so that it gets patched to
+  // the pre-monomorphic stub. These code objects are on yet another page.
+  {
+    v8::HandleScope inner_scope;
+    AlwaysAllocateScope always_allocate;
+    SimulateFullSpace(HEAP->code_space());
+    CompileRun("var o = { f:function(a,b,c,d,e,f,g,h,i) {}};"
+               "function call() { o.f(1,2,3,4,5,6,7,8,9); };"
+               "call();");
+  }
+
+ // Third we fill up the last page of the code space so that it does not get
+  // chosen as an evacuation candidate.
+  {
+    v8::HandleScope inner_scope;
+    AlwaysAllocateScope always_allocate;
+    CompileRun("for (var i = 0; i < 2000; i++) {"
+               "  eval('function f' + i + '() { return ' + i +'; };' +"
+               "       'f' + i + '();');"
+               "}");
+  }
+  HEAP->CollectAllGarbage(Heap::kNoGCFlags);
+
+  // Fourth is the tricky part. Make sure the code containing the CallIC is
+ // visited first without clearing the IC. The shared function info is then
+  // visited later, causing the CallIC to be cleared.
+  Handle<String> name = FACTORY->LookupAsciiSymbol("call");
+  Handle<GlobalObject> global(ISOLATE->context()->global());
+  MaybeObject* maybe_call = global->GetProperty(*name);
+  JSFunction* call = JSFunction::cast(maybe_call->ToObjectChecked());
+  USE(global->SetProperty(*name, Smi::FromInt(0), NONE, kNonStrictMode));
+  ISOLATE->compilation_cache()->Clear();
+  call->shared()->set_ic_age(HEAP->global_ic_age() + 1);
+  Handle<Object> call_code(call->code());
+  Handle<Object> call_function(call);
+
+  // Now we are ready to mess up the heap.
+  HEAP->CollectAllGarbage(Heap::kReduceMemoryFootprintMask);
+
+ // Either heap verification caught the problem already or we go kaboom once
+  // the CallIC is executed the next time.
+  USE(global->SetProperty(*name, *call_function, NONE, kNonStrictMode));
+  CompileRun("call();");
+}

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to