| Index: src/x87/code-stubs-x87.cc
 | 
| diff --git a/src/x87/code-stubs-x87.cc b/src/x87/code-stubs-x87.cc
 | 
| index 0ea919d3b1b0711f2946ff74db1f2e89eca34193..c7abc54cad155d432887ddd6217515d05d82d213 100644
 | 
| --- a/src/x87/code-stubs-x87.cc
 | 
| +++ b/src/x87/code-stubs-x87.cc
 | 
| @@ -2834,328 +2834,6 @@ void StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
 | 
|    __ jmp(ecx);  // Return to IC Miss stub, continuation still on stack.
 | 
|  }
 | 
|  
 | 
| -void KeyedStoreICTrampolineStub::Generate(MacroAssembler* masm) {
 | 
| -  __ EmitLoadTypeFeedbackVector(StoreWithVectorDescriptor::VectorRegister());
 | 
| -  KeyedStoreICStub stub(isolate(), state());
 | 
| -  stub.GenerateForTrampoline(masm);
 | 
| -}
 | 
| -
 | 
| -// value is on the stack already.
 | 
| -static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register receiver,
 | 
| -                                       Register key, Register vector,
 | 
| -                                       Register slot, Register feedback,
 | 
| -                                       bool is_polymorphic, Label* miss) {
 | 
| -  // feedback initially contains the feedback array
 | 
| -  Label next, next_loop, prepare_next;
 | 
| -  Label load_smi_map, compare_map;
 | 
| -  Label start_polymorphic;
 | 
| -  Label pop_and_miss;
 | 
| -
 | 
| -  __ push(receiver);
 | 
| -  // Value, vector and slot are passed on the stack, so no need to save/restore
 | 
| -  // them.
 | 
| -
 | 
| -  Register receiver_map = receiver;
 | 
| -  Register cached_map = vector;
 | 
| -
 | 
| -  // Receiver might not be a heap object.
 | 
| -  __ JumpIfSmi(receiver, &load_smi_map);
 | 
| -  __ mov(receiver_map, FieldOperand(receiver, 0));
 | 
| -  __ bind(&compare_map);
 | 
| -  __ mov(cached_map, FieldOperand(feedback, FixedArray::OffsetOfElementAt(0)));
 | 
| -
 | 
| -  // A named keyed store might have a 2 element array, all other cases can count
 | 
| -  // on an array with at least 2 {map, handler} pairs, so they can go right
 | 
| -  // into polymorphic array handling.
 | 
| -  __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset));
 | 
| -  __ j(not_equal, &start_polymorphic);
 | 
| -
 | 
| -  // found, now call handler.
 | 
| -  Register handler = feedback;
 | 
| -  DCHECK(handler.is(StoreWithVectorDescriptor::ValueRegister()));
 | 
| -  __ mov(handler, FieldOperand(feedback, FixedArray::OffsetOfElementAt(1)));
 | 
| -  __ pop(receiver);
 | 
| -  __ lea(handler, FieldOperand(handler, Code::kHeaderSize));
 | 
| -  __ jmp(handler);
 | 
| -
 | 
| -  // Polymorphic, we have to loop from 2 to N
 | 
| -  __ bind(&start_polymorphic);
 | 
| -  __ push(key);
 | 
| -  Register counter = key;
 | 
| -  __ mov(counter, Immediate(Smi::FromInt(2)));
 | 
| -
 | 
| -  if (!is_polymorphic) {
 | 
| -    // If is_polymorphic is false, we may only have a two element array.
 | 
| -    // Check against length now in that case.
 | 
| -    __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset));
 | 
| -    __ j(greater_equal, &pop_and_miss);
 | 
| -  }
 | 
| -
 | 
| -  __ bind(&next_loop);
 | 
| -  __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size,
 | 
| -                                  FixedArray::kHeaderSize));
 | 
| -  __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset));
 | 
| -  __ j(not_equal, &prepare_next);
 | 
| -  __ mov(handler, FieldOperand(feedback, counter, times_half_pointer_size,
 | 
| -                               FixedArray::kHeaderSize + kPointerSize));
 | 
| -  __ lea(handler, FieldOperand(handler, Code::kHeaderSize));
 | 
| -  __ pop(key);
 | 
| -  __ pop(receiver);
 | 
| -  __ jmp(handler);
 | 
| -
 | 
| -  __ bind(&prepare_next);
 | 
| -  __ add(counter, Immediate(Smi::FromInt(2)));
 | 
| -  __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset));
 | 
| -  __ j(less, &next_loop);
 | 
| -
 | 
| -  // We exhausted our array of map handler pairs.
 | 
| -  __ bind(&pop_and_miss);
 | 
| -  __ pop(key);
 | 
| -  __ pop(receiver);
 | 
| -  __ jmp(miss);
 | 
| -
 | 
| -  __ bind(&load_smi_map);
 | 
| -  __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex);
 | 
| -  __ jmp(&compare_map);
 | 
| -}
 | 
| -
 | 
| -
 | 
| -static void HandleMonomorphicStoreCase(MacroAssembler* masm, Register receiver,
 | 
| -                                       Register key, Register vector,
 | 
| -                                       Register slot, Register weak_cell,
 | 
| -                                       Label* miss) {
 | 
| -  // The store ic value is on the stack.
 | 
| -  DCHECK(weak_cell.is(StoreWithVectorDescriptor::ValueRegister()));
 | 
| -
 | 
| -  // feedback initially contains the feedback array
 | 
| -  Label compare_smi_map;
 | 
| -
 | 
| -  // Move the weak map into the weak_cell register.
 | 
| -  Register ic_map = weak_cell;
 | 
| -  __ mov(ic_map, FieldOperand(weak_cell, WeakCell::kValueOffset));
 | 
| -
 | 
| -  // Receiver might not be a heap object.
 | 
| -  __ JumpIfSmi(receiver, &compare_smi_map);
 | 
| -  __ cmp(ic_map, FieldOperand(receiver, 0));
 | 
| -  __ j(not_equal, miss);
 | 
| -  __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size,
 | 
| -                                 FixedArray::kHeaderSize + kPointerSize));
 | 
| -  __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize));
 | 
| -  // jump to the handler.
 | 
| -  __ jmp(weak_cell);
 | 
| -
 | 
| -  // In microbenchmarks, it made sense to unroll this code so that the call to
 | 
| -  // the handler is duplicated for a HeapObject receiver and a Smi receiver.
 | 
| -  __ bind(&compare_smi_map);
 | 
| -  __ CompareRoot(ic_map, Heap::kHeapNumberMapRootIndex);
 | 
| -  __ j(not_equal, miss);
 | 
| -  __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size,
 | 
| -                                 FixedArray::kHeaderSize + kPointerSize));
 | 
| -  __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize));
 | 
| -  // jump to the handler.
 | 
| -  __ jmp(weak_cell);
 | 
| -}
 | 
| -
 | 
| -void KeyedStoreICStub::Generate(MacroAssembler* masm) {
 | 
| -  GenerateImpl(masm, false);
 | 
| -}
 | 
| -
 | 
| -void KeyedStoreICStub::GenerateForTrampoline(MacroAssembler* masm) {
 | 
| -  GenerateImpl(masm, true);
 | 
| -}
 | 
| -
 | 
| -
 | 
| -static void HandlePolymorphicKeyedStoreCase(MacroAssembler* masm,
 | 
| -                                            Register receiver, Register key,
 | 
| -                                            Register vector, Register slot,
 | 
| -                                            Register feedback, Label* miss) {
 | 
| -  // feedback initially contains the feedback array
 | 
| -  Label next, next_loop, prepare_next;
 | 
| -  Label load_smi_map, compare_map;
 | 
| -  Label transition_call;
 | 
| -  Label pop_and_miss;
 | 
| -
 | 
| -  __ push(receiver);
 | 
| -  // Value, vector and slot are passed on the stack, so no need to save/restore
 | 
| -  // them.
 | 
| -
 | 
| -  Register receiver_map = receiver;
 | 
| -  Register cached_map = vector;
 | 
| -
 | 
| -  // Receiver might not be a heap object.
 | 
| -  __ JumpIfSmi(receiver, &load_smi_map);
 | 
| -  __ mov(receiver_map, FieldOperand(receiver, 0));
 | 
| -  __ bind(&compare_map);
 | 
| -
 | 
| -  // Polymorphic, we have to loop from 0 to N - 1
 | 
| -  __ push(key);
 | 
| -  // Current stack layout:
 | 
| -  // - esp[0]    -- key
 | 
| -  // - esp[4]    -- receiver
 | 
| -  // - esp[8]    -- return address
 | 
| -  // - esp[12]   -- vector
 | 
| -  // - esp[16]   -- slot
 | 
| -  // - esp[20]   -- value
 | 
| -  //
 | 
| -  // Required stack layout for handler call (see StoreWithVectorDescriptor):
 | 
| -  // - esp[0]    -- return address
 | 
| -  // - esp[4]    -- vector
 | 
| -  // - esp[8]    -- slot
 | 
| -  // - esp[12]   -- value
 | 
| -  // - receiver, key, handler in registers.
 | 
| -  Register counter = key;
 | 
| -  __ mov(counter, Immediate(Smi::kZero));
 | 
| -  __ bind(&next_loop);
 | 
| -  __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size,
 | 
| -                                  FixedArray::kHeaderSize));
 | 
| -  __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset));
 | 
| -  __ j(not_equal, &prepare_next);
 | 
| -  __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size,
 | 
| -                                  FixedArray::kHeaderSize + kPointerSize));
 | 
| -  __ CompareRoot(cached_map, Heap::kUndefinedValueRootIndex);
 | 
| -  __ j(not_equal, &transition_call);
 | 
| -  __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size,
 | 
| -                                FixedArray::kHeaderSize + 2 * kPointerSize));
 | 
| -  __ pop(key);
 | 
| -  __ pop(receiver);
 | 
| -  __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize));
 | 
| -  __ jmp(feedback);
 | 
| -
 | 
| -  __ bind(&transition_call);
 | 
| -  // Current stack layout:
 | 
| -  // - esp[0]    -- key
 | 
| -  // - esp[4]    -- receiver
 | 
| -  // - esp[8]    -- return address
 | 
| -  // - esp[12]   -- vector
 | 
| -  // - esp[16]   -- slot
 | 
| -  // - esp[20]   -- value
 | 
| -  //
 | 
| -  // Required stack layout for handler call (see StoreTransitionDescriptor):
 | 
| -  // - esp[0]    -- return address
 | 
| -  // - esp[4]    -- vector
 | 
| -  // - esp[8]    -- slot
 | 
| -  // - esp[12]   -- value
 | 
| -  // - receiver, key, map, handler in registers.
 | 
| -  __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size,
 | 
| -                                FixedArray::kHeaderSize + 2 * kPointerSize));
 | 
| -  __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize));
 | 
| -
 | 
| -  __ mov(cached_map, FieldOperand(cached_map, WeakCell::kValueOffset));
 | 
| -  // The weak cell may have been cleared.
 | 
| -  __ JumpIfSmi(cached_map, &pop_and_miss);
 | 
| -  DCHECK(!cached_map.is(StoreTransitionDescriptor::MapRegister()));
 | 
| -  __ mov(StoreTransitionDescriptor::MapRegister(), cached_map);
 | 
| -
 | 
| -  // Call store transition handler using StoreTransitionDescriptor calling
 | 
| -  // convention.
 | 
| -  __ pop(key);
 | 
| -  __ pop(receiver);
 | 
| -  // Ensure that the transition handler we are going to call has the same
 | 
| -  // number of stack arguments which means that we don't have to adapt them
 | 
| -  // before the call.
 | 
| -  STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3);
 | 
| -  STATIC_ASSERT(StoreTransitionDescriptor::kStackArgumentsCount == 3);
 | 
| -  STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount -
 | 
| -                    StoreWithVectorDescriptor::kValue ==
 | 
| -                StoreTransitionDescriptor::kParameterCount -
 | 
| -                    StoreTransitionDescriptor::kValue);
 | 
| -  STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount -
 | 
| -                    StoreWithVectorDescriptor::kSlot ==
 | 
| -                StoreTransitionDescriptor::kParameterCount -
 | 
| -                    StoreTransitionDescriptor::kSlot);
 | 
| -  STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount -
 | 
| -                    StoreWithVectorDescriptor::kVector ==
 | 
| -                StoreTransitionDescriptor::kParameterCount -
 | 
| -                    StoreTransitionDescriptor::kVector);
 | 
| -  __ jmp(feedback);
 | 
| -
 | 
| -  __ bind(&prepare_next);
 | 
| -  __ add(counter, Immediate(Smi::FromInt(3)));
 | 
| -  __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset));
 | 
| -  __ j(less, &next_loop);
 | 
| -
 | 
| -  // We exhausted our array of map handler pairs.
 | 
| -  __ bind(&pop_and_miss);
 | 
| -  __ pop(key);
 | 
| -  __ pop(receiver);
 | 
| -  __ jmp(miss);
 | 
| -
 | 
| -  __ bind(&load_smi_map);
 | 
| -  __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex);
 | 
| -  __ jmp(&compare_map);
 | 
| -}
 | 
| -
 | 
| -void KeyedStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
 | 
| -  Register receiver = StoreWithVectorDescriptor::ReceiverRegister();  // edx
 | 
| -  Register key = StoreWithVectorDescriptor::NameRegister();           // ecx
 | 
| -  Register value = StoreWithVectorDescriptor::ValueRegister();        // eax
 | 
| -  Register vector = StoreWithVectorDescriptor::VectorRegister();      // ebx
 | 
| -  Register slot = StoreWithVectorDescriptor::SlotRegister();          // edi
 | 
| -  Label miss;
 | 
| -
 | 
| -  if (StoreWithVectorDescriptor::kPassLastArgsOnStack) {
 | 
| -    // Current stack layout:
 | 
| -    // - esp[8]    -- value
 | 
| -    // - esp[4]    -- slot
 | 
| -    // - esp[0]    -- return address
 | 
| -    STATIC_ASSERT(StoreDescriptor::kStackArgumentsCount == 2);
 | 
| -    STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3);
 | 
| -    if (in_frame) {
 | 
| -      __ RecordComment("[ StoreDescriptor -> StoreWithVectorDescriptor");
 | 
| -      // If the vector is not on the stack, then insert the vector beneath
 | 
| -      // return address in order to prepare for calling handler with
 | 
| -      // StoreWithVector calling convention.
 | 
| -      __ push(Operand(esp, 0));
 | 
| -      __ mov(Operand(esp, 4), StoreWithVectorDescriptor::VectorRegister());
 | 
| -      __ RecordComment("]");
 | 
| -    } else {
 | 
| -      __ mov(vector, Operand(esp, 1 * kPointerSize));
 | 
| -    }
 | 
| -    __ mov(slot, Operand(esp, 2 * kPointerSize));
 | 
| -  }
 | 
| -
 | 
| -  Register scratch = value;
 | 
| -  __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size,
 | 
| -                               FixedArray::kHeaderSize));
 | 
| -
 | 
| -  // Is it a weak cell?
 | 
| -  Label try_array;
 | 
| -  Label not_array, smi_key, key_okay;
 | 
| -  __ CompareRoot(FieldOperand(scratch, 0), Heap::kWeakCellMapRootIndex);
 | 
| -  __ j(not_equal, &try_array);
 | 
| -  HandleMonomorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss);
 | 
| -
 | 
| -  // Is it a fixed array?
 | 
| -  __ bind(&try_array);
 | 
| -  __ CompareRoot(FieldOperand(scratch, 0), Heap::kFixedArrayMapRootIndex);
 | 
| -  __ j(not_equal, ¬_array);
 | 
| -  HandlePolymorphicKeyedStoreCase(masm, receiver, key, vector, slot, scratch,
 | 
| -                                  &miss);
 | 
| -
 | 
| -  __ bind(¬_array);
 | 
| -  Label try_poly_name;
 | 
| -  __ CompareRoot(scratch, Heap::kmegamorphic_symbolRootIndex);
 | 
| -  __ j(not_equal, &try_poly_name);
 | 
| -
 | 
| -  Handle<Code> megamorphic_stub =
 | 
| -      KeyedStoreIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState());
 | 
| -  __ jmp(megamorphic_stub, RelocInfo::CODE_TARGET);
 | 
| -
 | 
| -  __ bind(&try_poly_name);
 | 
| -  // We might have a name in feedback, and a fixed array in the next slot.
 | 
| -  __ cmp(key, scratch);
 | 
| -  __ j(not_equal, &miss);
 | 
| -  // If the name comparison succeeded, we know we have a fixed array with
 | 
| -  // at least one map/handler pair.
 | 
| -  __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size,
 | 
| -                               FixedArray::kHeaderSize + kPointerSize));
 | 
| -  HandlePolymorphicStoreCase(masm, receiver, key, vector, slot, scratch, false,
 | 
| -                             &miss);
 | 
| -
 | 
| -  __ bind(&miss);
 | 
| -  KeyedStoreIC::GenerateMiss(masm);
 | 
| -}
 | 
| -
 | 
|  void CallICTrampolineStub::Generate(MacroAssembler* masm) {
 | 
|    __ EmitLoadTypeFeedbackVector(ebx);
 | 
|    CallICStub stub(isolate(), state());
 | 
| 
 |