| Index: src/ia32/ic-ia32.cc
|
| diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
|
| index f8e4ea53d0f78cb32f63e86b30343f85c857f42c..97445d01f27424839b8c8ef669cee5a15c891c7f 100644
|
| --- a/src/ia32/ic-ia32.cc
|
| +++ b/src/ia32/ic-ia32.cc
|
| @@ -711,6 +711,34 @@ void KeyedStoreIC::GenerateNonStrictArguments(MacroAssembler* masm) {
|
| }
|
|
|
|
|
| +static void HasElementCallbacksInPrototypeChain(
|
| + MacroAssembler* masm,
|
| + Label* found) {
|
| + Factory* factory = masm->isolate()->factory();
|
| + Label loop, not_found;
|
| +
|
| + // ebx contained elements pointer.
|
| + __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
|
| +
|
| + // Loop based on the map going up the prototype chain.
|
| + __ bind(&loop);
|
| + __ test(FieldOperand(ebx, Map::kBitField4Offset),
|
| + Immediate(Smi::FromInt(Map::HasElementCallbacks::kMask)));
|
| + __ j(not_zero, found);
|
| +
|
| + // Next map
|
| + __ mov(ebx, FieldOperand(ebx, Map::kPrototypeOffset));
|
| + __ cmp(ebx, Immediate(factory->null_value()));
|
| + __ j(equal, ¬_found);
|
| + __ mov(ebx, FieldOperand(ebx, HeapObject::kMapOffset));
|
| + __ jmp(&loop);
|
| +
|
| + // Restore ebx
|
| + __ bind(¬_found);
|
| + __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
|
| +}
|
| +
|
| +
|
| static void KeyedStoreGenerateGenericHelper(
|
| MacroAssembler* masm,
|
| Label* fast_object,
|
| @@ -733,9 +761,22 @@ static void KeyedStoreGenerateGenericHelper(
|
| __ cmp(edi, masm->isolate()->factory()->fixed_array_map());
|
| __ j(not_equal, fast_double);
|
| }
|
| +
|
| + // HOLECHECK: guards "A[i] = V"
|
| + // We have to go to the runtime if the current value is undefined because
|
| + // there may be a callback on the element
|
| + Label holecheck_passed1;
|
| + __ cmp(CodeGenerator::FixedArrayElementOperand(ebx, ecx),
|
| + masm->isolate()->factory()->the_hole_value());
|
| + __ j(not_equal, &holecheck_passed1);
|
| + HasElementCallbacksInPrototypeChain(masm, slow);
|
| +
|
| + __ bind(&holecheck_passed1);
|
| +
|
| // Smi stores don't require further checks.
|
| Label non_smi_value;
|
| __ JumpIfNotSmi(eax, &non_smi_value);
|
| +
|
| if (increment_length == kIncrementLength) {
|
| // Add 1 to receiver->length.
|
| __ add(FieldOperand(edx, JSArray::kLengthOffset),
|
| @@ -773,6 +814,15 @@ static void KeyedStoreGenerateGenericHelper(
|
| // If the value is a number, store it as a double in the FastDoubleElements
|
| // array.
|
| }
|
| +
|
| + // HOLECHECK: guards "A[i] double hole?"
|
| + // We have to see if the double version of the hole is present. If so
|
| + // go to the runtime.
|
| + uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
|
| + __ cmp(FieldOperand(ebx, ecx, times_4, offset), Immediate(kHoleNanUpper32));
|
| + __ j(not_equal, &fast_double_without_map_check);
|
| + HasElementCallbacksInPrototypeChain(masm, slow);
|
| +
|
| __ bind(&fast_double_without_map_check);
|
| __ StoreNumberToDoubleElements(eax, ebx, ecx, edi, xmm0,
|
| &transition_double_elements, false);
|
| @@ -794,6 +844,7 @@ static void KeyedStoreGenerateGenericHelper(
|
|
|
| // Value is a double. Transition FAST_SMI_ELEMENTS -> FAST_DOUBLE_ELEMENTS
|
| // and complete the store.
|
| +
|
| __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
|
| FAST_DOUBLE_ELEMENTS,
|
| ebx,
|
| @@ -806,6 +857,7 @@ static void KeyedStoreGenerateGenericHelper(
|
| __ jmp(&fast_double_without_map_check);
|
|
|
| __ bind(&non_double_value);
|
| +
|
| // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS
|
| __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
|
| FAST_ELEMENTS,
|
|
|