Revision: 11894
Author:   [email protected]
Date:     Thu Jun 21 04:16:20 2012
Log:      Version 3.12.1

Performance and stability improvements on all platforms.
http://code.google.com/p/v8/source/detail?r=11894

Added:
 /trunk/test/mjsunit/math-floor-of-div-minus-zero.js
Modified:
 /trunk/ChangeLog
 /trunk/src/arm/lithium-codegen-arm.cc
 /trunk/src/hydrogen-instructions.cc
 /trunk/src/hydrogen-instructions.h
 /trunk/src/ia32/disasm-ia32.cc
 /trunk/src/ia32/lithium-codegen-ia32.cc
 /trunk/src/ia32/lithium-ia32.cc
 /trunk/src/ia32/lithium-ia32.h
 /trunk/src/isolate.cc
 /trunk/src/mips/lithium-codegen-mips.cc
 /trunk/src/parser.cc
 /trunk/src/version.cc
 /trunk/src/x64/disasm-x64.cc
 /trunk/src/x64/lithium-codegen-x64.cc
 /trunk/src/x64/lithium-x64.cc
 /trunk/src/x64/lithium-x64.h
 /trunk/test/cctest/test-api.cc
 /trunk/test/mjsunit/mjsunit.status
 /trunk/test/mjsunit/regress/regress-2185-2.js

=======================================
--- /dev/null
+++ /trunk/test/mjsunit/math-floor-of-div-minus-zero.js Thu Jun 21 04:16:20 2012
@@ -0,0 +1,40 @@
+// 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 --nouse_inlining
+
+// Test for negative zero that doesn't need bail out
+
+function test_div_no_deopt_minus_zero() {
+  var zero_in_array = [0];
+  assertTrue(0 === (Math.floor((zero_in_array[0] | 0) / -1) | 0));
+}
+
+test_div_no_deopt_minus_zero();
+%OptimizeFunctionOnNextCall(test_div_no_deopt_minus_zero);
+test_div_no_deopt_minus_zero();
+assertTrue(2 != %GetOptimizationStatus(test_div_no_deopt_minus_zero));
=======================================
--- /trunk/ChangeLog    Wed Jun 20 04:29:00 2012
+++ /trunk/ChangeLog    Thu Jun 21 04:16:20 2012
@@ -1,3 +1,8 @@
+2012-06-21: Version 3.12.1
+
+        Performance and stability improvements on all platforms.
+
+
 2012-06-20: Version 3.12.0

         Fixed Chromium issues:
=======================================
--- /trunk/src/arm/lithium-codegen-arm.cc       Wed Jun 20 04:29:00 2012
+++ /trunk/src/arm/lithium-codegen-arm.cc       Thu Jun 21 04:16:20 2012
@@ -2597,15 +2597,15 @@
   } else {
     // Negative lookup.
     // Check prototypes.
-    HeapObject* current = HeapObject::cast((*type)->prototype());
+    Handle<HeapObject> current(HeapObject::cast((*type)->prototype()));
     Heap* heap = type->GetHeap();
-    while (current != heap->null_value()) {
-      Handle<HeapObject> link(current);
-      __ LoadHeapObject(result, link);
+    while (*current != heap->null_value()) {
+      __ LoadHeapObject(result, current);
       __ ldr(result, FieldMemOperand(result, HeapObject::kMapOffset));
-      __ cmp(result, Operand(Handle<Map>(JSObject::cast(current)->map())));
+      __ cmp(result, Operand(Handle<Map>(current->map())));
       DeoptimizeIf(ne, env);
-      current = HeapObject::cast(current->map()->prototype());
+      current =
+ Handle<HeapObject>(HeapObject::cast(current->map()->prototype()));
     }
     __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
   }
=======================================
--- /trunk/src/hydrogen-instructions.cc Wed Jun 13 04:51:58 2012
+++ /trunk/src/hydrogen-instructions.cc Thu Jun 21 04:16:20 2012
@@ -941,7 +941,8 @@
     // introduced.
     if (value()->representation().IsInteger32()) return value();

-#ifdef V8_TARGET_ARCH_ARM
+#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_IA32) || \
+        defined(V8_TARGET_ARCH_X64)
     if (value()->IsDiv() && (value()->UseCount() == 1)) {
       // TODO(2038): Implement this optimization for non ARM architectures.
       HDiv* hdiv = HDiv::cast(value());
@@ -2221,6 +2222,13 @@
   }
   return NULL;
 }
+
+
+HValue* HMathFloorOfDiv::EnsureAndPropagateNotMinusZero(BitVector* visited) {
+  visited->Add(id());
+  SetFlag(kBailoutOnMinusZero);
+  return NULL;
+}


 HValue* HMul::EnsureAndPropagateNotMinusZero(BitVector* visited) {
=======================================
--- /trunk/src/hydrogen-instructions.h  Wed Jun 20 04:29:00 2012
+++ /trunk/src/hydrogen-instructions.h  Thu Jun 21 04:16:20 2012
@@ -2774,7 +2774,10 @@
       : HBinaryOperation(context, left, right) {
     set_representation(Representation::Integer32());
     SetFlag(kUseGVN);
-  }
+    SetFlag(kCanOverflow);
+  }
+
+  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);

   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Integer32();
=======================================
--- /trunk/src/ia32/disasm-ia32.cc      Tue Dec 13 00:07:27 2011
+++ /trunk/src/ia32/disasm-ia32.cc      Thu Jun 21 04:16:20 2012
@@ -553,6 +553,7 @@
       case 2: mnem = "not"; break;
       case 3: mnem = "neg"; break;
       case 4: mnem = "mul"; break;
+      case 5: mnem = "imul"; break;
       case 7: mnem = "idiv"; break;
       default: UnimplementedInstruction();
     }
=======================================
--- /trunk/src/ia32/lithium-codegen-ia32.cc     Wed Jun 20 04:29:00 2012
+++ /trunk/src/ia32/lithium-codegen-ia32.cc     Thu Jun 21 04:16:20 2012
@@ -1020,6 +1020,109 @@
   __ test(edx, Operand(edx));
   DeoptimizeIf(not_zero, instr->environment());
 }
+
+
+void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) {
+  ASSERT(instr->InputAt(1)->IsConstantOperand());
+
+  Register dividend = ToRegister(instr->InputAt(0));
+  int32_t divisor = ToInteger32(LConstantOperand::cast(instr->InputAt(1)));
+  Register result = ToRegister(instr->result());
+
+  switch (divisor) {
+  case 0:
+    DeoptimizeIf(no_condition, instr->environment());
+    return;
+
+  case 1:
+    __ Move(result, dividend);
+    return;
+
+  case -1:
+    __ Move(result, dividend);
+    __ neg(result);
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      DeoptimizeIf(zero, instr->environment());
+    }
+    if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+      DeoptimizeIf(overflow, instr->environment());
+    }
+    return;
+  }
+
+  uint32_t divisor_abs = abs(divisor);
+  if (IsPowerOf2(divisor_abs)) {
+    int32_t power = WhichPowerOf2(divisor_abs);
+    if (divisor < 0) {
+      // Input[dividend] is clobbered.
+      // The sequence is tedious because neg(dividend) might overflow.
+      __ mov(result, dividend);
+      __ sar(dividend, 31);
+      __ neg(result);
+      if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+        DeoptimizeIf(zero, instr->environment());
+      }
+      __ shl(dividend, 32 - power);
+      __ sar(result, power);
+      __ not_(dividend);
+      // Clear result.sign if dividend.sign is set.
+      __ and_(result, dividend);
+    } else {
+      __ Move(result, dividend);
+      __ sar(result, power);
+    }
+  } else {
+    ASSERT(ToRegister(instr->InputAt(0)).is(eax));
+    ASSERT(ToRegister(instr->result()).is(edx));
+    Register scratch = ToRegister(instr->TempAt(0));
+
+    // Find b which: 2^b < divisor_abs < 2^(b+1).
+    unsigned b = 31 - CompilerIntrinsics::CountLeadingZeros(divisor_abs);
+    unsigned shift = 32 + b;  // Precision +1bit (effectively).
+    double multiplier_f =
+ static_cast<double>(static_cast<uint64_t>(1) << shift) / divisor_abs;
+    int64_t multiplier;
+    if (multiplier_f - floor(multiplier_f) < 0.5) {
+        multiplier = static_cast<int64_t>(floor(multiplier_f));
+    } else {
+        multiplier = static_cast<int64_t>(floor(multiplier_f)) + 1;
+    }
+    // The multiplier is a uint32.
+    ASSERT(multiplier > 0 &&
+           multiplier < (static_cast<int64_t>(1) << 32));
+    __ mov(scratch, dividend);
+    if (divisor < 0 &&
+        instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      __ test(dividend, dividend);
+      DeoptimizeIf(zero, instr->environment());
+    }
+    __ mov(edx, static_cast<int32_t>(multiplier));
+    __ imul(edx);
+    if (static_cast<int32_t>(multiplier) < 0) {
+      __ add(edx, scratch);
+    }
+    Register reg_lo = eax;
+    Register reg_byte_scratch = scratch;
+    if (!reg_byte_scratch.is_byte_register()) {
+        __ xchg(reg_lo, reg_byte_scratch);
+        reg_lo = scratch;
+        reg_byte_scratch = eax;
+    }
+    if (divisor < 0) {
+      __ xor_(reg_byte_scratch, reg_byte_scratch);
+      __ cmp(reg_lo, 0x40000000);
+      __ setcc(above, reg_byte_scratch);
+      __ neg(edx);
+      __ sub(edx, reg_byte_scratch);
+    } else {
+      __ xor_(reg_byte_scratch, reg_byte_scratch);
+      __ cmp(reg_lo, 0xC0000000);
+      __ setcc(above_equal, reg_byte_scratch);
+      __ add(edx, reg_byte_scratch);
+    }
+    __ sar(edx, shift - 32);
+  }
+}


 void LCodeGen::DoMulI(LMulI* instr) {
@@ -2327,15 +2430,15 @@
   } else {
     // Negative lookup.
     // Check prototypes.
-    HeapObject* current = HeapObject::cast((*type)->prototype());
+    Handle<HeapObject> current(HeapObject::cast((*type)->prototype()));
     Heap* heap = type->GetHeap();
-    while (current != heap->null_value()) {
-      Handle<HeapObject> link(current);
-      __ LoadHeapObject(result, link);
+    while (*current != heap->null_value()) {
+      __ LoadHeapObject(result, current);
       __ cmp(FieldOperand(result, HeapObject::kMapOffset),
-                          Handle<Map>(JSObject::cast(current)->map()));
+                          Handle<Map>(current->map()));
       DeoptimizeIf(not_equal, env);
-      current = HeapObject::cast(current->map()->prototype());
+      current =
+ Handle<HeapObject>(HeapObject::cast(current->map()->prototype()));
     }
     __ mov(result, factory()->undefined_value());
   }
=======================================
--- /trunk/src/ia32/lithium-ia32.cc     Wed Jun 13 04:51:58 2012
+++ /trunk/src/ia32/lithium-ia32.cc     Thu Jun 21 04:16:20 2012
@@ -1347,10 +1347,55 @@
 }


-LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
-  UNIMPLEMENTED();
+HValue* LChunkBuilder::SimplifiedDividendForMathFloorOfDiv(HValue* dividend) { + // A value with an integer representation does not need to be transformed.
+  if (dividend->representation().IsInteger32()) {
+    return dividend;
+  // A change from an integer32 can be replaced by the integer32 value.
+  } else if (dividend->IsChange() &&
+      HChange::cast(dividend)->from().IsInteger32()) {
+    return HChange::cast(dividend)->value();
+  }
   return NULL;
 }
+
+
+HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) {
+  if (divisor->IsConstant() &&
+      HConstant::cast(divisor)->HasInteger32Value()) {
+    HConstant* constant_val = HConstant::cast(divisor);
+    return constant_val->CopyToRepresentation(Representation::Integer32(),
+                                              divisor->block()->zone());
+  }
+  return NULL;
+}
+
+
+LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
+  HValue* right = instr->right();
+ ASSERT(right->IsConstant() && HConstant::cast(right)->HasInteger32Value()); + LOperand* divisor = chunk_->DefineConstantOperand(HConstant::cast(right));
+  int32_t divisor_si = HConstant::cast(right)->Integer32Value();
+  if (divisor_si == 0) {
+    LOperand* dividend = UseRegister(instr->left());
+    return AssignEnvironment(DefineAsRegister(
+        new(zone()) LMathFloorOfDiv(dividend, divisor, NULL)));
+  } else if (IsPowerOf2(abs(divisor_si))) {
+    // use dividend as temp if divisor < 0 && divisor != -1
+    LOperand* dividend = divisor_si < -1 ? UseTempRegister(instr->left()) :
+                         UseRegisterAtStart(instr->left());
+    LInstruction* result = DefineAsRegister(
+        new(zone()) LMathFloorOfDiv(dividend, divisor, NULL));
+    return divisor_si < 0 ? AssignEnvironment(result) : result;
+  } else {
+    // needs edx:eax, plus a temp
+    LOperand* dividend = UseFixed(instr->left(), eax);
+    LOperand* temp = TempRegister();
+    LInstruction* result = DefineFixed(
+        new(zone()) LMathFloorOfDiv(dividend, divisor, temp), edx);
+    return divisor_si < 0 ? AssignEnvironment(result) : result;
+  }
+}


 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
=======================================
--- /trunk/src/ia32/lithium-ia32.h      Wed Jun 13 04:51:58 2012
+++ /trunk/src/ia32/lithium-ia32.h      Thu Jun 21 04:16:20 2012
@@ -126,6 +126,7 @@
   V(LoadNamedField)                             \
   V(LoadNamedFieldPolymorphic)                  \
   V(LoadNamedGeneric)                           \
+  V(MathFloorOfDiv)                             \
   V(MathPowHalf)                                \
   V(ModI)                                       \
   V(MulI)                                       \
@@ -546,6 +547,21 @@
 };


+class LMathFloorOfDiv: public LTemplateInstruction<1, 2, 1> {
+ public:
+  LMathFloorOfDiv(LOperand* left,
+                  LOperand* right,
+                  LOperand* temp = NULL) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+    temps_[0] = temp;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv, "math-floor-of-div")
+  DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
+};
+
+
 class LMulI: public LTemplateInstruction<1, 2, 1> {
  public:
   LMulI(LOperand* left, LOperand* right, LOperand* temp) {
@@ -2399,6 +2415,9 @@
   HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
 #undef DECLARE_DO

+  static HValue* SimplifiedDividendForMathFloorOfDiv(HValue* val);
+  static HValue* SimplifiedDivisorForMathFloorOfDiv(HValue* val);
+
  private:
   enum Status {
     UNUSED,
=======================================
--- /trunk/src/isolate.cc       Wed Jun 20 04:29:00 2012
+++ /trunk/src/isolate.cc       Thu Jun 21 04:16:20 2012
@@ -945,12 +945,9 @@
   // When scheduling a throw we first throw the exception to get the
   // error reporting if it is uncaught before rescheduling it.
   Throw(exception);
-  PropagatePendingExceptionToExternalTryCatch();
-  if (has_pending_exception()) {
-    thread_local_top()->scheduled_exception_ = pending_exception();
-    thread_local_top()->external_caught_exception_ = false;
-    clear_pending_exception();
-  }
+  thread_local_top()->scheduled_exception_ = pending_exception();
+  thread_local_top()->external_caught_exception_ = false;
+  clear_pending_exception();
 }


=======================================
--- /trunk/src/mips/lithium-codegen-mips.cc     Wed Jun 20 04:29:00 2012
+++ /trunk/src/mips/lithium-codegen-mips.cc     Thu Jun 21 04:16:20 2012
@@ -2341,15 +2341,14 @@
   } else {
     // Negative lookup.
     // Check prototypes.
-    HeapObject* current = HeapObject::cast((*type)->prototype());
+    Handle<HeapObject> current(HeapObject::cast((*type)->prototype()));
     Heap* heap = type->GetHeap();
-    while (current != heap->null_value()) {
-      Handle<HeapObject> link(current);
-      __ LoadHeapObject(result, link);
+    while (*current != heap->null_value()) {
+      __ LoadHeapObject(result, current);
       __ lw(result, FieldMemOperand(result, HeapObject::kMapOffset));
-      DeoptimizeIf(ne, env,
-          result, Operand(Handle<Map>(JSObject::cast(current)->map())));
-      current = HeapObject::cast(current->map()->prototype());
+      DeoptimizeIf(ne, env, result, Operand(Handle<Map>(current->map())));
+      current =
+ Handle<HeapObject>(HeapObject::cast(current->map()->prototype()));
     }
     __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
   }
=======================================
--- /trunk/src/parser.cc        Wed Jun 20 04:29:00 2012
+++ /trunk/src/parser.cc        Thu Jun 21 04:16:20 2012
@@ -6026,7 +6026,6 @@
 bool ParserApi::Parse(CompilationInfo* info, int parsing_flags) {
   ASSERT(info->function() == NULL);
   FunctionLiteral* result = NULL;
-  Handle<Script> script = info->script();
   ASSERT((parsing_flags & kLanguageModeMask) == CLASSIC_MODE);
   if (!info->is_native() && FLAG_harmony_scoping) {
     // Harmony scoping is requested.
=======================================
--- /trunk/src/version.cc       Wed Jun 20 04:29:00 2012
+++ /trunk/src/version.cc       Thu Jun 21 04:16:20 2012
@@ -34,7 +34,7 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     12
-#define BUILD_NUMBER      0
+#define BUILD_NUMBER      1
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
=======================================
--- /trunk/src/x64/disasm-x64.cc        Tue May 22 02:16:05 2012
+++ /trunk/src/x64/disasm-x64.cc        Thu Jun 21 04:16:20 2012
@@ -703,6 +703,9 @@
       case 4:
         mnem = "mul";
         break;
+      case 5:
+        mnem = "imul";
+        break;
       case 7:
         mnem = "idiv";
         break;
=======================================
--- /trunk/src/x64/lithium-codegen-x64.cc       Wed Jun 20 04:29:00 2012
+++ /trunk/src/x64/lithium-codegen-x64.cc       Thu Jun 21 04:16:20 2012
@@ -884,6 +884,89 @@
     __ bind(&done);
   }
 }
+
+
+void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) {
+  ASSERT(instr->InputAt(1)->IsConstantOperand());
+
+  const Register dividend = ToRegister(instr->InputAt(0));
+  int32_t divisor = ToInteger32(LConstantOperand::cast(instr->InputAt(1)));
+  const Register result = ToRegister(instr->result());
+
+  switch (divisor) {
+  case 0:
+    DeoptimizeIf(no_condition, instr->environment());
+    return;
+
+  case 1:
+    if (!result.is(dividend)) {
+        __ movl(result, dividend);
+    }
+    return;
+
+  case -1:
+    if (!result.is(dividend)) {
+      __ movl(result, dividend);
+    }
+    __ negl(result);
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      DeoptimizeIf(zero, instr->environment());
+    }
+    if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+      DeoptimizeIf(overflow, instr->environment());
+    }
+    return;
+  }
+
+  uint32_t divisor_abs = abs(divisor);
+  if (IsPowerOf2(divisor_abs)) {
+    int32_t power = WhichPowerOf2(divisor_abs);
+    if (divisor < 0) {
+      __ movsxlq(result, dividend);
+      __ neg(result);
+      if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+        DeoptimizeIf(zero, instr->environment());
+      }
+      __ sar(result, Immediate(power));
+    } else {
+      if (!result.is(dividend)) {
+        __ movl(result, dividend);
+      }
+      __ sarl(result, Immediate(power));
+    }
+  } else {
+    Register reg1 = ToRegister(instr->TempAt(0));
+    Register reg2 = ToRegister(instr->result());
+
+    // Find b which: 2^b < divisor_abs < 2^(b+1).
+    unsigned b = 31 - CompilerIntrinsics::CountLeadingZeros(divisor_abs);
+    unsigned shift = 32 + b;  // Precision +1bit (effectively).
+    double multiplier_f =
+ static_cast<double>(static_cast<uint64_t>(1) << shift) / divisor_abs;
+    int64_t multiplier;
+    if (multiplier_f - floor(multiplier_f) < 0.5) {
+        multiplier = static_cast<int64_t>(floor(multiplier_f));
+    } else {
+        multiplier = static_cast<int64_t>(floor(multiplier_f)) + 1;
+    }
+    // The multiplier is a uint32.
+    ASSERT(multiplier > 0 &&
+           multiplier < (static_cast<int64_t>(1) << 32));
+    // The multiply is int64, so sign-extend to r64.
+    __ movsxlq(reg1, dividend);
+    if (divisor < 0 &&
+        instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      __ neg(reg1);
+      DeoptimizeIf(zero, instr->environment());
+    }
+    __ movq(reg2, multiplier, RelocInfo::NONE);
+    // Result just fit in r64, because it's int32 * uint32.
+    __ imul(reg2, reg1);
+
+    __ addq(reg2, Immediate(1 << 30));
+    __ sar(reg2, Immediate(shift));
+  }
+}


 void LCodeGen::DoDivI(LDivI* instr) {
@@ -2221,15 +2304,15 @@
   } else {
     // Negative lookup.
     // Check prototypes.
-    HeapObject* current = HeapObject::cast((*type)->prototype());
+    Handle<HeapObject> current(HeapObject::cast((*type)->prototype()));
     Heap* heap = type->GetHeap();
-    while (current != heap->null_value()) {
-      Handle<HeapObject> link(current);
-      __ LoadHeapObject(result, link);
+    while (*current != heap->null_value()) {
+      __ LoadHeapObject(result, current);
       __ Cmp(FieldOperand(result, HeapObject::kMapOffset),
-                          Handle<Map>(JSObject::cast(current)->map()));
+                          Handle<Map>(current->map()));
       DeoptimizeIf(not_equal, env);
-      current = HeapObject::cast(current->map()->prototype());
+      current =
+ Handle<HeapObject>(HeapObject::cast(current->map()->prototype()));
     }
     __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
   }
=======================================
--- /trunk/src/x64/lithium-x64.cc       Wed Jun 13 04:51:58 2012
+++ /trunk/src/x64/lithium-x64.cc       Thu Jun 21 04:16:20 2012
@@ -1287,10 +1287,53 @@
 }


-LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
-  UNIMPLEMENTED();
+HValue* LChunkBuilder::SimplifiedDividendForMathFloorOfDiv(HValue* dividend) { + // A value with an integer representation does not need to be transformed.
+  if (dividend->representation().IsInteger32()) {
+    return dividend;
+  // A change from an integer32 can be replaced by the integer32 value.
+  } else if (dividend->IsChange() &&
+      HChange::cast(dividend)->from().IsInteger32()) {
+    return HChange::cast(dividend)->value();
+  }
   return NULL;
 }
+
+
+HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) {
+  if (divisor->IsConstant() &&
+      HConstant::cast(divisor)->HasInteger32Value()) {
+    HConstant* constant_val = HConstant::cast(divisor);
+    return constant_val->CopyToRepresentation(Representation::Integer32(),
+                                              divisor->block()->zone());
+  }
+  return NULL;
+}
+
+
+LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
+  HValue* right = instr->right();
+ ASSERT(right->IsConstant() && HConstant::cast(right)->HasInteger32Value()); + LOperand* divisor = chunk_->DefineConstantOperand(HConstant::cast(right));
+  int32_t divisor_si = HConstant::cast(right)->Integer32Value();
+  if (divisor_si == 0) {
+    LOperand* dividend = UseRegister(instr->left());
+    return AssignEnvironment(DefineAsRegister(
+        new(zone()) LMathFloorOfDiv(dividend, divisor, NULL)));
+  } else if (IsPowerOf2(abs(divisor_si))) {
+    LOperand* dividend = UseRegisterAtStart(instr->left());
+    LInstruction* result = DefineAsRegister(
+        new(zone()) LMathFloorOfDiv(dividend, divisor, NULL));
+    return divisor_si < 0 ? AssignEnvironment(result) : result;
+  } else {
+    // use two r64
+    LOperand* dividend = UseRegisterAtStart(instr->left());
+    LOperand* temp = TempRegister();
+    LInstruction* result = DefineAsRegister(
+        new(zone()) LMathFloorOfDiv(dividend, divisor, temp));
+    return divisor_si < 0 ? AssignEnvironment(result) : result;
+  }
+}


 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
=======================================
--- /trunk/src/x64/lithium-x64.h        Wed Jun 13 04:51:58 2012
+++ /trunk/src/x64/lithium-x64.h        Thu Jun 21 04:16:20 2012
@@ -132,6 +132,7 @@
   V(LoadNamedField)                             \
   V(LoadNamedFieldPolymorphic)                  \
   V(LoadNamedGeneric)                           \
+  V(MathFloorOfDiv)                             \
   V(ModI)                                       \
   V(MulI)                                       \
   V(NumberTagD)                                 \
@@ -554,6 +555,21 @@
 };


+class LMathFloorOfDiv: public LTemplateInstruction<1, 2, 1> {
+ public:
+  LMathFloorOfDiv(LOperand* left,
+                  LOperand* right,
+                  LOperand* temp = NULL) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+    temps_[0] = temp;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv, "math-floor-of-div")
+  DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
+};
+
+
 class LMulI: public LTemplateInstruction<1, 2, 0> {
  public:
   LMulI(LOperand* left, LOperand* right) {
@@ -2255,6 +2271,9 @@
   HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
 #undef DECLARE_DO

+  static HValue* SimplifiedDividendForMathFloorOfDiv(HValue* val);
+  static HValue* SimplifiedDivisorForMathFloorOfDiv(HValue* val);
+
  private:
   enum Status {
     UNUSED,
=======================================
--- /trunk/test/cctest/test-api.cc      Wed Jun 20 04:29:00 2012
+++ /trunk/test/cctest/test-api.cc      Thu Jun 21 04:16:20 2012
@@ -3361,30 +3361,6 @@
       "}\n");
   CHECK(try_catch.HasCaught());
 }
-
-
-static void TryCatchNestedHelper(int depth) {
-  if (depth > 0) {
-    v8::TryCatch try_catch;
-    try_catch.SetVerbose(true);
-    TryCatchNestedHelper(depth - 1);
-    CHECK(try_catch.HasCaught());
-    try_catch.ReThrow();
-  } else {
-    v8::ThrowException(v8_str("back"));
-  }
-}
-
-
-TEST(TryCatchNested) {
-  v8::V8::Initialize();
-  v8::HandleScope scope;
-  LocalContext context;
-  v8::TryCatch try_catch;
-  TryCatchNestedHelper(5);
-  CHECK(try_catch.HasCaught());
- CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "back"));
-}


 THREADED_TEST(Equality) {
@@ -5242,7 +5218,7 @@
   object.MarkIndependent();
   HEAP->PerformScavenge();
   CHECK(revived);
-  HEAP->CollectAllGarbage(true);
+  HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   {
     v8::HandleScope handle_scope;
     v8::Local<String> y_str = v8_str("y");
@@ -9394,7 +9370,8 @@
 v8::Handle<v8::Value> DirectApiCallback(const v8::Arguments& args) {
   static int count = 0;
   if (count++ % 3 == 0) {
-    HEAP->  CollectAllGarbage(true);  // This should move the stub
+    HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+        // This should move the stub
GenerateSomeGarbage(); // This should ensure the old stub memory is flushed
   }
   return v8::Handle<v8::Value>();
@@ -9449,7 +9426,7 @@
 v8::Handle<v8::Value> DirectGetterCallback(Local<String> name,
                                            const v8::AccessorInfo& info) {
   if (++p_getter_count % 3 == 0) {
-    HEAP->CollectAllGarbage(true);
+    HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
     GenerateSomeGarbage();
   }
   return v8::Handle<v8::Value>();
@@ -16120,7 +16097,8 @@
     CHECK_LE(1, elements);
   }

-  i::Isolate::Current()->heap()->CollectAllGarbage(true);
+  i::Isolate::Current()->heap()->CollectAllGarbage(
+      i::Heap::kAbortIncrementalMarkingMask);
{ i::Object* raw_map_cache = i::Isolate::Current()->context()->map_cache(); if (raw_map_cache != i::Isolate::Current()->heap()->undefined_value()) {
       i::MapCache* map_cache = i::MapCache::cast(raw_map_cache);
=======================================
--- /trunk/test/mjsunit/mjsunit.status  Wed Jun 20 04:29:00 2012
+++ /trunk/test/mjsunit/mjsunit.status  Thu Jun 21 04:16:20 2012
@@ -126,6 +126,9 @@
 debug-liveedit-stack-padding: SKIP
 debug-liveedit-restart-frame: SKIP

+# Currently always deopt on minus zero
+math-floor-of-div-minus-zero: SKIP
+
##############################################################################
 [ $arch == mips ]

=======================================
--- /trunk/test/mjsunit/regress/regress-2185-2.js       Wed Jun 20 04:29:00 2012
+++ /trunk/test/mjsunit/regress/regress-2185-2.js       Thu Jun 21 04:16:20 2012
@@ -27,7 +27,7 @@

 // These tests used to time out before this was fixed.

-var LEN = 1e5;
+var LEN = 3e4;

 function short() {
   var sum = 0;

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

Reply via email to