Version 3.1.3.

Fixed a bug triggered by functions with huge numbers of declared arguments.

Fixed zap value aliasing a real object - debug mode only.  Issue 866.

Fixed issue where Array.prototype.__proto__ had been set to null.  Issue 1121.

Fixed stability bugs in Crankshaft for x86.
Review URL: http://codereview.chromium.org/6460038

git-svn-id: http://v8.googlecode.com/svn/trunk@6711 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 9e4bada..b6a6382 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -804,7 +804,7 @@
     __ test(left, Operand(left));
     __ j(not_zero, &done);
     if (right->IsConstantOperand()) {
-      if (ToInteger32(LConstantOperand::cast(right)) < 0) {
+      if (ToInteger32(LConstantOperand::cast(right)) <= 0) {
         DeoptimizeIf(no_condition, instr->environment());
       }
     } else {
@@ -945,19 +945,31 @@
   if (BitCast<uint64_t, double>(v) == 0) {
     __ xorpd(res, res);
   } else {
-    int32_t v_int32 = static_cast<int32_t>(v);
-    if (static_cast<double>(v_int32) == v) {
-      __ push_imm32(v_int32);
-      __ cvtsi2sd(res, Operand(esp, 0));
-      __ add(Operand(esp), Immediate(kPointerSize));
+    Register temp = ToRegister(instr->TempAt(0));
+    uint64_t int_val = BitCast<uint64_t, double>(v);
+    int32_t lower = static_cast<int32_t>(int_val);
+    int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
+    if (CpuFeatures::IsSupported(SSE4_1)) {
+      CpuFeatures::Scope scope(SSE4_1);
+      if (lower != 0) {
+        __ Set(temp, Immediate(lower));
+        __ movd(res, Operand(temp));
+        __ Set(temp, Immediate(upper));
+        __ pinsrd(res, Operand(temp), 1);
+      } else {
+        __ xorpd(res, res);
+        __ Set(temp, Immediate(upper));
+        __ pinsrd(res, Operand(temp), 1);
+      }
     } else {
-      uint64_t int_val = BitCast<uint64_t, double>(v);
-      int32_t lower = static_cast<int32_t>(int_val);
-      int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
-      __ push_imm32(upper);
-      __ push_imm32(lower);
-      __ movdbl(res, Operand(esp, 0));
-      __ add(Operand(esp), Immediate(2 * kPointerSize));
+      __ Set(temp, Immediate(upper));
+      __ movd(res, Operand(temp));
+      __ psllq(res, 32);
+      if (lower != 0) {
+        __ Set(temp, Immediate(lower));
+        __ movd(xmm0, Operand(temp));
+        __ por(res, xmm0);
+      }
     }
   }
 }
@@ -1881,7 +1893,7 @@
   }
   __ mov(esp, ebp);
   __ pop(ebp);
-  __ ret((ParameterCount() + 1) * kPointerSize);
+  __ Ret((ParameterCount() + 1) * kPointerSize, ecx);
 }
 
 
@@ -2035,7 +2047,10 @@
   ASSERT(result.is(elements));
 
   // Load the result.
-  __ mov(result, FieldOperand(elements, key, times_4, FixedArray::kHeaderSize));
+  __ mov(result, FieldOperand(elements,
+                              key,
+                              times_pointer_size,
+                              FixedArray::kHeaderSize));
 
   // Check for the hole value.
   __ cmp(result, Factory::the_hole_value());
@@ -2661,13 +2676,20 @@
         ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize;
     __ mov(FieldOperand(elements, offset), value);
   } else {
-    __ mov(FieldOperand(elements, key, times_4, FixedArray::kHeaderSize),
+    __ mov(FieldOperand(elements,
+                        key,
+                        times_pointer_size,
+                        FixedArray::kHeaderSize),
            value);
   }
 
   if (instr->hydrogen()->NeedsWriteBarrier()) {
     // Compute address of modified element and store it into key register.
-    __ lea(key, FieldOperand(elements, key, times_4, FixedArray::kHeaderSize));
+    __ lea(key,
+           FieldOperand(elements,
+                        key,
+                        times_pointer_size,
+                        FixedArray::kHeaderSize));
     __ RecordWrite(elements, key, value);
   }
 }
@@ -3577,6 +3599,53 @@
 }
 
 
+void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) {
+  Register result = ToRegister(instr->result());
+  NearLabel true_label;
+  NearLabel false_label;
+  NearLabel done;
+
+  EmitIsConstructCall(result);
+  __ j(equal, &true_label);
+
+  __ mov(result, Factory::false_value());
+  __ jmp(&done);
+
+  __ bind(&true_label);
+  __ mov(result, Factory::true_value());
+
+  __ bind(&done);
+}
+
+
+void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
+  Register temp = ToRegister(instr->TempAt(0));
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+
+  EmitIsConstructCall(temp);
+  EmitBranch(true_block, false_block, equal);
+}
+
+
+void LCodeGen::EmitIsConstructCall(Register temp) {
+  // Get the frame pointer for the calling frame.
+  __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
+
+  // Skip the arguments adaptor frame if it exists.
+  NearLabel check_frame_marker;
+  __ cmp(Operand(temp, StandardFrameConstants::kContextOffset),
+         Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+  __ j(not_equal, &check_frame_marker);
+  __ mov(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset));
+
+  // Check the marker in the calling frame.
+  __ bind(&check_frame_marker);
+  __ cmp(Operand(temp, StandardFrameConstants::kMarkerOffset),
+         Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
+}
+
+
 void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
   // No code for lazy bailout instruction. Used to capture environment after a
   // call for populating the safepoint data with deoptimization data.