165a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
793a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_IA32
89dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
9196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/codegen.h"
103e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org#include "src/heap/heap.h"
11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/macro-assembler.h"
1243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace v8 {
1471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace internal {
1543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1630ce411529579186181838984710b0b0980857aaricow@chromium.org
1730ce411529579186181838984710b0b0980857aaricow@chromium.org// -------------------------------------------------------------------------
1830ce411529579186181838984710b0b0980857aaricow@chromium.org// Platform-specific RuntimeCallHelper functions.
1930ce411529579186181838984710b0b0980857aaricow@chromium.org
20a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const {
21c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  masm->EnterFrame(StackFrame::INTERNAL);
22e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!masm->has_frame());
23c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  masm->set_has_frame(true);
2430ce411529579186181838984710b0b0980857aaricow@chromium.org}
2530ce411529579186181838984710b0b0980857aaricow@chromium.org
2630ce411529579186181838984710b0b0980857aaricow@chromium.org
27a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const {
28c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  masm->LeaveFrame(StackFrame::INTERNAL);
29e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(masm->has_frame());
30c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  masm->set_has_frame(false);
3130ce411529579186181838984710b0b0980857aaricow@chromium.org}
3230ce411529579186181838984710b0b0980857aaricow@chromium.org
3330ce411529579186181838984710b0b0980857aaricow@chromium.org
341af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org#define __ masm.
351af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org
369a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org
371f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.orgUnaryMathFunction CreateExpFunction() {
38e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  if (!FLAG_fast_math) return &std::exp;
391f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  size_t actual_size;
405de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer =
415de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
42e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  if (buffer == NULL) return &std::exp;
431f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  ExternalReference::InitializeMathExpData();
441f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org
451f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
461f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  // esp[1 * kPointerSize]: raw double input
471f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  // esp[0 * kPointerSize]: return address
481f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  {
491f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org    XMMRegister input = xmm1;
501f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org    XMMRegister result = xmm2;
510fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(input, Operand(esp, 1 * kPointerSize));
521f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org    __ push(eax);
531f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org    __ push(ebx);
541f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org
551f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org    MathExpGenerator::EmitMathExp(&masm, input, result, xmm0, eax, ebx);
561f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org
571f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org    __ pop(ebx);
581f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org    __ pop(eax);
590fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(Operand(esp, 1 * kPointerSize), result);
601f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org    __ fld_d(Operand(esp, 1 * kPointerSize));
611f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org    __ Ret();
621f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  }
631f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org
641f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  CodeDesc desc;
651f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  masm.GetCode(&desc);
66e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!RelocInfo::RequiresRelocation(desc));
671f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org
685de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  CpuFeatures::FlushICache(buffer, actual_size);
695de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  base::OS::ProtectCode(buffer, actual_size);
701f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  return FUNCTION_CAST<UnaryMathFunction>(buffer);
711f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org}
721f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org
731f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org
74154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.orgUnaryMathFunction CreateSqrtFunction() {
75154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org  size_t actual_size;
76154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org  // Allocate buffer in executable space.
775de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer =
785de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
793c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  if (buffer == NULL) return &std::sqrt;
80154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org  MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
81154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org  // esp[1 * kPointerSize]: raw double input
82154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org  // esp[0 * kPointerSize]: return address
83154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org  // Move double input into registers.
84154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org  {
850fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(xmm0, Operand(esp, 1 * kPointerSize));
86154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org    __ sqrtsd(xmm0, xmm0);
870fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(Operand(esp, 1 * kPointerSize), xmm0);
88154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org    // Load result into floating point register as return value.
89154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org    __ fld_d(Operand(esp, 1 * kPointerSize));
90154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org    __ Ret();
91154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org  }
92154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org
93154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org  CodeDesc desc;
94154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org  masm.GetCode(&desc);
95e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!RelocInfo::RequiresRelocation(desc));
96154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org
975de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  CpuFeatures::FlushICache(buffer, actual_size);
985de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  base::OS::ProtectCode(buffer, actual_size);
99154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org  return FUNCTION_CAST<UnaryMathFunction>(buffer);
1009a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org}
1019a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org
1029a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org
103e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// Helper functions for CreateMemMoveFunction.
104e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org#undef __
105e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org#define __ ACCESS_MASM(masm)
106e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
107e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgenum Direction { FORWARD, BACKWARD };
108e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgenum Alignment { MOVE_ALIGNED, MOVE_UNALIGNED };
109e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
110e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// Expects registers:
111e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// esi - source, aligned if alignment == ALIGNED
112e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// edi - destination, always aligned
113e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// ecx - count (copy size in bytes)
114e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// edx - loop count (number of 64 byte chunks)
115e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgvoid MemMoveEmitMainLoop(MacroAssembler* masm,
116e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                         Label* move_last_15,
117e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                         Direction direction,
118e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                         Alignment alignment) {
119e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Register src = esi;
120e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Register dst = edi;
121e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Register count = ecx;
122e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Register loop_count = edx;
123e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Label loop, move_last_31, move_last_63;
124e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ cmp(loop_count, 0);
125e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ j(equal, &move_last_63);
126e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ bind(&loop);
127e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Main loop. Copy in 64 byte chunks.
128e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (direction == BACKWARD) __ sub(src, Immediate(0x40));
129e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ movdq(alignment == MOVE_ALIGNED, xmm0, Operand(src, 0x00));
130e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ movdq(alignment == MOVE_ALIGNED, xmm1, Operand(src, 0x10));
131e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ movdq(alignment == MOVE_ALIGNED, xmm2, Operand(src, 0x20));
132e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ movdq(alignment == MOVE_ALIGNED, xmm3, Operand(src, 0x30));
133e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (direction == FORWARD) __ add(src, Immediate(0x40));
134e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (direction == BACKWARD) __ sub(dst, Immediate(0x40));
135e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ movdqa(Operand(dst, 0x00), xmm0);
136e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ movdqa(Operand(dst, 0x10), xmm1);
137e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ movdqa(Operand(dst, 0x20), xmm2);
138e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ movdqa(Operand(dst, 0x30), xmm3);
139e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (direction == FORWARD) __ add(dst, Immediate(0x40));
140e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ dec(loop_count);
141e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ j(not_zero, &loop);
142e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // At most 63 bytes left to copy.
143e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ bind(&move_last_63);
144e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ test(count, Immediate(0x20));
145e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ j(zero, &move_last_31);
146e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (direction == BACKWARD) __ sub(src, Immediate(0x20));
147e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ movdq(alignment == MOVE_ALIGNED, xmm0, Operand(src, 0x00));
148e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ movdq(alignment == MOVE_ALIGNED, xmm1, Operand(src, 0x10));
149e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (direction == FORWARD) __ add(src, Immediate(0x20));
150e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (direction == BACKWARD) __ sub(dst, Immediate(0x20));
151e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ movdqa(Operand(dst, 0x00), xmm0);
152e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ movdqa(Operand(dst, 0x10), xmm1);
153e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (direction == FORWARD) __ add(dst, Immediate(0x20));
154e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // At most 31 bytes left to copy.
155e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ bind(&move_last_31);
156e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ test(count, Immediate(0x10));
157e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ j(zero, move_last_15);
158e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (direction == BACKWARD) __ sub(src, Immediate(0x10));
159e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ movdq(alignment == MOVE_ALIGNED, xmm0, Operand(src, 0));
160e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (direction == FORWARD) __ add(src, Immediate(0x10));
161e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (direction == BACKWARD) __ sub(dst, Immediate(0x10));
162e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ movdqa(Operand(dst, 0), xmm0);
163e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (direction == FORWARD) __ add(dst, Immediate(0x10));
164e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
165e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
166e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
167e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgvoid MemMoveEmitPopAndReturn(MacroAssembler* masm) {
168e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ pop(esi);
169e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ pop(edi);
170e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ ret(0);
171a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
172a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
173a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
174e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org#undef __
175e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org#define __ masm.
176e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
177e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
178639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.orgclass LabelConverter {
179639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org public:
180639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  explicit LabelConverter(byte* buffer) : buffer_(buffer) {}
181639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  int32_t address(Label* l) const {
182639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org    return reinterpret_cast<int32_t>(buffer_) + l->pos();
183639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  }
184639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org private:
185639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  byte* buffer_;
186639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org};
187639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org
188639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org
189d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.orgMemMoveFunction CreateMemMoveFunction() {
190c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  size_t actual_size;
191c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  // Allocate buffer in executable space.
1925de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer =
1935de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
194e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (buffer == NULL) return NULL;
195c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
196639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  LabelConverter conv(buffer);
1971af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org
198e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Generated code is put into a fixed, unmovable buffer, and not into
1991af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  // the V8 heap. We can't, and don't, refer to any relocatable addresses
2001af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  // (e.g. the JavaScript nan-object).
2011af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org
2021af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  // 32-bit C declaration function calls pass arguments on stack.
2031af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org
2041af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  // Stack layout:
2051af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  // esp[12]: Third argument, size.
2061af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  // esp[8]: Second argument, source pointer.
2071af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  // esp[4]: First argument, destination pointer.
2081af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  // esp[0]: return address
2091af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org
2101af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  const int kDestinationOffset = 1 * kPointerSize;
2111af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  const int kSourceOffset = 2 * kPointerSize;
2121af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  const int kSizeOffset = 3 * kPointerSize;
2131af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org
214e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // When copying up to this many bytes, use special "small" handlers.
215e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  const size_t kSmallCopySize = 8;
216e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // When copying up to this many bytes, use special "medium" handlers.
217e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  const size_t kMediumCopySize = 63;
218e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // When non-overlapping region of src and dst is less than this,
219e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // use a more careful implementation (slightly slower).
220e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  const size_t kMinMoveDistance = 16;
221e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Note that these values are dictated by the implementation below,
222e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // do not just change them and hope things will work!
223e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
2241af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  int stack_offset = 0;  // Update if we change the stack height.
2251af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org
226e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Label backward, backward_much_overlap;
227e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Label forward_much_overlap, small_size, medium_size, pop_and_return;
228e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ push(edi);
229e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ push(esi);
230e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  stack_offset += 2 * kPointerSize;
231e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Register dst = edi;
232e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Register src = esi;
233e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Register count = ecx;
234e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Register loop_count = edx;
235e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ mov(dst, Operand(esp, stack_offset + kDestinationOffset));
236e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ mov(src, Operand(esp, stack_offset + kSourceOffset));
237e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ mov(count, Operand(esp, stack_offset + kSizeOffset));
238e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
239e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ cmp(dst, src);
240e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ j(equal, &pop_and_return);
241e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
2423c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  __ prefetch(Operand(src, 0), 1);
2433c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  __ cmp(count, kSmallCopySize);
2443c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  __ j(below_equal, &small_size);
2453c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  __ cmp(count, kMediumCopySize);
2463c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  __ j(below_equal, &medium_size);
2473c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  __ cmp(dst, src);
2483c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  __ j(above, &backward);
2493c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org
2503c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  {
2513c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // |dst| is a lower address than |src|. Copy front-to-back.
2523c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    Label unaligned_source, move_last_15, skip_last_move;
2533c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov(eax, src);
2543c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ sub(eax, dst);
2553c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ cmp(eax, kMinMoveDistance);
2563c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ j(below, &forward_much_overlap);
2573c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // Copy first 16 bytes.
2583c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(xmm0, Operand(src, 0));
2593c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(Operand(dst, 0), xmm0);
2603c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // Determine distance to alignment: 16 - (dst & 0xF).
2613c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov(edx, dst);
2623c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ and_(edx, 0xF);
2633c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ neg(edx);
2643c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ add(edx, Immediate(16));
2653c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ add(dst, edx);
2663c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ add(src, edx);
2673c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ sub(count, edx);
2683c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // dst is now aligned. Main copy loop.
2693c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov(loop_count, count);
2703c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ shr(loop_count, 6);
2713c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // Check if src is also aligned.
2723c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ test(src, Immediate(0xF));
2733c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ j(not_zero, &unaligned_source);
2743c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // Copy loop for aligned source and destination.
2753c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    MemMoveEmitMainLoop(&masm, &move_last_15, FORWARD, MOVE_ALIGNED);
2763c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // At most 15 bytes to copy. Copy 16 bytes at end of string.
2773c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&move_last_15);
2783c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ and_(count, 0xF);
2793c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ j(zero, &skip_last_move, Label::kNear);
2803c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(xmm0, Operand(src, count, times_1, -0x10));
2813c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(Operand(dst, count, times_1, -0x10), xmm0);
2823c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&skip_last_move);
2833c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    MemMoveEmitPopAndReturn(&masm);
2843c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org
2853c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // Copy loop for unaligned source and aligned destination.
2863c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&unaligned_source);
2873c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    MemMoveEmitMainLoop(&masm, &move_last_15, FORWARD, MOVE_UNALIGNED);
2883c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ jmp(&move_last_15);
2893c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org
2903c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // Less than kMinMoveDistance offset between dst and src.
2913c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    Label loop_until_aligned, last_15_much_overlap;
2923c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&loop_until_aligned);
2933c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov_b(eax, Operand(src, 0));
2943c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ inc(src);
2953c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov_b(Operand(dst, 0), eax);
2963c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ inc(dst);
2973c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ dec(count);
2983c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&forward_much_overlap);  // Entry point into this block.
2993c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ test(dst, Immediate(0xF));
3003c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ j(not_zero, &loop_until_aligned);
3013c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // dst is now aligned, src can't be. Main copy loop.
3023c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov(loop_count, count);
3033c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ shr(loop_count, 6);
3043c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    MemMoveEmitMainLoop(&masm, &last_15_much_overlap,
3053c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org                        FORWARD, MOVE_UNALIGNED);
3063c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&last_15_much_overlap);
3073c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ and_(count, 0xF);
3083c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ j(zero, &pop_and_return);
309e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ cmp(count, kSmallCopySize);
310e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ j(below_equal, &small_size);
3113c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ jmp(&medium_size);
3123c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  }
3131af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org
3143c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  {
3153c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // |dst| is a higher address than |src|. Copy backwards.
3163c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    Label unaligned_source, move_first_15, skip_last_move;
3173c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&backward);
3183c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // |dst| and |src| always point to the end of what's left to copy.
3193c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ add(dst, count);
3203c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ add(src, count);
3213c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov(eax, dst);
3223c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ sub(eax, src);
3233c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ cmp(eax, kMinMoveDistance);
3243c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ j(below, &backward_much_overlap);
3253c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // Copy last 16 bytes.
3263c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(xmm0, Operand(src, -0x10));
3273c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(Operand(dst, -0x10), xmm0);
3283c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // Find distance to alignment: dst & 0xF
3293c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov(edx, dst);
3303c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ and_(edx, 0xF);
3313c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ sub(dst, edx);
3323c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ sub(src, edx);
3333c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ sub(count, edx);
3343c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // dst is now aligned. Main copy loop.
3353c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov(loop_count, count);
3363c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ shr(loop_count, 6);
3373c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // Check if src is also aligned.
3383c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ test(src, Immediate(0xF));
3393c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ j(not_zero, &unaligned_source);
3403c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // Copy loop for aligned source and destination.
3413c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    MemMoveEmitMainLoop(&masm, &move_first_15, BACKWARD, MOVE_ALIGNED);
3423c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // At most 15 bytes to copy. Copy 16 bytes at beginning of string.
3433c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&move_first_15);
3443c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ and_(count, 0xF);
3453c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ j(zero, &skip_last_move, Label::kNear);
3463c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ sub(src, count);
3473c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ sub(dst, count);
3483c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(xmm0, Operand(src, 0));
3493c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(Operand(dst, 0), xmm0);
3503c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&skip_last_move);
3513c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    MemMoveEmitPopAndReturn(&masm);
3523c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org
3533c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // Copy loop for unaligned source and aligned destination.
3543c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&unaligned_source);
3553c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    MemMoveEmitMainLoop(&masm, &move_first_15, BACKWARD, MOVE_UNALIGNED);
3563c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ jmp(&move_first_15);
3573c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org
3583c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // Less than kMinMoveDistance offset between dst and src.
3593c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    Label loop_until_aligned, first_15_much_overlap;
3603c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&loop_until_aligned);
3613c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ dec(src);
3623c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ dec(dst);
3633c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov_b(eax, Operand(src, 0));
3643c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov_b(Operand(dst, 0), eax);
3653c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ dec(count);
3663c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&backward_much_overlap);  // Entry point into this block.
3673c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ test(dst, Immediate(0xF));
3683c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ j(not_zero, &loop_until_aligned);
3693c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // dst is now aligned, src can't be. Main copy loop.
3703c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov(loop_count, count);
3713c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ shr(loop_count, 6);
3723c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    MemMoveEmitMainLoop(&masm, &first_15_much_overlap,
3733c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org                        BACKWARD, MOVE_UNALIGNED);
3743c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&first_15_much_overlap);
3753c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ and_(count, 0xF);
3763c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ j(zero, &pop_and_return);
3773c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // Small/medium handlers expect dst/src to point to the beginning.
3783c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ sub(dst, count);
3793c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ sub(src, count);
3803c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ cmp(count, kSmallCopySize);
3813c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ j(below_equal, &small_size);
3823c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ jmp(&medium_size);
3833c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  }
3843c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  {
3853c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // Special handlers for 9 <= copy_size < 64. No assumptions about
3863c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // alignment or move distance, so all reads must be unaligned and
3873c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // must happen before any writes.
3883c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    Label medium_handlers, f9_16, f17_32, f33_48, f49_63;
3893c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org
3903c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&f9_16);
3913c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movsd(xmm0, Operand(src, 0));
3923c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movsd(xmm1, Operand(src, count, times_1, -8));
3933c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movsd(Operand(dst, 0), xmm0);
3943c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movsd(Operand(dst, count, times_1, -8), xmm1);
3953c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    MemMoveEmitPopAndReturn(&masm);
3963c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org
3973c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&f17_32);
3983c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(xmm0, Operand(src, 0));
3993c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(xmm1, Operand(src, count, times_1, -0x10));
4003c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(Operand(dst, 0x00), xmm0);
4013c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(Operand(dst, count, times_1, -0x10), xmm1);
4023c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    MemMoveEmitPopAndReturn(&masm);
4033c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org
4043c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&f33_48);
4053c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(xmm0, Operand(src, 0x00));
4063c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(xmm1, Operand(src, 0x10));
4073c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(xmm2, Operand(src, count, times_1, -0x10));
4083c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(Operand(dst, 0x00), xmm0);
4093c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(Operand(dst, 0x10), xmm1);
4103c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(Operand(dst, count, times_1, -0x10), xmm2);
4113c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    MemMoveEmitPopAndReturn(&masm);
4123c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org
4133c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&f49_63);
4143c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(xmm0, Operand(src, 0x00));
4153c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(xmm1, Operand(src, 0x10));
4163c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(xmm2, Operand(src, 0x20));
4173c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(xmm3, Operand(src, count, times_1, -0x10));
4183c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(Operand(dst, 0x00), xmm0);
4193c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(Operand(dst, 0x10), xmm1);
4203c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(Operand(dst, 0x20), xmm2);
4213c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movdqu(Operand(dst, count, times_1, -0x10), xmm3);
4223c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    MemMoveEmitPopAndReturn(&masm);
4233c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org
4243c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&medium_handlers);
4253c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ dd(conv.address(&f9_16));
4263c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ dd(conv.address(&f17_32));
4273c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ dd(conv.address(&f33_48));
4283c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ dd(conv.address(&f49_63));
4293c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org
4303c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&medium_size);  // Entry point into this block.
4313c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov(eax, count);
4323c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ dec(eax);
4333c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ shr(eax, 4);
4343c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    if (FLAG_debug_code) {
4353c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      Label ok;
4363c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      __ cmp(eax, 3);
4373c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      __ j(below_equal, &ok);
4383c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      __ int3();
4393c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      __ bind(&ok);
440e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    }
4413c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov(eax, Operand(eax, times_4, conv.address(&medium_handlers)));
4423c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ jmp(eax);
4433c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  }
4443c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  {
4453c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    // Specialized copiers for copy_size <= 8 bytes.
4463c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    Label small_handlers, f0, f1, f2, f3, f4, f5_8;
4473c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&f0);
4483c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    MemMoveEmitPopAndReturn(&masm);
4493c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org
4503c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&f1);
4513c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov_b(eax, Operand(src, 0));
4523c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov_b(Operand(dst, 0), eax);
4533c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    MemMoveEmitPopAndReturn(&masm);
4543c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org
4553c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&f2);
4563c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov_w(eax, Operand(src, 0));
4573c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov_w(Operand(dst, 0), eax);
4583c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    MemMoveEmitPopAndReturn(&masm);
4593c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org
4603c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&f3);
4613c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov_w(eax, Operand(src, 0));
4623c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov_b(edx, Operand(src, 2));
4633c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov_w(Operand(dst, 0), eax);
4643c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov_b(Operand(dst, 2), edx);
4653c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    MemMoveEmitPopAndReturn(&masm);
4663c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org
4673c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&f4);
4683c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov(eax, Operand(src, 0));
4693c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov(Operand(dst, 0), eax);
4703c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    MemMoveEmitPopAndReturn(&masm);
4713c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org
4723c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&f5_8);
4733c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov(eax, Operand(src, 0));
4743c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov(edx, Operand(src, count, times_1, -4));
4753c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov(Operand(dst, 0), eax);
4763c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov(Operand(dst, count, times_1, -4), edx);
4773c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    MemMoveEmitPopAndReturn(&masm);
4783c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org
4793c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&small_handlers);
4803c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ dd(conv.address(&f0));
4813c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ dd(conv.address(&f1));
4823c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ dd(conv.address(&f2));
4833c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ dd(conv.address(&f3));
4843c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ dd(conv.address(&f4));
4853c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ dd(conv.address(&f5_8));
4863c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ dd(conv.address(&f5_8));
4873c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ dd(conv.address(&f5_8));
4883c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ dd(conv.address(&f5_8));
4893c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org
4903c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ bind(&small_size);  // Entry point into this block.
4913c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    if (FLAG_debug_code) {
4923c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      Label ok;
4933c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      __ cmp(count, 8);
4943c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      __ j(below_equal, &ok);
4953c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      __ int3();
4963c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      __ bind(&ok);
497e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    }
4983c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ mov(eax, Operand(count, times_4, conv.address(&small_handlers)));
4993c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ jmp(eax);
5001af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  }
5011af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org
502e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ bind(&pop_and_return);
503e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  MemMoveEmitPopAndReturn(&masm);
504e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
5051af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  CodeDesc desc;
5061af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  masm.GetCode(&desc);
507e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!RelocInfo::RequiresRelocation(desc));
5085de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  CpuFeatures::FlushICache(buffer, actual_size);
5095de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  base::OS::ProtectCode(buffer, actual_size);
51077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  // TODO(jkummerow): It would be nice to register this code creation event
51177ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  // with the PROFILE / GDBJIT system.
512d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org  return FUNCTION_CAST<MemMoveFunction>(buffer);
5131af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org}
5141af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org
515e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
5161af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org#undef __
5171af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org
518394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com// -------------------------------------------------------------------------
519394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com// Code generators
520394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
521394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com#define __ ACCESS_MASM(masm)
522394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
52359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
524830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.orgvoid ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
5259bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    MacroAssembler* masm,
5269bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    Register receiver,
5279bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    Register key,
5289bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    Register value,
5299bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    Register target_map,
5309bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    AllocationSiteMode mode,
531ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    Label* allocation_memento_found) {
5329bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  Register scratch = edi;
533e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!AreAliased(receiver, key, value, target_map, scratch));
5349bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org
53546a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  if (mode == TRACK_ALLOCATION_SITE) {
536e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(allocation_memento_found != NULL);
5379bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    __ JumpIfJSArrayHasAllocationMemento(
5389bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org        receiver, scratch, allocation_memento_found);
53946a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  }
54046a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org
541394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Set transitioned map.
5429bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  __ mov(FieldOperand(receiver, HeapObject::kMapOffset), target_map);
5439bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  __ RecordWriteField(receiver,
544394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      HeapObject::kMapOffset,
5459bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org                      target_map,
5469bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org                      scratch,
547394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      kDontSaveFPRegs,
548394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      EMIT_REMEMBERED_SET,
549394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      OMIT_SMI_CHECK);
550394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com}
551394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
552394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
553830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.orgvoid ElementsTransitionGenerator::GenerateSmiToDouble(
5549bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    MacroAssembler* masm,
5559bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    Register receiver,
5569bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    Register key,
5579bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    Register value,
5589bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    Register target_map,
5599bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    AllocationSiteMode mode,
5609bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    Label* fail) {
5619bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  // Return address is on the stack.
562e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(receiver.is(edx));
563e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(key.is(ecx));
564e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(value.is(eax));
565e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(target_map.is(ebx));
5669bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org
56765a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  Label loop, entry, convert_hole, gc_required, only_change_map;
56865a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org
56946a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  if (mode == TRACK_ALLOCATION_SITE) {
570b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org    __ JumpIfJSArrayHasAllocationMemento(edx, edi, fail);
57159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  }
57259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
57365a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  // Check for empty arrays, which only require a map transition and no changes
57465a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  // to the backing store.
57565a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
57665a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array()));
57765a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ j(equal, &only_change_map);
57865a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org
579394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ push(eax);
580394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ push(ebx);
581394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
582394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(edi, FieldOperand(edi, FixedArray::kLengthOffset));
583394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
584394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Allocate new FixedDoubleArray.
585394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // edx: receiver
586394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // edi: length of source FixedArray (smi-tagged)
5874cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org  AllocationFlags flags =
5884cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org      static_cast<AllocationFlags>(TAG_OBJECT | DOUBLE_ALIGNMENT);
589f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  __ Allocate(FixedDoubleArray::kHeaderSize, times_8, edi,
590f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org              REGISTER_VALUE_IS_SMI, eax, ebx, no_reg, &gc_required, flags);
591ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
592394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // eax: destination FixedDoubleArray
593394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // edi: number of elements
594394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // edx: receiver
595394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(FieldOperand(eax, HeapObject::kMapOffset),
596394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com         Immediate(masm->isolate()->factory()->fixed_double_array_map()));
597394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(FieldOperand(eax, FixedDoubleArray::kLengthOffset), edi);
598394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(esi, FieldOperand(edx, JSObject::kElementsOffset));
599394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Replace receiver's backing store with newly created FixedDoubleArray.
600394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax);
601394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(ebx, eax);
602394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ RecordWriteField(edx,
603394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      JSObject::kElementsOffset,
604394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      ebx,
605394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      edi,
606394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      kDontSaveFPRegs,
607394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      EMIT_REMEMBERED_SET,
608394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      OMIT_SMI_CHECK);
609394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
610394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(edi, FieldOperand(esi, FixedArray::kLengthOffset));
611394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
612394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Prepare for conversion loop.
613394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  ExternalReference canonical_the_hole_nan_reference =
614394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      ExternalReference::address_of_the_hole_nan();
615394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  XMMRegister the_hole_nan = xmm1;
6163c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  __ movsd(the_hole_nan,
6173c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org           Operand::StaticVariable(canonical_the_hole_nan_reference));
618394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ jmp(&entry);
619394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
620394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Call into runtime if GC is required.
621394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ bind(&gc_required);
622394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Restore registers before jumping into runtime.
623394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
624394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ pop(ebx);
625394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ pop(eax);
626394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ jmp(fail);
627394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
628394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Convert and copy elements
629394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // esi: source FixedArray
630394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ bind(&loop);
631394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(ebx, FieldOperand(esi, edi, times_2, FixedArray::kHeaderSize));
632394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // ebx: current element from source
633394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // edi: index of current element
634394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ JumpIfNotSmi(ebx, &convert_hole);
635394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
636394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Normal smi, convert it to double and store.
637394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ SmiUntag(ebx);
6383c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  __ Cvtsi2sd(xmm0, ebx);
6393c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  __ movsd(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize),
6403c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org           xmm0);
641394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ jmp(&entry);
642394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
643394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Found hole, store hole_nan_as_double instead.
644394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ bind(&convert_hole);
645c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
646c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (FLAG_debug_code) {
647c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    __ cmp(ebx, masm->isolate()->factory()->the_hole_value());
648594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(equal, kObjectFoundInSmiOnlyArray);
649c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  }
650c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
6513c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  __ movsd(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize),
6523c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org           the_hole_nan);
653394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
654394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ bind(&entry);
655becbc5247ca44bb32846a82794e96425980e9d50erik.corry@gmail.com  __ sub(edi, Immediate(Smi::FromInt(1)));
656becbc5247ca44bb32846a82794e96425980e9d50erik.corry@gmail.com  __ j(not_sign, &loop);
657394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
658394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ pop(ebx);
659394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ pop(eax);
66065a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org
66165a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  // Restore esi.
66265a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
66365a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org
66465a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ bind(&only_change_map);
665394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // eax: value
666394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // ebx: target map
667394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Set transitioned map.
668394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx);
669394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ RecordWriteField(edx,
670394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      HeapObject::kMapOffset,
671394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      ebx,
672394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      edi,
673394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      kDontSaveFPRegs,
67465a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org                      OMIT_REMEMBERED_SET,
675394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      OMIT_SMI_CHECK);
676394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com}
677394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
678394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
679394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.comvoid ElementsTransitionGenerator::GenerateDoubleToObject(
6809bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    MacroAssembler* masm,
6819bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    Register receiver,
6829bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    Register key,
6839bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    Register value,
6849bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    Register target_map,
6859bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    AllocationSiteMode mode,
6869bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    Label* fail) {
6879bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  // Return address is on the stack.
688e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(receiver.is(edx));
689e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(key.is(ecx));
690e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(value.is(eax));
691e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(target_map.is(ebx));
6929bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org
69365a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  Label loop, entry, convert_hole, gc_required, only_change_map, success;
69465a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org
69546a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  if (mode == TRACK_ALLOCATION_SITE) {
696b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org    __ JumpIfJSArrayHasAllocationMemento(edx, edi, fail);
69746a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  }
69846a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org
69965a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  // Check for empty arrays, which only require a map transition and no changes
70065a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  // to the backing store.
70165a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
70265a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array()));
70365a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ j(equal, &only_change_map);
70465a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org
705394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ push(eax);
706394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ push(edx);
707394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ push(ebx);
708394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
709394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(ebx, FieldOperand(edi, FixedDoubleArray::kLengthOffset));
710394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
711394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Allocate new FixedArray.
712394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // ebx: length of source FixedDoubleArray (smi-tagged)
713394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ lea(edi, Operand(ebx, times_2, FixedArray::kHeaderSize));
714f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  __ Allocate(edi, eax, esi, no_reg, &gc_required, TAG_OBJECT);
715394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
716394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // eax: destination FixedArray
717394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // ebx: number of elements
718394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(FieldOperand(eax, HeapObject::kMapOffset),
719394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com         Immediate(masm->isolate()->factory()->fixed_array_map()));
720394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(FieldOperand(eax, FixedArray::kLengthOffset), ebx);
721394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
722394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
723394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ jmp(&entry);
724394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
72565a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  // ebx: target map
72665a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  // edx: receiver
72765a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  // Set transitioned map.
72865a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ bind(&only_change_map);
72965a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx);
73065a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ RecordWriteField(edx,
73165a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org                      HeapObject::kMapOffset,
73265a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org                      ebx,
73365a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org                      edi,
73465a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org                      kDontSaveFPRegs,
73565a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org                      OMIT_REMEMBERED_SET,
73665a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org                      OMIT_SMI_CHECK);
73765a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ jmp(&success);
73865a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org
739394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Call into runtime if GC is required.
740394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ bind(&gc_required);
741394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
742394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ pop(ebx);
743394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ pop(edx);
744394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ pop(eax);
745394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ jmp(fail);
746394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
747394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Box doubles into heap numbers.
748394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // edi: source FixedDoubleArray
749394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // eax: destination FixedArray
750394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ bind(&loop);
751394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // ebx: index of current element (smi-tagged)
752394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
753394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ cmp(FieldOperand(edi, ebx, times_4, offset), Immediate(kHoleNanUpper32));
754394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ j(equal, &convert_hole);
755394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
756394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Non-hole double, copy value into a heap number.
757394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ AllocateHeapNumber(edx, esi, no_reg, &gc_required);
758394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // edx: new heap number
7593c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  __ movsd(xmm0,
7603c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org           FieldOperand(edi, ebx, times_4, FixedDoubleArray::kHeaderSize));
7613c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  __ movsd(FieldOperand(edx, HeapNumber::kValueOffset), xmm0);
762394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize), edx);
763394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(esi, ebx);
764394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ RecordWriteArray(eax,
765394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      edx,
766394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      esi,
767394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      kDontSaveFPRegs,
768394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      EMIT_REMEMBERED_SET,
769394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      OMIT_SMI_CHECK);
770394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ jmp(&entry, Label::kNear);
771394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
772394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Replace the-hole NaN with the-hole pointer.
773394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ bind(&convert_hole);
774394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize),
775394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com         masm->isolate()->factory()->the_hole_value());
776394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
777394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ bind(&entry);
778becbc5247ca44bb32846a82794e96425980e9d50erik.corry@gmail.com  __ sub(ebx, Immediate(Smi::FromInt(1)));
779becbc5247ca44bb32846a82794e96425980e9d50erik.corry@gmail.com  __ j(not_sign, &loop);
780394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
781394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ pop(ebx);
782394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ pop(edx);
783394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // ebx: target map
784394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // edx: receiver
785394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Set transitioned map.
786394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx);
787394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ RecordWriteField(edx,
788394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      HeapObject::kMapOffset,
789394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      ebx,
790394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      edi,
791394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      kDontSaveFPRegs,
79265a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org                      OMIT_REMEMBERED_SET,
793394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      OMIT_SMI_CHECK);
794394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Replace receiver's backing store with newly created and filled FixedArray.
795394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax);
796394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ RecordWriteField(edx,
797394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      JSObject::kElementsOffset,
798394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      eax,
799394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      edi,
800394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      kDontSaveFPRegs,
801394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      EMIT_REMEMBERED_SET,
802394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                      OMIT_SMI_CHECK);
803394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
804394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Restore registers.
805394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ pop(eax);
806394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
80765a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org
80865a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ bind(&success);
809394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com}
810394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
8110ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry
8120ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorryvoid StringCharLoadGenerator::Generate(MacroAssembler* masm,
8130ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry                                       Factory* factory,
8140ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry                                       Register string,
8150ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry                                       Register index,
8160ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry                                       Register result,
8170ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry                                       Label* call_runtime) {
8180ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  // Fetch the instance type of the receiver into result register.
8190ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ mov(result, FieldOperand(string, HeapObject::kMapOffset));
8200ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
8210ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry
8220ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  // We need special handling for indirect strings.
8230ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  Label check_sequential;
8240ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ test(result, Immediate(kIsIndirectStringMask));
8251b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ j(zero, &check_sequential, Label::kNear);
8260ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry
8270ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  // Dispatch on the indirect string shape: slice or cons.
8280ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  Label cons_string;
8290ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ test(result, Immediate(kSlicedNotConsMask));
8301b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ j(zero, &cons_string, Label::kNear);
8310ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry
8320ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  // Handle slices.
8330ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  Label indirect_string_loaded;
8340ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ mov(result, FieldOperand(string, SlicedString::kOffsetOffset));
8350ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ SmiUntag(result);
8360ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ add(index, result);
8370ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ mov(string, FieldOperand(string, SlicedString::kParentOffset));
8381b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ jmp(&indirect_string_loaded, Label::kNear);
8390ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry
8401b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  // Handle cons strings.
8410ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  // Check whether the right hand side is the empty string (i.e. if
8420ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  // this is really a flat string in a cons string). If that is not
8430ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  // the case we would rather go to the runtime system now to flatten
8440ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  // the string.
8450ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ bind(&cons_string);
8460ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ cmp(FieldOperand(string, ConsString::kSecondOffset),
8470ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry         Immediate(factory->empty_string()));
8480ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ j(not_equal, call_runtime);
8490ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ mov(string, FieldOperand(string, ConsString::kFirstOffset));
8500ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry
8510ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ bind(&indirect_string_loaded);
8520ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ mov(result, FieldOperand(string, HeapObject::kMapOffset));
8530ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
8540ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry
8551b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  // Distinguish sequential and external strings. Only these two string
8561b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  // representations can reach here (slices and flat cons strings have been
8571b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  // reduced to the underlying sequential or external string).
8581b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  Label seq_string;
8590ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ bind(&check_sequential);
8600ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  STATIC_ASSERT(kSeqStringTag == 0);
8610ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ test(result, Immediate(kStringRepresentationMask));
8621b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ j(zero, &seq_string, Label::kNear);
8631b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
8641b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  // Handle external strings.
8652c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  Label one_byte_external, done;
8661b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  if (FLAG_debug_code) {
8671b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // Assert that we do not have a cons or slice (indirect strings) here.
8681b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // Sequential strings have already been ruled out.
8691b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    __ test(result, Immediate(kIsIndirectStringMask));
870594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(zero, kExternalStringExpectedButNotFound);
8711b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  }
8721b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  // Rule out short external strings.
873d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org  STATIC_ASSERT(kShortExternalStringTag != 0);
8741b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ test_b(result, kShortExternalStringMask);
8751b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ j(not_zero, call_runtime);
8761b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  // Check encoding.
8771b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  STATIC_ASSERT(kTwoByteStringTag == 0);
8781b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ test_b(result, kStringEncodingMask);
8791b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ mov(result, FieldOperand(string, ExternalString::kResourceDataOffset));
8802c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  __ j(not_equal, &one_byte_external, Label::kNear);
8811b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  // Two-byte string.
8821b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ movzx_w(result, Operand(result, index, times_2, 0));
8831b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ jmp(&done, Label::kNear);
8842c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  __ bind(&one_byte_external);
8852c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // One-byte string.
8861b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ movzx_b(result, Operand(result, index, times_1, 0));
8871b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ jmp(&done, Label::kNear);
8880ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry
8892c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // Dispatch on the encoding: one-byte or two-byte.
8902c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  Label one_byte;
8911b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ bind(&seq_string);
892e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
8930ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
8940ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ test(result, Immediate(kStringEncodingMask));
8952c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  __ j(not_zero, &one_byte, Label::kNear);
8960ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry
8970ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  // Two-byte string.
8980ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  // Load the two-byte character code into the result register.
8990ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ movzx_w(result, FieldOperand(string,
9000ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry                                  index,
9010ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry                                  times_2,
9020ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry                                  SeqTwoByteString::kHeaderSize));
9030ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ jmp(&done, Label::kNear);
9040ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry
9052c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // One-byte string.
9060ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  // Load the byte into the result register.
9072c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  __ bind(&one_byte);
9080ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ movzx_b(result, FieldOperand(string,
9090ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry                                  index,
9100ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry                                  times_1,
911fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                  SeqOneByteString::kHeaderSize));
9120ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ bind(&done);
9130ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry}
9140ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry
9151f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org
9161f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.orgstatic Operand ExpConstant(int index) {
9171f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  return Operand::StaticVariable(ExternalReference::math_exp_constants(index));
9181f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org}
9191f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org
9201f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org
9211f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.orgvoid MathExpGenerator::EmitMathExp(MacroAssembler* masm,
9221f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org                                   XMMRegister input,
9231f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org                                   XMMRegister result,
9241f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org                                   XMMRegister double_scratch,
9251f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org                                   Register temp1,
9261f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org                                   Register temp2) {
927e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!input.is(double_scratch));
928e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!input.is(result));
929e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!result.is(double_scratch));
930e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!temp1.is(temp2));
931e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ExternalReference::math_exp_constants(0).address() != NULL);
9329d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  DCHECK(!masm->serializer_enabled());  // External references not serializable.
9331f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org
9341f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  Label done;
9351f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org
9360fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org  __ movsd(double_scratch, ExpConstant(0));
9371f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ xorpd(result, result);
9381f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ ucomisd(double_scratch, input);
9391f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ j(above_equal, &done);
9401f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ ucomisd(input, ExpConstant(1));
9410fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org  __ movsd(result, ExpConstant(2));
9421f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ j(above_equal, &done);
9430fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org  __ movsd(double_scratch, ExpConstant(3));
9440fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org  __ movsd(result, ExpConstant(4));
9451f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ mulsd(double_scratch, input);
9461f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ addsd(double_scratch, result);
9471f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ movd(temp2, double_scratch);
9481f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ subsd(double_scratch, result);
9490fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org  __ movsd(result, ExpConstant(6));
9501f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ mulsd(double_scratch, ExpConstant(5));
9511f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ subsd(double_scratch, input);
9521f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ subsd(result, double_scratch);
9531f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ movsd(input, double_scratch);
9541f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ mulsd(input, double_scratch);
9551f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ mulsd(result, input);
9561f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ mov(temp1, temp2);
9571f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ mulsd(result, ExpConstant(7));
9581f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ subsd(result, double_scratch);
9591f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ add(temp1, Immediate(0x1ff800));
9601f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ addsd(result, ExpConstant(8));
9611f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ and_(temp2, Immediate(0x7ff));
9621f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ shr(temp1, 11);
9631f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ shl(temp1, 20);
9641f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ movd(input, temp1);
9651f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ pshufd(input, input, static_cast<uint8_t>(0xe1));  // Order: 11 10 00 01
9660fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org  __ movsd(double_scratch, Operand::StaticArray(
9671f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org      temp2, times_8, ExternalReference::math_exp_log_table()));
968057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  __ orps(input, double_scratch);
9691f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ mulsd(result, input);
9701f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  __ bind(&done);
9711f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org}
9721f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org
973394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com#undef __
974394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
975e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org
9765924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.orgCodeAgingHelper::CodeAgingHelper() {
977e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength);
9785924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org  CodePatcher patcher(young_sequence_.start(), young_sequence_.length());
9795924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org  patcher.masm()->push(ebp);
9805924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org  patcher.masm()->mov(ebp, esp);
9815924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org  patcher.masm()->push(esi);
9825924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org  patcher.masm()->push(edi);
9835924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org}
9845924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org
9855924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org
9865924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org#ifdef DEBUG
9875924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.orgbool CodeAgingHelper::IsOld(byte* candidate) const {
9885924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org  return *candidate == kCallOpcode;
989e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org}
9905924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org#endif
991e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org
992e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org
9935924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.orgbool Code::IsYoungSequence(Isolate* isolate, byte* sequence) {
9945924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org  bool result = isolate->code_aging_helper()->IsYoung(sequence);
995e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(result || isolate->code_aging_helper()->IsOld(sequence));
996e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  return result;
997e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org}
998e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org
999e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org
10005924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.orgvoid Code::GetCodeAgeAndParity(Isolate* isolate, byte* sequence, Age* age,
1001e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org                               MarkingParity* parity) {
10025924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org  if (IsYoungSequence(isolate, sequence)) {
1003e94b5ff1e1e95fb2c8ef6bce66ce8533786d9792bmeurer@chromium.org    *age = kNoAgeCodeAge;
1004e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org    *parity = NO_MARKING_PARITY;
1005e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  } else {
1006e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org    sequence++;  // Skip the kCallOpcode byte
1007e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org    Address target_address = sequence + *reinterpret_cast<int*>(sequence) +
1008e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org        Assembler::kCallTargetAddressOffset;
1009e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org    Code* stub = GetCodeFromTargetAddress(target_address);
1010e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org    GetCodeAgeAndParity(stub, age, parity);
1011e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  }
1012e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org}
1013e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org
1014e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org
1015528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.orgvoid Code::PatchPlatformCodeAge(Isolate* isolate,
1016528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                                byte* sequence,
1017e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org                                Code::Age age,
1018e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org                                MarkingParity parity) {
10195924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org  uint32_t young_length = isolate->code_aging_helper()->young_sequence_length();
1020e94b5ff1e1e95fb2c8ef6bce66ce8533786d9792bmeurer@chromium.org  if (age == kNoAgeCodeAge) {
10215924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org    isolate->code_aging_helper()->CopyYoungSequenceTo(sequence);
10225de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org    CpuFeatures::FlushICache(sequence, young_length);
1023e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  } else {
1024528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    Code* stub = GetCodeAgeStub(isolate, age, parity);
1025e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org    CodePatcher patcher(sequence, young_length);
102659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    patcher.masm()->call(stub->instruction_start(), RelocInfo::NONE32);
1027e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  }
1028e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org}
1029e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org
1030e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org
103143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} }  // namespace v8::internal
10329dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
10339dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com#endif  // V8_TARGET_ARCH_IA32
1034