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