| Index: src/ia32/stub-cache-ia32.cc
 | 
| diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
 | 
| index 783462714473d2a2d819c5d146d6e930e10073ed..c8695c572c8c6d8b4167c06f06cd5ae79c3547c5 100644
 | 
| --- a/src/ia32/stub-cache-ia32.cc
 | 
| +++ b/src/ia32/stub-cache-ia32.cc
 | 
| @@ -3398,17 +3398,9 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
 | 
|    // -----------------------------------
 | 
|  
 | 
|    ElementsKind elements_kind = receiver_map->elements_kind();
 | 
| -  if (receiver_map->has_fast_elements() ||
 | 
| -      receiver_map->has_external_array_elements()) {
 | 
| -    Handle<Code> stub = KeyedLoadFastElementStub(
 | 
| -        receiver_map->instance_type() == JS_ARRAY_TYPE,
 | 
| -        elements_kind).GetCode();
 | 
| -    __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
 | 
| -  } else {
 | 
| -    Handle<Code> stub =
 | 
| -        KeyedLoadDictionaryElementStub().GetCode();
 | 
| -    __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
 | 
| -  }
 | 
| +  Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode();
 | 
| +
 | 
| +  __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
 | 
|  
 | 
|    GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 | 
|  
 | 
| @@ -3669,6 +3661,157 @@ static void GenerateSmiKeyCheck(MacroAssembler* masm,
 | 
|  }
 | 
|  
 | 
|  
 | 
| +void KeyedLoadStubCompiler::GenerateLoadExternalArray(
 | 
| +    MacroAssembler* masm,
 | 
| +    ElementsKind elements_kind) {
 | 
| +  // ----------- S t a t e -------------
 | 
| +  //  -- ecx    : key
 | 
| +  //  -- edx    : receiver
 | 
| +  //  -- esp[0] : return address
 | 
| +  // -----------------------------------
 | 
| +  Label miss_force_generic, failed_allocation, slow;
 | 
| +
 | 
| +  // This stub is meant to be tail-jumped to, the receiver must already
 | 
| +  // have been verified by the caller to not be a smi.
 | 
| +
 | 
| +  // Check that the key is a smi or a heap number convertible to a smi.
 | 
| +  GenerateSmiKeyCheck(masm, ecx, eax, xmm0, xmm1, &miss_force_generic);
 | 
| +
 | 
| +  // Check that the index is in range.
 | 
| +  __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
 | 
| +  __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset));
 | 
| +  // Unsigned comparison catches both negative and too-large values.
 | 
| +  __ j(above_equal, &miss_force_generic);
 | 
| +  __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset));
 | 
| +  // ebx: base pointer of external storage
 | 
| +  switch (elements_kind) {
 | 
| +    case EXTERNAL_BYTE_ELEMENTS:
 | 
| +      __ SmiUntag(ecx);  // Untag the index.
 | 
| +      __ movsx_b(eax, Operand(ebx, ecx, times_1, 0));
 | 
| +      break;
 | 
| +    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
 | 
| +    case EXTERNAL_PIXEL_ELEMENTS:
 | 
| +      __ SmiUntag(ecx);  // Untag the index.
 | 
| +      __ movzx_b(eax, Operand(ebx, ecx, times_1, 0));
 | 
| +      break;
 | 
| +    case EXTERNAL_SHORT_ELEMENTS:
 | 
| +      __ movsx_w(eax, Operand(ebx, ecx, times_1, 0));
 | 
| +      break;
 | 
| +    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
 | 
| +      __ movzx_w(eax, Operand(ebx, ecx, times_1, 0));
 | 
| +      break;
 | 
| +    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
 | 
| +    case EXTERNAL_INT_ELEMENTS:
 | 
| +      __ mov(eax, Operand(ebx, ecx, times_2, 0));
 | 
| +      break;
 | 
| +    case EXTERNAL_FLOAT_ELEMENTS:
 | 
| +      __ fld_s(Operand(ebx, ecx, times_2, 0));
 | 
| +      break;
 | 
| +    case EXTERNAL_DOUBLE_ELEMENTS:
 | 
| +      __ fld_d(Operand(ebx, ecx, times_4, 0));
 | 
| +      break;
 | 
| +    default:
 | 
| +      UNREACHABLE();
 | 
| +      break;
 | 
| +  }
 | 
| +
 | 
| +  // For integer array types:
 | 
| +  // eax: value
 | 
| +  // For floating-point array type:
 | 
| +  // FP(0): value
 | 
| +
 | 
| +  if (elements_kind == EXTERNAL_INT_ELEMENTS ||
 | 
| +      elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
 | 
| +    // For the Int and UnsignedInt array types, we need to see whether
 | 
| +    // the value can be represented in a Smi. If not, we need to convert
 | 
| +    // it to a HeapNumber.
 | 
| +    Label box_int;
 | 
| +    if (elements_kind == EXTERNAL_INT_ELEMENTS) {
 | 
| +      __ cmp(eax, 0xc0000000);
 | 
| +      __ j(sign, &box_int);
 | 
| +    } else {
 | 
| +      ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind);
 | 
| +      // The test is different for unsigned int values. Since we need
 | 
| +      // the value to be in the range of a positive smi, we can't
 | 
| +      // handle either of the top two bits being set in the value.
 | 
| +      __ test(eax, Immediate(0xc0000000));
 | 
| +      __ j(not_zero, &box_int);
 | 
| +    }
 | 
| +
 | 
| +    __ SmiTag(eax);
 | 
| +    __ ret(0);
 | 
| +
 | 
| +    __ bind(&box_int);
 | 
| +
 | 
| +    // Allocate a HeapNumber for the int and perform int-to-double
 | 
| +    // conversion.
 | 
| +    if (elements_kind == EXTERNAL_INT_ELEMENTS) {
 | 
| +      __ push(eax);
 | 
| +      __ fild_s(Operand(esp, 0));
 | 
| +      __ pop(eax);
 | 
| +    } else {
 | 
| +      ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind);
 | 
| +      // Need to zero-extend the value.
 | 
| +      // There's no fild variant for unsigned values, so zero-extend
 | 
| +      // to a 64-bit int manually.
 | 
| +      __ push(Immediate(0));
 | 
| +      __ push(eax);
 | 
| +      __ fild_d(Operand(esp, 0));
 | 
| +      __ pop(eax);
 | 
| +      __ pop(eax);
 | 
| +    }
 | 
| +    // FP(0): value
 | 
| +    __ AllocateHeapNumber(eax, ebx, edi, &failed_allocation);
 | 
| +    // Set the value.
 | 
| +    __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
 | 
| +    __ ret(0);
 | 
| +  } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
 | 
| +             elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
 | 
| +    // For the floating-point array type, we need to always allocate a
 | 
| +    // HeapNumber.
 | 
| +    __ AllocateHeapNumber(eax, ebx, edi, &failed_allocation);
 | 
| +    // Set the value.
 | 
| +    __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
 | 
| +    __ ret(0);
 | 
| +  } else {
 | 
| +    __ SmiTag(eax);
 | 
| +    __ ret(0);
 | 
| +  }
 | 
| +
 | 
| +  // If we fail allocation of the HeapNumber, we still have a value on
 | 
| +  // top of the FPU stack. Remove it.
 | 
| +  __ bind(&failed_allocation);
 | 
| +  __ fstp(0);
 | 
| +  // Fall through to slow case.
 | 
| +
 | 
| +  // Slow case: Jump to runtime.
 | 
| +  __ bind(&slow);
 | 
| +  Counters* counters = masm->isolate()->counters();
 | 
| +  __ IncrementCounter(counters->keyed_load_external_array_slow(), 1);
 | 
| +
 | 
| +  // ----------- S t a t e -------------
 | 
| +  //  -- ecx    : key
 | 
| +  //  -- edx    : receiver
 | 
| +  //  -- esp[0] : return address
 | 
| +  // -----------------------------------
 | 
| +
 | 
| +  Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow();
 | 
| +  __ jmp(ic, RelocInfo::CODE_TARGET);
 | 
| +
 | 
| +  // ----------- S t a t e -------------
 | 
| +  //  -- ecx    : key
 | 
| +  //  -- edx    : receiver
 | 
| +  //  -- esp[0] : return address
 | 
| +  // -----------------------------------
 | 
| +
 | 
| +  // Miss case: Jump to runtime.
 | 
| +  __ bind(&miss_force_generic);
 | 
| +  Handle<Code> miss_ic =
 | 
| +      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
 | 
| +  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void KeyedStoreStubCompiler::GenerateStoreExternalArray(
 | 
|      MacroAssembler* masm,
 | 
|      ElementsKind elements_kind) {
 | 
| @@ -3868,6 +4011,106 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
 | 
|  }
 | 
|  
 | 
|  
 | 
| +void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
 | 
| +  // ----------- S t a t e -------------
 | 
| +  //  -- ecx    : key
 | 
| +  //  -- edx    : receiver
 | 
| +  //  -- esp[0] : return address
 | 
| +  // -----------------------------------
 | 
| +  Label miss_force_generic;
 | 
| +
 | 
| +  // This stub is meant to be tail-jumped to, the receiver must already
 | 
| +  // have been verified by the caller to not be a smi.
 | 
| +
 | 
| +  // Check that the key is a smi or a heap number convertible to a smi.
 | 
| +  GenerateSmiKeyCheck(masm, ecx, eax, xmm0, xmm1, &miss_force_generic);
 | 
| +
 | 
| +  // Get the elements array.
 | 
| +  __ mov(eax, FieldOperand(edx, JSObject::kElementsOffset));
 | 
| +  __ AssertFastElements(eax);
 | 
| +
 | 
| +  // Check that the key is within bounds.
 | 
| +  __ cmp(ecx, FieldOperand(eax, FixedArray::kLengthOffset));
 | 
| +  __ j(above_equal, &miss_force_generic);
 | 
| +
 | 
| +  // Load the result and make sure it's not the hole.
 | 
| +  __ mov(ebx, Operand(eax, ecx, times_2,
 | 
| +                      FixedArray::kHeaderSize - kHeapObjectTag));
 | 
| +  __ cmp(ebx, masm->isolate()->factory()->the_hole_value());
 | 
| +  __ j(equal, &miss_force_generic);
 | 
| +  __ mov(eax, ebx);
 | 
| +  __ ret(0);
 | 
| +
 | 
| +  __ bind(&miss_force_generic);
 | 
| +  Handle<Code> miss_ic =
 | 
| +      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
 | 
| +  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
 | 
| +    MacroAssembler* masm) {
 | 
| +  // ----------- S t a t e -------------
 | 
| +  //  -- ecx    : key
 | 
| +  //  -- edx    : receiver
 | 
| +  //  -- esp[0] : return address
 | 
| +  // -----------------------------------
 | 
| +  Label miss_force_generic, slow_allocate_heapnumber;
 | 
| +
 | 
| +  // This stub is meant to be tail-jumped to, the receiver must already
 | 
| +  // have been verified by the caller to not be a smi.
 | 
| +
 | 
| +  // Check that the key is a smi or a heap number convertible to a smi.
 | 
| +  GenerateSmiKeyCheck(masm, ecx, eax, xmm0, xmm1, &miss_force_generic);
 | 
| +
 | 
| +  // Get the elements array.
 | 
| +  __ mov(eax, FieldOperand(edx, JSObject::kElementsOffset));
 | 
| +  __ AssertFastElements(eax);
 | 
| +
 | 
| +  // Check that the key is within bounds.
 | 
| +  __ cmp(ecx, FieldOperand(eax, FixedDoubleArray::kLengthOffset));
 | 
| +  __ j(above_equal, &miss_force_generic);
 | 
| +
 | 
| +  // Check for the hole
 | 
| +  uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
 | 
| +  __ cmp(FieldOperand(eax, ecx, times_4, offset), Immediate(kHoleNanUpper32));
 | 
| +  __ j(equal, &miss_force_generic);
 | 
| +
 | 
| +  // Always allocate a heap number for the result.
 | 
| +  if (CpuFeatures::IsSupported(SSE2)) {
 | 
| +    CpuFeatures::Scope use_sse2(SSE2);
 | 
| +    __ movdbl(xmm0, FieldOperand(eax, ecx, times_4,
 | 
| +                                 FixedDoubleArray::kHeaderSize));
 | 
| +  } else {
 | 
| +    __ fld_d(FieldOperand(eax, ecx, times_4, FixedDoubleArray::kHeaderSize));
 | 
| +  }
 | 
| +  __ AllocateHeapNumber(eax, ebx, edi, &slow_allocate_heapnumber);
 | 
| +  // Set the value.
 | 
| +  if (CpuFeatures::IsSupported(SSE2)) {
 | 
| +    CpuFeatures::Scope use_sse2(SSE2);
 | 
| +    __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
 | 
| +  } else {
 | 
| +    __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
 | 
| +  }
 | 
| +  __ ret(0);
 | 
| +
 | 
| +  __ bind(&slow_allocate_heapnumber);
 | 
| +  // A value was pushed on the floating point stack before the allocation, if
 | 
| +  // the allocation fails it needs to be removed.
 | 
| +  if (!CpuFeatures::IsSupported(SSE2)) {
 | 
| +    __ fstp(0);
 | 
| +  }
 | 
| +  Handle<Code> slow_ic =
 | 
| +      masm->isolate()->builtins()->KeyedLoadIC_Slow();
 | 
| +  __ jmp(slow_ic, RelocInfo::CODE_TARGET);
 | 
| +
 | 
| +  __ bind(&miss_force_generic);
 | 
| +  Handle<Code> miss_ic =
 | 
| +      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
 | 
| +  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void KeyedStoreStubCompiler::GenerateStoreFastElement(
 | 
|      MacroAssembler* masm,
 | 
|      bool is_js_array,
 | 
| 
 |