| Index: src/ia32/code-stubs-ia32.cc
|
| diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
|
| index fe1641c374bc769d2bbb1bde13d2b6a5e2ec1e56..569f7e36ca791a8fff4405dcfe0f2e6a14844516 100644
|
| --- a/src/ia32/code-stubs-ia32.cc
|
| +++ b/src/ia32/code-stubs-ia32.cc
|
| @@ -7040,6 +7040,32 @@ void FastElementsConversionStub::GenerateSmiOnlyToObject(MacroAssembler* masm) {
|
| kDontSaveFPRegs,
|
| EMIT_REMEMBERED_SET,
|
| OMIT_SMI_CHECK);
|
| +
|
| + if (FLAG_trace_element_transitions) {
|
| + // Save registers and make sure return address is on top.
|
| + __ pop(esi);
|
| + __ push(eax);
|
| + __ push(ebx);
|
| + __ push(ecx);
|
| + __ push(edx);
|
| + __ push(esi);
|
| + {
|
| + FrameScope scope(masm, StackFrame::INTERNAL);
|
| + __ push(edx);
|
| + __ push(Immediate(FAST_SMI_ONLY_ELEMENTS << kSmiTagSize));
|
| + __ push(FieldOperand(edx, JSObject::kElementsOffset));
|
| + __ push(Immediate(FAST_ELEMENTS << kSmiTagSize));
|
| + __ push(FieldOperand(edx, JSObject::kElementsOffset));
|
| + __ CallRuntime(Runtime::kTraceElementsKindTransition, 5);
|
| + }
|
| + // Restore registers and make sure return address is on top.
|
| + __ pop(esi);
|
| + __ pop(edx);
|
| + __ pop(ecx);
|
| + __ pop(ebx);
|
| + __ pop(eax);
|
| + __ push(esi);
|
| + }
|
| }
|
|
|
|
|
| @@ -7053,6 +7079,8 @@ void FastElementsConversionStub::GenerateSmiOnlyToDouble(
|
| // -- esp[0] : return address
|
| // -----------------------------------
|
| Label loop, entry, convert_hole, gc_required;
|
| + // Make sure to change the following when pushing more values on the stack.
|
| + static int registers_already_on_stack = 2;
|
| __ push(eax);
|
| __ push(ebx);
|
|
|
| @@ -7085,6 +7113,44 @@ void FastElementsConversionStub::GenerateSmiOnlyToDouble(
|
|
|
| __ mov(edi, FieldOperand(esi, FixedArray::kLengthOffset));
|
|
|
| + if (FLAG_trace_element_transitions) {
|
| + static int registers_to_save = 6;
|
| + // Swizzle the stack so that all registers are saved below the return
|
| + // address, which must be at the top of stack when calling out.
|
| + int registers_slot_for_return_address =
|
| + registers_to_save + registers_already_on_stack;
|
| + __ sub(esp, Immediate(registers_to_save * kPointerSize));
|
| + __ mov(Operand(esp, 5 * kPointerSize), ebx);
|
| + __ mov(Operand(esp, 4 * kPointerSize), ecx);
|
| + __ mov(Operand(esp, 3 * kPointerSize), edx);
|
| + __ mov(Operand(esp, 2 * kPointerSize), esi);
|
| + __ mov(Operand(esp, 1 * kPointerSize), edi);
|
| + __ mov(ebx, Operand(esp, registers_slot_for_return_address * kPointerSize));
|
| + __ mov(Operand(esp, 0), ebx);
|
| + __ mov(Operand(esp, registers_slot_for_return_address * kPointerSize), eax);
|
| + {
|
| + FrameScope scope(masm, StackFrame::INTERNAL);
|
| + __ push(edx);
|
| + __ push(Immediate(FAST_SMI_ONLY_ELEMENTS << kSmiTagSize));
|
| + __ push(esi);
|
| + __ push(Immediate(FAST_DOUBLE_ELEMENTS << kSmiTagSize));
|
| + __ push(eax);
|
| + __ CallRuntime(Runtime::kTraceElementsKindTransition, 5);
|
| + }
|
| + // Restore all the registers that were saved before the internal frame scope
|
| + // was created, ensuring that the return address remains on the top of
|
| + // stack.
|
| + __ mov(eax, Operand(esp, registers_slot_for_return_address * kPointerSize));
|
| + __ mov(ebx, Operand(esp, 0));
|
| + __ mov(Operand(esp, registers_slot_for_return_address * kPointerSize), ebx);
|
| + __ mov(ebx, Operand(esp, 5 * kPointerSize));
|
| + __ mov(ecx, Operand(esp, 4 * kPointerSize));
|
| + __ mov(edx, Operand(esp, 3 * kPointerSize));
|
| + __ mov(esi, Operand(esp, 2 * kPointerSize));
|
| + __ mov(edi, Operand(esp, 1 * kPointerSize));
|
| + __ add(esp, Immediate(registers_to_save * kPointerSize));
|
| + }
|
| +
|
| // Prepare for conversion loop.
|
| ExternalReference canonical_the_hole_nan_reference =
|
| ExternalReference::address_of_the_hole_nan();
|
| @@ -7257,6 +7323,42 @@ void FastElementsConversionStub::GenerateDoubleToObject(
|
| kDontSaveFPRegs,
|
| EMIT_REMEMBERED_SET,
|
| OMIT_SMI_CHECK);
|
| +
|
| + if (FLAG_trace_element_transitions) {
|
| + static int registers_already_on_stack = 1;
|
| + static int registers_to_save = 4;
|
| + // Swizzle the stack so that all registers are saved below the return
|
| + // address, which must be at the top of stack when calling out.
|
| + int registers_slot_for_return_address =
|
| + registers_to_save + registers_already_on_stack;
|
| + __ sub(esp, Immediate(registers_to_save * kPointerSize));
|
| + __ mov(Operand(esp, 3 * kPointerSize), edx);
|
| + __ mov(Operand(esp, 2 * kPointerSize), ecx);
|
| + __ mov(Operand(esp, 1 * kPointerSize), ebx);
|
| + __ mov(ebx, Operand(esp, registers_slot_for_return_address * kPointerSize));
|
| + __ mov(Operand(esp, 0), ebx);
|
| + __ mov(Operand(esp, registers_slot_for_return_address * kPointerSize), eax);
|
| + {
|
| + FrameScope scope(masm, StackFrame::INTERNAL);
|
| + __ push(edx);
|
| + __ push(Immediate(FAST_DOUBLE_ELEMENTS << kSmiTagSize));
|
| + __ push(FieldOperand(edx, JSObject::kElementsOffset));
|
| + __ push(Immediate(FAST_ELEMENTS << kSmiTagSize));
|
| + __ push(eax);
|
| + __ CallRuntime(Runtime::kTraceElementsKindTransition, 5);
|
| + }
|
| + // Restore all the registers that were saved before the internal frame scope
|
| + // was created, ensuring that the return address remains on the top of
|
| + // stack.
|
| + __ mov(eax, Operand(esp, registers_slot_for_return_address * kPointerSize));
|
| + __ mov(ebx, Operand(esp, 0));
|
| + __ mov(Operand(esp, registers_slot_for_return_address * kPointerSize), ebx);
|
| + __ mov(edx, Operand(esp, 3 * kPointerSize));
|
| + __ mov(ecx, Operand(esp, 2 * kPointerSize));
|
| + __ mov(ebx, Operand(esp, 1 * kPointerSize));
|
| + __ add(esp, Immediate(registers_to_save * kPointerSize));
|
| + }
|
| +
|
| // Replace receiver's backing store with newly created and filled FixedArray.
|
| __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax);
|
| __ RecordWriteField(edx,
|
|
|