Revision: 13655
Author:   [email protected]
Date:     Wed Feb 13 06:01:22 2013
Log:      MIPS: Generate the TransitionElementsStub using Crankshaft

Port r13585 (4174b9d2)

Original commit message:
This includes:
* Adding support for saving callee-clobbered double registers in Crankshaft code. * Adding a new "HTrapAllocationMemento" hydrogen instruction to handle AllocationSiteInfo data in crankshafted stubs. * Adding a new "HAllocate" hydrogen instruction that can allocate raw memory from the GC in crankshafted code. * Support for manipulation of the hole in HChange instructions for Crankshafted stubs. * Utility routines to manually build loops and if statements containing hydrogen code.

BUG=
TEST=

Review URL: https://chromiumcodereview.appspot.com/12212080
http://code.google.com/p/v8/source/detail?r=13655

Modified:
 /branches/bleeding_edge/src/mips/assembler-mips-inl.h
 /branches/bleeding_edge/src/mips/assembler-mips.h
 /branches/bleeding_edge/src/mips/code-stubs-mips.cc
 /branches/bleeding_edge/src/mips/codegen-mips.cc
 /branches/bleeding_edge/src/mips/deoptimizer-mips.cc
 /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc
 /branches/bleeding_edge/src/mips/lithium-codegen-mips.h
 /branches/bleeding_edge/src/mips/lithium-mips.cc
 /branches/bleeding_edge/src/mips/lithium-mips.h
 /branches/bleeding_edge/src/mips/macro-assembler-mips.cc
 /branches/bleeding_edge/src/mips/macro-assembler-mips.h

=======================================
--- /branches/bleeding_edge/src/mips/assembler-mips-inl.h Mon Jan 7 02:18:25 2013 +++ /branches/bleeding_edge/src/mips/assembler-mips-inl.h Wed Feb 13 06:01:22 2013
@@ -91,7 +91,7 @@

 int DoubleRegister::NumRegisters() {
   if (CpuFeatures::IsSupported(FPU)) {
-    return FPURegister::kNumRegisters;
+    return FPURegister::kMaxNumRegisters;
   } else {
     return 1;
   }
=======================================
--- /branches/bleeding_edge/src/mips/assembler-mips.h Wed Jan 23 08:29:48 2013 +++ /branches/bleeding_edge/src/mips/assembler-mips.h Wed Feb 13 06:01:22 2013
@@ -189,7 +189,7 @@

 // Coprocessor register.
 struct FPURegister {
-  static const int kNumRegisters = v8::internal::kNumFPURegisters;
+  static const int kMaxNumRegisters = v8::internal::kNumFPURegisters;

// TODO(plind): Warning, inconsistent numbering here. kNumFPURegisters refers
   // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to
@@ -200,7 +200,7 @@
   //  f28: 0.0
   //  f30: scratch register.
   static const int kNumReservedRegisters = 2;
-  static const int kMaxNumAllocatableRegisters = kNumRegisters / 2 -
+  static const int kMaxNumAllocatableRegisters = kMaxNumRegisters / 2 -
       kNumReservedRegisters;

   inline static int NumRegisters();
@@ -218,7 +218,7 @@
     return r;
   }

-  bool is_valid() const { return 0 <= code_ && code_ < kNumFPURegisters ; }
+  bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters ; }
   bool is(FPURegister creg) const { return code_ == creg.code_; }
   FPURegister low() const {
     // Find low reg of a Double-reg pair, which is the reg itself.
=======================================
--- /branches/bleeding_edge/src/mips/code-stubs-mips.cc Thu Jan 31 04:57:05 2013 +++ /branches/bleeding_edge/src/mips/code-stubs-mips.cc Wed Feb 13 06:01:22 2013
@@ -48,6 +48,18 @@
   descriptor->deoptimization_handler_ =
       FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure);
 }
+
+
+void TransitionElementsKindStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  static Register registers[] = { a0, a1 };
+  descriptor->register_param_count_ = 2;
+  descriptor->register_params_ = registers;
+  Address entry =
+      Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry;
+  descriptor->deoptimization_handler_ = FUNCTION_ADDR(entry);
+}


 #define __ ACCESS_MASM(masm)
=======================================
--- /branches/bleeding_edge/src/mips/codegen-mips.cc Mon Jan 21 00:30:11 2013 +++ /branches/bleeding_edge/src/mips/codegen-mips.cc Wed Feb 13 06:01:22 2013
@@ -155,7 +155,7 @@
   // -----------------------------------
   if (mode == TRACK_ALLOCATION_SITE) {
     ASSERT(allocation_site_info_found != NULL);
-    masm->TestJSArrayForAllocationSiteInfo(a2, t0,
+    masm->TestJSArrayForAllocationSiteInfo(a2, t0, eq,
                                            allocation_site_info_found);
   }

@@ -188,7 +188,7 @@
   Register scratch = t6;

   if (mode == TRACK_ALLOCATION_SITE) {
-    masm->TestJSArrayForAllocationSiteInfo(a2, t0, fail);
+    masm->TestJSArrayForAllocationSiteInfo(a2, t0, eq, fail);
   }

// Check for empty arrays, which only require a map transition and no changes
@@ -332,7 +332,7 @@
   Label entry, loop, convert_hole, gc_required, only_change_map;

   if (mode == TRACK_ALLOCATION_SITE) {
-    masm->TestJSArrayForAllocationSiteInfo(a2, t0, fail);
+    masm->TestJSArrayForAllocationSiteInfo(a2, t0, eq, fail);
   }

// Check for empty arrays, which only require a map transition and no changes
=======================================
--- /branches/bleeding_edge/src/mips/deoptimizer-mips.cc Wed Feb 13 05:45:26 2013 +++ /branches/bleeding_edge/src/mips/deoptimizer-mips.cc Wed Feb 13 06:01:22 2013
@@ -525,6 +525,11 @@
     output_frame_offset -= kPointerSize;
     DoTranslateCommand(iterator, 0, output_frame_offset);
   }
+
+  for (int i = 0; i < DoubleRegister::kMaxNumRegisters; ++i) {
+    double double_value = input_->GetDoubleRegister(i);
+    output_frame->SetDoubleRegister(i, double_value);
+  }

   value = input_->GetRegister(fp.code());
   output_frame->SetRegister(fp.code(), value);
@@ -1076,11 +1081,11 @@
     }
   }

+  int double_regs_offset = FrameDescription::double_registers_offset();
   if (CpuFeatures::IsSupported(FPU)) {
     CpuFeatures::Scope scope(FPU);
     // Copy FPU registers to
     // double_registers_[DoubleRegister::kNumAllocatableRegisters]
-    int double_regs_offset = FrameDescription::double_registers_offset();
     for (int i = 0; i < FPURegister::NumAllocatableRegisters(); ++i) {
       int dst_offset = i * kDoubleSize + double_regs_offset;
       int src_offset = i * kDoubleSize + kNumberOfRegisters * kPointerSize;
@@ -1131,16 +1136,16 @@
   // Replace the current (input) frame with the output frames.
   Label outer_push_loop, inner_push_loop,
       outer_loop_header, inner_loop_header;
-  // Outer loop state: a0 = current "FrameDescription** output_",
+  // Outer loop state: t0 = current "FrameDescription** output_",
   // a1 = one past the last FrameDescription**.
   __ lw(a1, MemOperand(a0, Deoptimizer::output_count_offset()));
- __ lw(a0, MemOperand(a0, Deoptimizer::output_offset())); // a0 is output_. + __ lw(t0, MemOperand(a0, Deoptimizer::output_offset())); // t0 is output_.
   __ sll(a1, a1, kPointerSizeLog2);  // Count to offset.
-  __ addu(a1, a0, a1);  // a1 = one past the last FrameDescription**.
+  __ addu(a1, t0, a1);  // a1 = one past the last FrameDescription**.
   __ jmp(&outer_loop_header);
   __ bind(&outer_push_loop);
   // Inner loop state: a2 = current FrameDescription*, a3 = loop index.
-  __ lw(a2, MemOperand(a0, 0));  // output_[ix]
+  __ lw(a2, MemOperand(t0, 0));  // output_[ix]
   __ lw(a3, MemOperand(a2, FrameDescription::frame_size_offset()));
   __ jmp(&inner_loop_header);
   __ bind(&inner_push_loop);
@@ -1151,10 +1156,20 @@
   __ bind(&inner_loop_header);
   __ Branch(&inner_push_loop, ne, a3, Operand(zero_reg));

-  __ Addu(a0, a0, Operand(kPointerSize));
+  __ Addu(t0, t0, Operand(kPointerSize));
   __ bind(&outer_loop_header);
-  __ Branch(&outer_push_loop, lt, a0, Operand(a1));
+  __ Branch(&outer_push_loop, lt, t0, Operand(a1));

+  if (CpuFeatures::IsSupported(FPU)) {
+    CpuFeatures::Scope scope(FPU);
+
+    __ lw(a1, MemOperand(a0, Deoptimizer::input_offset()));
+    for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) {
+      const FPURegister fpu_reg = FPURegister::FromAllocationIndex(i);
+      int src_offset = i * kDoubleSize + double_regs_offset;
+      __ ldc1(fpu_reg, MemOperand(a1, src_offset));
+    }
+  }

   // Push state, pc, and continuation from the last output frame.
   if (type() != OSR) {
=======================================
--- /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Tue Feb 12 03:44:08 2013 +++ /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Wed Feb 13 06:01:22 2013
@@ -147,14 +147,21 @@

   info()->set_prologue_offset(masm_->pc_offset());
   if (NeedsEagerFrame()) {
- // The following three instructions must remain together and unmodified for
-    // code aging to work properly.
-    __ Push(ra, fp, cp, a1);
-    // Add unused load of ip to ensure prologue sequence is identical for
-    // full-codegen and lithium-codegen.
-    __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
-    // Adj. FP to point to saved FP.
-    __ Addu(fp, sp, Operand(2 * kPointerSize));
+    if (info()->IsStub()) {
+      __ Push(ra, fp, cp);
+      __ Push(Smi::FromInt(StackFrame::STUB));
+      // Adjust FP to point to saved FP.
+      __ Addu(fp, sp, Operand(2 * kPointerSize));
+    } else {
+ // The following three instructions must remain together and unmodified
+      // for code aging to work properly.
+      __ Push(ra, fp, cp, a1);
+      // Add unused load of ip to ensure prologue sequence is identical for
+      // full-codegen and lithium-codegen.
+      __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
+      // Adj. FP to point to saved FP.
+      __ Addu(fp, sp, Operand(2 * kPointerSize));
+    }
     frame_is_built_ = true;
   }

@@ -162,17 +169,36 @@
   int slots = GetStackSlotCount();
   if (slots > 0) {
     if (FLAG_debug_code) {
-      __ li(a0, Operand(slots));
-      __ li(a2, Operand(kSlotsZapValue));
+      __ Subu(sp,  sp, Operand(slots * kPointerSize));
+      __ push(a0);
+      __ push(a1);
+      __ Addu(a0, sp, Operand(slots *  kPointerSize));
+      __ li(a1, Operand(kSlotsZapValue));
       Label loop;
       __ bind(&loop);
-      __ push(a2);
-      __ Subu(a0, a0, 1);
-      __ Branch(&loop, ne, a0, Operand(zero_reg));
+      __ Subu(a0, a0, Operand(kPointerSize));
+      __ sw(a1, MemOperand(a0, 2 * kPointerSize));
+      __ Branch(&loop, ne, a0, Operand(sp));
+      __ pop(a1);
+      __ pop(a0);
     } else {
       __ Subu(sp, sp, Operand(slots * kPointerSize));
     }
   }
+
+  if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(FPU)) {
+    CpuFeatures::Scope scope(FPU);
+    Comment(";;; Save clobbered callee double registers");
+    int count = 0;
+    BitVector* doubles = chunk()->allocated_double_registers();
+    BitVector::Iterator save_iterator(doubles);
+    while (!save_iterator.Done()) {
+      __ sdc1(DoubleRegister::FromAllocationIndex(save_iterator.Current()),
+              MemOperand(sp, count * kDoubleSize));
+      save_iterator.Advance();
+      count++;
+    }
+  }

   // Possibly allocate a local context.
   int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
@@ -2464,11 +2490,26 @@
     __ push(v0);
     __ CallRuntime(Runtime::kTraceExit, 1);
   }
+  if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(FPU)) {
+    CpuFeatures::Scope scope(FPU);
+    ASSERT(NeedsEagerFrame());
+    BitVector* doubles = chunk()->allocated_double_registers();
+    BitVector::Iterator save_iterator(doubles);
+    int count = 0;
+    while (!save_iterator.Done()) {
+      __ ldc1(DoubleRegister::FromAllocationIndex(save_iterator.Current()),
+              MemOperand(sp, count * kDoubleSize));
+      save_iterator.Advance();
+      count++;
+    }
+  }
   if (NeedsEagerFrame()) {
     int32_t sp_delta = (GetParameterCount() + 1) * kPointerSize;
     __ mov(sp, fp);
     __ Pop(ra, fp);
-    __ Addu(sp, sp, Operand(sp_delta));
+    if (!info()->IsStub()) {
+      __ Addu(sp, sp, Operand(sp_delta));
+    }
   }
   __ Jump(ra);
 }
@@ -3245,8 +3286,14 @@


 void LCodeGen::DoContext(LContext* instr) {
+  // If there is a non-return use, the context must be moved to a register.
   Register result = ToRegister(instr->result());
-  __ mov(result, cp);
+ for (HUseIterator it(instr->hydrogen()->uses()); !it.Done(); it.Advance()) {
+    if (!it.value()->IsReturn()) {
+      __ mov(result, cp);
+      return;
+    }
+  }
 }


@@ -4173,7 +4220,6 @@

 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
   Register object_reg = ToRegister(instr->object());
-  Register new_map_reg = ToRegister(instr->new_map_temp());
   Register scratch = scratch0();

   Handle<Map> from_map = instr->original_map();
@@ -4181,23 +4227,32 @@
   ElementsKind from_kind = instr->from_kind();
   ElementsKind to_kind = instr->to_kind();

-  __ mov(ToRegister(instr->result()), object_reg);
-
   Label not_applicable;
   __ lw(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset));
   __ Branch(&not_applicable, ne, scratch, Operand(from_map));

-  __ li(new_map_reg, Operand(to_map));
   if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
+    Register new_map_reg = ToRegister(instr->new_map_temp());
+    __ li(new_map_reg, Operand(to_map));
__ sw(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset));
     // Write barrier.
     __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
                         scratch, kRAHasBeenSaved, kDontSaveFPRegs);
+  } else if (FLAG_compiled_transitions) {
+    PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
+    __ mov(a0, object_reg);
+    __ li(a1, Operand(to_map));
+    TransitionElementsKindStub stub(from_kind, to_kind);
+    __ CallStub(&stub);
+    RecordSafepointWithRegisters(
+        instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
   } else if (IsFastSmiElementsKind(from_kind) &&
              IsFastDoubleElementsKind(to_kind)) {
     Register fixed_object_reg = ToRegister(instr->temp());
     ASSERT(fixed_object_reg.is(a2));
+    Register new_map_reg = ToRegister(instr->new_map_temp());
     ASSERT(new_map_reg.is(a3));
+    __ li(new_map_reg, Operand(to_map));
     __ mov(fixed_object_reg, object_reg);
     CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(),
              RelocInfo::CODE_TARGET, instr);
@@ -4205,7 +4260,9 @@
              IsFastObjectElementsKind(to_kind)) {
     Register fixed_object_reg = ToRegister(instr->temp());
     ASSERT(fixed_object_reg.is(a2));
+    Register new_map_reg = ToRegister(instr->new_map_temp());
     ASSERT(new_map_reg.is(a3));
+    __ li(new_map_reg, Operand(to_map));
     __ mov(fixed_object_reg, object_reg);
     CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(),
              RelocInfo::CODE_TARGET, instr);
@@ -4214,6 +4271,16 @@
   }
   __ bind(&not_applicable);
 }
+
+
+void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
+  Register object = ToRegister(instr->object());
+  Register temp = ToRegister(instr->temp());
+  Label fail;
+  __ TestJSArrayForAllocationSiteInfo(object, temp, ne, &fail);
+  DeoptimizeIf(al, instr->environment());
+  __ bind(&fail);
+}


 void LCodeGen::DoStringAdd(LStringAdd* instr) {
@@ -4552,6 +4619,52 @@
   Register temp1 = ToRegister(instr->temp());
   Register temp2 = ToRegister(instr->temp2());

+  bool convert_hole = false;
+  HValue* change_input = instr->hydrogen()->value();
+  if (change_input->IsLoadKeyed()) {
+    HLoadKeyed* load = HLoadKeyed::cast(change_input);
+    convert_hole = load->UsesMustHandleHole();
+  }
+
+  Label no_special_nan_handling;
+  Label done;
+  if (convert_hole) {
+    if (CpuFeatures::IsSupported(FPU)) {
+      CpuFeatures::Scope scope(FPU);
+      DoubleRegister input_reg = ToDoubleRegister(instr->value());
+      __ BranchF(&no_special_nan_handling, NULL, eq, input_reg, input_reg);
+      __ Move(reg, scratch0(), input_reg);
+      Label canonicalize;
+      __ Branch(&canonicalize, ne, scratch0(), Operand(kHoleNanUpper32));
+      __ li(reg, factory()->the_hole_value());
+      __ Branch(&done);
+      __ bind(&canonicalize);
+      __ Move(input_reg,
+              FixedDoubleArray::canonical_not_the_hole_nan_as_double());
+    } else {
+      Label not_hole;
+      __ Branch(&not_hole, ne, sfpd_hi, Operand(kHoleNanUpper32));
+      __ li(reg, factory()->the_hole_value());
+      __ Branch(&done);
+      __ bind(&not_hole);
+      __ And(scratch, sfpd_hi, Operand(0x7ff00000));
+ __ Branch(&no_special_nan_handling, ne, scratch, Operand(0x7ff00000));
+      Label special_nan_handling;
+      __ And(at, sfpd_hi, Operand(0x000FFFFF));
+      __ Branch(&special_nan_handling, ne, at, Operand(zero_reg));
+      __ Branch(&no_special_nan_handling, eq, sfpd_lo, Operand(zero_reg));
+      __ bind(&special_nan_handling);
+      double canonical_nan =
+          FixedDoubleArray::canonical_not_the_hole_nan_as_double();
+      uint64_t casted_nan = BitCast<uint64_t>(canonical_nan);
+      __ li(sfpd_lo,
+            Operand(static_cast<uint32_t>(casted_nan & 0xFFFFFFFF)));
+      __ li(sfpd_hi,
+            Operand(static_cast<uint32_t>(casted_nan >> 32)));
+    }
+  }
+
+  __ bind(&no_special_nan_handling);
DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr);
   if (FLAG_inline_new) {
     __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
@@ -4571,6 +4684,7 @@
   }
   // Now that we have finished with the object's real address tag it
   __ Addu(reg, reg, kHeapObjectTag);
+  __ bind(&done);
 }


@@ -4614,43 +4728,57 @@
                                 DoubleRegister result_reg,
                                 bool deoptimize_on_undefined,
                                 bool deoptimize_on_minus_zero,
-                                LEnvironment* env) {
+                                LEnvironment* env,
+                                NumberUntagDMode mode) {
   Register scratch = scratch0();
   CpuFeatures::Scope scope(FPU);

   Label load_smi, heap_number, done;

-  // Smi check.
-  __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);
+  if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
+    // Smi check.
+    __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);

-  // Heap number map check.
-  __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
-  __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
-  if (deoptimize_on_undefined) {
-    DeoptimizeIf(ne, env, scratch, Operand(at));
-  } else {
-    Label heap_number;
-    __ Branch(&heap_number, eq, scratch, Operand(at));
+    // Heap number map check.
+    __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
+    __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
+    if (deoptimize_on_undefined) {
+      DeoptimizeIf(ne, env, scratch, Operand(at));
+    } else {
+      Label heap_number;
+      __ Branch(&heap_number, eq, scratch, Operand(at));

-    __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
-    DeoptimizeIf(ne, env, input_reg, Operand(at));
+      __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
+      DeoptimizeIf(ne, env, input_reg, Operand(at));

-    // Convert undefined to NaN.
-    __ LoadRoot(at, Heap::kNanValueRootIndex);
-    __ ldc1(result_reg, FieldMemOperand(at, HeapNumber::kValueOffset));
-    __ Branch(&done);
+      // Convert undefined to NaN.
+      __ LoadRoot(at, Heap::kNanValueRootIndex);
+      __ ldc1(result_reg, FieldMemOperand(at, HeapNumber::kValueOffset));
+      __ Branch(&done);

-    __ bind(&heap_number);
-  }
-  // Heap number to double register conversion.
- __ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset));
-  if (deoptimize_on_minus_zero) {
-    __ mfc1(at, result_reg.low());
-    __ Branch(&done, ne, at, Operand(zero_reg));
-    __ mfc1(scratch, result_reg.high());
-    DeoptimizeIf(eq, env, scratch, Operand(HeapNumber::kSignMask));
+      __ bind(&heap_number);
+    }
+    // Heap number to double register conversion.
+ __ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset));
+    if (deoptimize_on_minus_zero) {
+      __ mfc1(at, result_reg.low());
+      __ Branch(&done, ne, at, Operand(zero_reg));
+      __ mfc1(scratch, result_reg.high());
+      DeoptimizeIf(eq, env, scratch, Operand(HeapNumber::kSignMask));
+    }
+    __ Branch(&done);
+  } else if (mode == NUMBER_CANDIDATE_IS_SMI_OR_HOLE) {
+    __ SmiUntag(scratch, input_reg);
+    DeoptimizeIf(Ugreater_equal, env, scratch, Operand(zero_reg));
+  } else if (mode == NUMBER_CANDIDATE_IS_SMI_CONVERT_HOLE) {
+    __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);
+    __ Move(result_reg,
+            FixedDoubleArray::hole_nan_as_double());
+    __ Branch(&done);
+  } else {
+    __ SmiUntag(scratch, input_reg);
+    ASSERT(mode == NUMBER_CANDIDATE_IS_SMI);
   }
-  __ Branch(&done);

   // Smi to double register conversion
   __ bind(&load_smi);
@@ -4776,11 +4904,29 @@

   Register input_reg = ToRegister(input);
   DoubleRegister result_reg = ToDoubleRegister(result);
+
+  NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED;
+  HValue* value = instr->hydrogen()->value();
+  if (value->type().IsSmi()) {
+    if (value->IsLoadKeyed()) {
+      HLoadKeyed* load = HLoadKeyed::cast(value);
+      if (load->UsesMustHandleHole()) {
+        if (load->hole_mode() == ALLOW_RETURN_HOLE) {
+          mode = NUMBER_CANDIDATE_IS_SMI_CONVERT_HOLE;
+        } else {
+          mode = NUMBER_CANDIDATE_IS_SMI_OR_HOLE;
+        }
+      } else {
+        mode = NUMBER_CANDIDATE_IS_SMI;
+      }
+    }
+  }

   EmitNumberUntagD(input_reg, result_reg,
                    instr->hydrogen()->deoptimize_on_undefined(),
                    instr->hydrogen()->deoptimize_on_minus_zero(),
-                   instr->environment());
+                   instr->environment(),
+                   mode);
 }


@@ -5072,6 +5218,63 @@
   CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
   __ StoreToSafepointRegisterSlot(v0, result);
 }
+
+
+void LCodeGen::DoAllocate(LAllocate* instr) {
+  class DeferredAllocate: public LDeferredCode {
+   public:
+    DeferredAllocate(LCodeGen* codegen, LAllocate* instr)
+        : LDeferredCode(codegen), instr_(instr) { }
+    virtual void Generate() { codegen()->DoDeferredAllocate(instr_); }
+    virtual LInstruction* instr() { return instr_; }
+   private:
+    LAllocate* instr_;
+  };
+
+  DeferredAllocate* deferred =
+      new(zone()) DeferredAllocate(this, instr);
+
+  Register size = ToRegister(instr->size());
+  Register result = ToRegister(instr->result());
+  Register scratch = ToRegister(instr->temp1());
+  Register scratch2 = ToRegister(instr->temp2());
+
+  HAllocate* original_instr = instr->hydrogen();
+  if (original_instr->size()->IsConstant()) {
+    UNREACHABLE();
+  } else {
+    // Allocate memory for the object.
+    AllocationFlags flags = TAG_OBJECT;
+    if (original_instr->MustAllocateDoubleAligned()) {
+      flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
+    }
+    __ AllocateInNewSpace(size,
+                          result,
+                          scratch,
+                          scratch2,
+                          deferred->entry(),
+                          TAG_OBJECT);
+  }
+
+  __ bind(deferred->exit());
+}
+
+
+void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
+  Register size = ToRegister(instr->size());
+  Register result = ToRegister(instr->result());
+
+  // TODO(3095996): Get rid of this. For now, we need to make the
+  // result register contain a valid pointer because it is already
+  // contained in the register pointer map.
+  __ mov(result, zero_reg);
+
+  PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
+  __ SmiTag(size, size);
+  __ push(size);
+  CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
+  __ StoreToSafepointRegisterSlot(v0, result);
+}


 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
=======================================
--- /branches/bleeding_edge/src/mips/lithium-codegen-mips.h Tue Feb 12 03:44:08 2013 +++ /branches/bleeding_edge/src/mips/lithium-codegen-mips.h Wed Feb 13 06:01:22 2013
@@ -133,6 +133,7 @@
   void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
   void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
   void DoDeferredAllocateObject(LAllocateObject* instr);
+  void DoDeferredAllocate(LAllocate* instr);
   void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
                                        Label* map_check);

@@ -326,7 +327,8 @@
                         DoubleRegister result,
                         bool deoptimize_on_undefined,
                         bool deoptimize_on_minus_zero,
-                        LEnvironment* env);
+                        LEnvironment* env,
+                        NumberUntagDMode mode);

   // Emits optimized code for typeof x == "y".  Modifies input register.
   // Returns the condition on which a final split to
=======================================
--- /branches/bleeding_edge/src/mips/lithium-mips.cc Tue Feb 12 03:44:08 2013 +++ /branches/bleeding_edge/src/mips/lithium-mips.cc Wed Feb 13 06:01:22 2013
@@ -2011,12 +2011,16 @@

 LInstruction* LChunkBuilder::DoTransitionElementsKind(
     HTransitionElementsKind* instr) {
+  LOperand* object = UseRegister(instr->object());
   if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
-    LOperand* object = UseRegister(instr->object());
     LOperand* new_map_reg = TempRegister();
     LTransitionElementsKind* result =
         new(zone()) LTransitionElementsKind(object, new_map_reg, NULL);
     return DefineSameAsFirst(result);
+  } else if (FLAG_compiled_transitions) {
+    LTransitionElementsKind* result =
+        new(zone()) LTransitionElementsKind(object, NULL, NULL);
+    return AssignPointerMap(result);
   } else {
     LOperand* object = UseFixed(instr->object(), a0);
     LOperand* fixed_object_reg = FixedTemp(a2);
@@ -2025,9 +2029,19 @@
         new(zone()) LTransitionElementsKind(object,
                                             new_map_reg,
                                             fixed_object_reg);
-    return MarkAsCall(DefineFixed(result, v0), instr);
+    return MarkAsCall(result, instr);
   }
 }
+
+
+LInstruction* LChunkBuilder::DoTrapAllocationMemento(
+    HTrapAllocationMemento* instr) {
+  LOperand* object = UseRegister(instr->object());
+  LOperand* temp = TempRegister();
+  LTrapAllocationMemento* result =
+      new(zone()) LTrapAllocationMemento(object, temp);
+  return AssignEnvironment(result);
+}


 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
@@ -2096,10 +2110,21 @@


 LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
+  info()->MarkAsDeferredCalling();
   LAllocateObject* result =
       new(zone()) LAllocateObject(TempRegister(), TempRegister());
   return AssignPointerMap(DefineAsRegister(result));
 }
+
+
+LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
+  info()->MarkAsDeferredCalling();
+  LOperand* size = UseTempRegister(instr->size());
+  LOperand* temp1 = TempRegister();
+  LOperand* temp2 = TempRegister();
+  LAllocate* result = new(zone()) LAllocate(size, temp1, temp2);
+  return AssignPointerMap(DefineAsRegister(result));
+}


 LInstruction* LChunkBuilder::DoFastLiteral(HFastLiteral* instr) {
=======================================
--- /branches/bleeding_edge/src/mips/lithium-mips.h     Wed Jan 23 07:25:28 2013
+++ /branches/bleeding_edge/src/mips/lithium-mips.h     Wed Feb 13 06:01:22 2013
@@ -50,6 +50,7 @@
   V(AccessArgumentsAt)                          \
   V(AddI)                                       \
   V(AllocateObject)                             \
+  V(Allocate)                                   \
   V(ApplyArguments)                             \
   V(ArgumentsElements)                          \
   V(ArgumentsLength)                            \
@@ -173,6 +174,7 @@
   V(Throw)                                      \
   V(ToFastProperties)                           \
   V(TransitionElementsKind)                     \
+  V(TrapAllocationMemento)                      \
   V(Typeof)                                     \
   V(TypeofIsAndBranch)                          \
   V(UnaryMathOperation)                         \
@@ -1583,6 +1585,7 @@
 class LContext: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(Context, "context")
+  DECLARE_HYDROGEN_ACCESSOR(Context)
 };


@@ -1816,6 +1819,7 @@
   LOperand* temp2() { return temps_[1]; }

   DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d")
+  DECLARE_HYDROGEN_ACCESSOR(Change)
 };


@@ -2000,10 +2004,10 @@
  public:
   LTransitionElementsKind(LOperand* object,
                           LOperand* new_map_temp,
-                          LOperand* temp) {
+                          LOperand* fixed_object_temp) {
     inputs_[0] = object;
     temps_[0] = new_map_temp;
-    temps_[1] = temp;
+    temps_[1] = fixed_object_temp;
   }

   LOperand* object() { return inputs_[0]; }
@@ -2023,6 +2027,22 @@
 };


+class LTrapAllocationMemento : public LTemplateInstruction<0, 1, 1> {
+ public:
+  LTrapAllocationMemento(LOperand* object,
+                         LOperand* temp) {
+    inputs_[0] = object;
+    temps_[0] = temp;
+  }
+
+  LOperand* object() { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento,
+                               "trap-allocation-memento")
+};
+
+
 class LStringAdd: public LTemplateInstruction<1, 2, 0> {
  public:
   LStringAdd(LOperand* left, LOperand* right) {
@@ -2203,7 +2223,7 @@
 };


-class LAllocateObject: public LTemplateInstruction<1, 0, 2> {
+class LAllocateObject: public LTemplateInstruction<1, 1, 2> {
  public:
   LAllocateObject(LOperand* temp, LOperand* temp2) {
     temps_[0] = temp;
@@ -2218,6 +2238,23 @@
 };


+class LAllocate: public LTemplateInstruction<1, 2, 2> {
+ public:
+  LAllocate(LOperand* size, LOperand* temp1, LOperand* temp2) {
+    inputs_[1] = size;
+    temps_[0] = temp1;
+    temps_[1] = temp2;
+  }
+
+  LOperand* size() { return inputs_[1]; }
+  LOperand* temp1() { return temps_[0]; }
+  LOperand* temp2() { return temps_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Allocate, "allocate")
+  DECLARE_HYDROGEN_ACCESSOR(Allocate)
+};
+
+
 class LFastLiteral: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(FastLiteral, "fast-literal")
=======================================
--- /branches/bleeding_edge/src/mips/macro-assembler-mips.cc Tue Jan 22 08:18:59 2013 +++ /branches/bleeding_edge/src/mips/macro-assembler-mips.cc Wed Feb 13 06:01:22 2013
@@ -4632,16 +4632,17 @@

   const int frame_alignment = MacroAssembler::ActivationFrameAlignment();
   if (save_doubles) {
+    CpuFeatures::Scope scope(FPU);
     // The stack  must be allign to 0 modulo 8 for stores with sdc1.
     ASSERT(kDoubleSize == frame_alignment);
     if (frame_alignment > 0) {
       ASSERT(IsPowerOf2(frame_alignment));
       And(sp, sp, Operand(-frame_alignment));  // Align stack.
     }
-    int space = FPURegister::kNumRegisters * kDoubleSize;
+    int space = FPURegister::kMaxNumRegisters * kDoubleSize;
     Subu(sp, sp, Operand(space));
     // Remember: we only need to save every 2nd double FPU value.
-    for (int i = 0; i < FPURegister::kNumRegisters; i+=2) {
+    for (int i = 0; i < FPURegister::kMaxNumRegisters; i+=2) {
       FPURegister reg = FPURegister::from_code(i);
       sdc1(reg, MemOperand(sp, i * kDoubleSize));
     }
@@ -4669,9 +4670,10 @@
                                     bool do_return) {
   // Optionally restore all double registers.
   if (save_doubles) {
+    CpuFeatures::Scope scope(FPU);
     // Remember: we only need to restore every 2nd double FPU value.
     lw(t8, MemOperand(fp, ExitFrameConstants::kSPOffset));
-    for (int i = 0; i < FPURegister::kNumRegisters; i+=2) {
+    for (int i = 0; i < FPURegister::kMaxNumRegisters; i+=2) {
       FPURegister reg = FPURegister::from_code(i);
       ldc1(reg, MemOperand(t8, i  * kDoubleSize + kPointerSize));
     }
@@ -5448,6 +5450,7 @@
 void MacroAssembler::TestJSArrayForAllocationSiteInfo(
     Register receiver_reg,
     Register scratch_reg,
+    Condition cond,
     Label* allocation_info_present) {
   Label no_info_available;
   ExternalReference new_space_start =
@@ -5461,7 +5464,7 @@
   lw(at, MemOperand(at));
   Branch(&no_info_available, gt, scratch_reg, Operand(at));
   lw(scratch_reg, MemOperand(scratch_reg, -AllocationSiteInfo::kSize));
-  Branch(allocation_info_present, eq, scratch_reg,
+  Branch(allocation_info_present, cond, scratch_reg,
       Operand(Handle<Map>(isolate()->heap()->allocation_site_info_map())));
   bind(&no_info_available);
 }
=======================================
--- /branches/bleeding_edge/src/mips/macro-assembler-mips.h Wed Jan 9 02:12:56 2013 +++ /branches/bleeding_edge/src/mips/macro-assembler-mips.h Wed Feb 13 06:01:22 2013
@@ -1448,6 +1448,7 @@
   // If allocation info is present, jump to allocation_info_present
   void TestJSArrayForAllocationSiteInfo(Register receiver_reg,
                                         Register scratch_reg,
+                                        Condition cond,
                                         Label* allocation_info_present);

  private:

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