| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_IA32 | 7 #if V8_TARGET_ARCH_X87 |
| 8 | 8 |
| 9 #include "codegen.h" | 9 #include "codegen.h" |
| 10 #include "heap.h" | 10 #include "heap.h" |
| 11 #include "macro-assembler.h" | 11 #include "macro-assembler.h" |
| 12 | 12 |
| 13 namespace v8 { | 13 namespace v8 { |
| 14 namespace internal { | 14 namespace internal { |
| 15 | 15 |
| 16 | 16 |
| 17 // ------------------------------------------------------------------------- | 17 // ------------------------------------------------------------------------- |
| (...skipping 10 matching lines...) Expand all Loading... |
| 28 masm->LeaveFrame(StackFrame::INTERNAL); | 28 masm->LeaveFrame(StackFrame::INTERNAL); |
| 29 ASSERT(masm->has_frame()); | 29 ASSERT(masm->has_frame()); |
| 30 masm->set_has_frame(false); | 30 masm->set_has_frame(false); |
| 31 } | 31 } |
| 32 | 32 |
| 33 | 33 |
| 34 #define __ masm. | 34 #define __ masm. |
| 35 | 35 |
| 36 | 36 |
| 37 UnaryMathFunction CreateExpFunction() { | 37 UnaryMathFunction CreateExpFunction() { |
| 38 if (!FLAG_fast_math) return &std::exp; | 38 // No SSE2 support |
| 39 size_t actual_size; | 39 return &std::exp; |
| 40 byte* buffer = static_cast<byte*>(OS::Allocate(1 * KB, &actual_size, true)); | |
| 41 if (buffer == NULL) return &std::exp; | |
| 42 ExternalReference::InitializeMathExpData(); | |
| 43 | |
| 44 MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size)); | |
| 45 // esp[1 * kPointerSize]: raw double input | |
| 46 // esp[0 * kPointerSize]: return address | |
| 47 { | |
| 48 XMMRegister input = xmm1; | |
| 49 XMMRegister result = xmm2; | |
| 50 __ movsd(input, Operand(esp, 1 * kPointerSize)); | |
| 51 __ push(eax); | |
| 52 __ push(ebx); | |
| 53 | |
| 54 MathExpGenerator::EmitMathExp(&masm, input, result, xmm0, eax, ebx); | |
| 55 | |
| 56 __ pop(ebx); | |
| 57 __ pop(eax); | |
| 58 __ movsd(Operand(esp, 1 * kPointerSize), result); | |
| 59 __ fld_d(Operand(esp, 1 * kPointerSize)); | |
| 60 __ Ret(); | |
| 61 } | |
| 62 | |
| 63 CodeDesc desc; | |
| 64 masm.GetCode(&desc); | |
| 65 ASSERT(!RelocInfo::RequiresRelocation(desc)); | |
| 66 | |
| 67 CPU::FlushICache(buffer, actual_size); | |
| 68 OS::ProtectCode(buffer, actual_size); | |
| 69 return FUNCTION_CAST<UnaryMathFunction>(buffer); | |
| 70 } | 40 } |
| 71 | 41 |
| 72 | 42 |
| 73 UnaryMathFunction CreateSqrtFunction() { | 43 UnaryMathFunction CreateSqrtFunction() { |
| 74 size_t actual_size; | 44 // No SSE2 support |
| 75 // Allocate buffer in executable space. | 45 return &std::sqrt; |
| 76 byte* buffer = static_cast<byte*>(OS::Allocate(1 * KB, | |
| 77 &actual_size, | |
| 78 true)); | |
| 79 if (buffer == NULL) return &std::sqrt; | |
| 80 MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size)); | |
| 81 // esp[1 * kPointerSize]: raw double input | |
| 82 // esp[0 * kPointerSize]: return address | |
| 83 // Move double input into registers. | |
| 84 { | |
| 85 __ movsd(xmm0, Operand(esp, 1 * kPointerSize)); | |
| 86 __ sqrtsd(xmm0, xmm0); | |
| 87 __ movsd(Operand(esp, 1 * kPointerSize), xmm0); | |
| 88 // Load result into floating point register as return value. | |
| 89 __ fld_d(Operand(esp, 1 * kPointerSize)); | |
| 90 __ Ret(); | |
| 91 } | |
| 92 | |
| 93 CodeDesc desc; | |
| 94 masm.GetCode(&desc); | |
| 95 ASSERT(!RelocInfo::RequiresRelocation(desc)); | |
| 96 | |
| 97 CPU::FlushICache(buffer, actual_size); | |
| 98 OS::ProtectCode(buffer, actual_size); | |
| 99 return FUNCTION_CAST<UnaryMathFunction>(buffer); | |
| 100 } | 46 } |
| 101 | 47 |
| 102 | 48 |
| 103 // Helper functions for CreateMemMoveFunction. | 49 // Helper functions for CreateMemMoveFunction. |
| 104 #undef __ | 50 #undef __ |
| 105 #define __ ACCESS_MASM(masm) | 51 #define __ ACCESS_MASM(masm) |
| 106 | 52 |
| 107 enum Direction { FORWARD, BACKWARD }; | 53 enum Direction { FORWARD, BACKWARD }; |
| 108 enum Alignment { MOVE_ALIGNED, MOVE_UNALIGNED }; | 54 enum Alignment { MOVE_ALIGNED, MOVE_UNALIGNED }; |
| 109 | 55 |
| 110 // Expects registers: | |
| 111 // esi - source, aligned if alignment == ALIGNED | |
| 112 // edi - destination, always aligned | |
| 113 // ecx - count (copy size in bytes) | |
| 114 // edx - loop count (number of 64 byte chunks) | |
| 115 void MemMoveEmitMainLoop(MacroAssembler* masm, | |
| 116 Label* move_last_15, | |
| 117 Direction direction, | |
| 118 Alignment alignment) { | |
| 119 Register src = esi; | |
| 120 Register dst = edi; | |
| 121 Register count = ecx; | |
| 122 Register loop_count = edx; | |
| 123 Label loop, move_last_31, move_last_63; | |
| 124 __ cmp(loop_count, 0); | |
| 125 __ j(equal, &move_last_63); | |
| 126 __ bind(&loop); | |
| 127 // Main loop. Copy in 64 byte chunks. | |
| 128 if (direction == BACKWARD) __ sub(src, Immediate(0x40)); | |
| 129 __ movdq(alignment == MOVE_ALIGNED, xmm0, Operand(src, 0x00)); | |
| 130 __ movdq(alignment == MOVE_ALIGNED, xmm1, Operand(src, 0x10)); | |
| 131 __ movdq(alignment == MOVE_ALIGNED, xmm2, Operand(src, 0x20)); | |
| 132 __ movdq(alignment == MOVE_ALIGNED, xmm3, Operand(src, 0x30)); | |
| 133 if (direction == FORWARD) __ add(src, Immediate(0x40)); | |
| 134 if (direction == BACKWARD) __ sub(dst, Immediate(0x40)); | |
| 135 __ movdqa(Operand(dst, 0x00), xmm0); | |
| 136 __ movdqa(Operand(dst, 0x10), xmm1); | |
| 137 __ movdqa(Operand(dst, 0x20), xmm2); | |
| 138 __ movdqa(Operand(dst, 0x30), xmm3); | |
| 139 if (direction == FORWARD) __ add(dst, Immediate(0x40)); | |
| 140 __ dec(loop_count); | |
| 141 __ j(not_zero, &loop); | |
| 142 // At most 63 bytes left to copy. | |
| 143 __ bind(&move_last_63); | |
| 144 __ test(count, Immediate(0x20)); | |
| 145 __ j(zero, &move_last_31); | |
| 146 if (direction == BACKWARD) __ sub(src, Immediate(0x20)); | |
| 147 __ movdq(alignment == MOVE_ALIGNED, xmm0, Operand(src, 0x00)); | |
| 148 __ movdq(alignment == MOVE_ALIGNED, xmm1, Operand(src, 0x10)); | |
| 149 if (direction == FORWARD) __ add(src, Immediate(0x20)); | |
| 150 if (direction == BACKWARD) __ sub(dst, Immediate(0x20)); | |
| 151 __ movdqa(Operand(dst, 0x00), xmm0); | |
| 152 __ movdqa(Operand(dst, 0x10), xmm1); | |
| 153 if (direction == FORWARD) __ add(dst, Immediate(0x20)); | |
| 154 // At most 31 bytes left to copy. | |
| 155 __ bind(&move_last_31); | |
| 156 __ test(count, Immediate(0x10)); | |
| 157 __ j(zero, move_last_15); | |
| 158 if (direction == BACKWARD) __ sub(src, Immediate(0x10)); | |
| 159 __ movdq(alignment == MOVE_ALIGNED, xmm0, Operand(src, 0)); | |
| 160 if (direction == FORWARD) __ add(src, Immediate(0x10)); | |
| 161 if (direction == BACKWARD) __ sub(dst, Immediate(0x10)); | |
| 162 __ movdqa(Operand(dst, 0), xmm0); | |
| 163 if (direction == FORWARD) __ add(dst, Immediate(0x10)); | |
| 164 } | |
| 165 | |
| 166 | 56 |
| 167 void MemMoveEmitPopAndReturn(MacroAssembler* masm) { | 57 void MemMoveEmitPopAndReturn(MacroAssembler* masm) { |
| 168 __ pop(esi); | 58 __ pop(esi); |
| 169 __ pop(edi); | 59 __ pop(edi); |
| 170 __ ret(0); | 60 __ ret(0); |
| 171 } | 61 } |
| 172 | 62 |
| 173 | 63 |
| 174 #undef __ | 64 #undef __ |
| 175 #define __ masm. | 65 #define __ masm. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 203 // Stack layout: | 93 // Stack layout: |
| 204 // esp[12]: Third argument, size. | 94 // esp[12]: Third argument, size. |
| 205 // esp[8]: Second argument, source pointer. | 95 // esp[8]: Second argument, source pointer. |
| 206 // esp[4]: First argument, destination pointer. | 96 // esp[4]: First argument, destination pointer. |
| 207 // esp[0]: return address | 97 // esp[0]: return address |
| 208 | 98 |
| 209 const int kDestinationOffset = 1 * kPointerSize; | 99 const int kDestinationOffset = 1 * kPointerSize; |
| 210 const int kSourceOffset = 2 * kPointerSize; | 100 const int kSourceOffset = 2 * kPointerSize; |
| 211 const int kSizeOffset = 3 * kPointerSize; | 101 const int kSizeOffset = 3 * kPointerSize; |
| 212 | 102 |
| 213 // When copying up to this many bytes, use special "small" handlers. | |
| 214 const size_t kSmallCopySize = 8; | |
| 215 // When copying up to this many bytes, use special "medium" handlers. | |
| 216 const size_t kMediumCopySize = 63; | |
| 217 // When non-overlapping region of src and dst is less than this, | |
| 218 // use a more careful implementation (slightly slower). | |
| 219 const size_t kMinMoveDistance = 16; | |
| 220 // Note that these values are dictated by the implementation below, | |
| 221 // do not just change them and hope things will work! | |
| 222 | |
| 223 int stack_offset = 0; // Update if we change the stack height. | 103 int stack_offset = 0; // Update if we change the stack height. |
| 224 | 104 |
| 225 Label backward, backward_much_overlap; | 105 Label backward, backward_much_overlap; |
| 226 Label forward_much_overlap, small_size, medium_size, pop_and_return; | 106 Label forward_much_overlap, small_size, medium_size, pop_and_return; |
| 227 __ push(edi); | 107 __ push(edi); |
| 228 __ push(esi); | 108 __ push(esi); |
| 229 stack_offset += 2 * kPointerSize; | 109 stack_offset += 2 * kPointerSize; |
| 230 Register dst = edi; | 110 Register dst = edi; |
| 231 Register src = esi; | 111 Register src = esi; |
| 232 Register count = ecx; | 112 Register count = ecx; |
| 233 Register loop_count = edx; | |
| 234 __ mov(dst, Operand(esp, stack_offset + kDestinationOffset)); | 113 __ mov(dst, Operand(esp, stack_offset + kDestinationOffset)); |
| 235 __ mov(src, Operand(esp, stack_offset + kSourceOffset)); | 114 __ mov(src, Operand(esp, stack_offset + kSourceOffset)); |
| 236 __ mov(count, Operand(esp, stack_offset + kSizeOffset)); | 115 __ mov(count, Operand(esp, stack_offset + kSizeOffset)); |
| 237 | 116 |
| 238 __ cmp(dst, src); | 117 __ cmp(dst, src); |
| 239 __ j(equal, &pop_and_return); | 118 __ j(equal, &pop_and_return); |
| 240 | 119 |
| 241 __ prefetch(Operand(src, 0), 1); | 120 // No SSE2. |
| 242 __ cmp(count, kSmallCopySize); | 121 Label forward; |
| 243 __ j(below_equal, &small_size); | 122 __ cmp(count, 0); |
| 244 __ cmp(count, kMediumCopySize); | 123 __ j(equal, &pop_and_return); |
| 245 __ j(below_equal, &medium_size); | |
| 246 __ cmp(dst, src); | 124 __ cmp(dst, src); |
| 247 __ j(above, &backward); | 125 __ j(above, &backward); |
| 248 | 126 __ jmp(&forward); |
| 249 { | 127 { |
| 250 // |dst| is a lower address than |src|. Copy front-to-back. | 128 // Simple forward copier. |
| 251 Label unaligned_source, move_last_15, skip_last_move; | 129 Label forward_loop_1byte, forward_loop_4byte; |
| 252 __ mov(eax, src); | 130 __ bind(&forward_loop_4byte); |
| 253 __ sub(eax, dst); | 131 __ mov(eax, Operand(src, 0)); |
| 254 __ cmp(eax, kMinMoveDistance); | 132 __ sub(count, Immediate(4)); |
| 255 __ j(below, &forward_much_overlap); | 133 __ add(src, Immediate(4)); |
| 256 // Copy first 16 bytes. | 134 __ mov(Operand(dst, 0), eax); |
| 257 __ movdqu(xmm0, Operand(src, 0)); | 135 __ add(dst, Immediate(4)); |
| 258 __ movdqu(Operand(dst, 0), xmm0); | 136 __ bind(&forward); // Entry point. |
| 259 // Determine distance to alignment: 16 - (dst & 0xF). | 137 __ cmp(count, 3); |
| 260 __ mov(edx, dst); | 138 __ j(above, &forward_loop_4byte); |
| 261 __ and_(edx, 0xF); | 139 __ bind(&forward_loop_1byte); |
| 262 __ neg(edx); | 140 __ cmp(count, 0); |
| 263 __ add(edx, Immediate(16)); | 141 __ j(below_equal, &pop_and_return); |
| 264 __ add(dst, edx); | |
| 265 __ add(src, edx); | |
| 266 __ sub(count, edx); | |
| 267 // dst is now aligned. Main copy loop. | |
| 268 __ mov(loop_count, count); | |
| 269 __ shr(loop_count, 6); | |
| 270 // Check if src is also aligned. | |
| 271 __ test(src, Immediate(0xF)); | |
| 272 __ j(not_zero, &unaligned_source); | |
| 273 // Copy loop for aligned source and destination. | |
| 274 MemMoveEmitMainLoop(&masm, &move_last_15, FORWARD, MOVE_ALIGNED); | |
| 275 // At most 15 bytes to copy. Copy 16 bytes at end of string. | |
| 276 __ bind(&move_last_15); | |
| 277 __ and_(count, 0xF); | |
| 278 __ j(zero, &skip_last_move, Label::kNear); | |
| 279 __ movdqu(xmm0, Operand(src, count, times_1, -0x10)); | |
| 280 __ movdqu(Operand(dst, count, times_1, -0x10), xmm0); | |
| 281 __ bind(&skip_last_move); | |
| 282 MemMoveEmitPopAndReturn(&masm); | |
| 283 | |
| 284 // Copy loop for unaligned source and aligned destination. | |
| 285 __ bind(&unaligned_source); | |
| 286 MemMoveEmitMainLoop(&masm, &move_last_15, FORWARD, MOVE_UNALIGNED); | |
| 287 __ jmp(&move_last_15); | |
| 288 | |
| 289 // Less than kMinMoveDistance offset between dst and src. | |
| 290 Label loop_until_aligned, last_15_much_overlap; | |
| 291 __ bind(&loop_until_aligned); | |
| 292 __ mov_b(eax, Operand(src, 0)); | 142 __ mov_b(eax, Operand(src, 0)); |
| 143 __ dec(count); |
| 293 __ inc(src); | 144 __ inc(src); |
| 294 __ mov_b(Operand(dst, 0), eax); | 145 __ mov_b(Operand(dst, 0), eax); |
| 295 __ inc(dst); | 146 __ inc(dst); |
| 296 __ dec(count); | 147 __ jmp(&forward_loop_1byte); |
| 297 __ bind(&forward_much_overlap); // Entry point into this block. | |
| 298 __ test(dst, Immediate(0xF)); | |
| 299 __ j(not_zero, &loop_until_aligned); | |
| 300 // dst is now aligned, src can't be. Main copy loop. | |
| 301 __ mov(loop_count, count); | |
| 302 __ shr(loop_count, 6); | |
| 303 MemMoveEmitMainLoop(&masm, &last_15_much_overlap, | |
| 304 FORWARD, MOVE_UNALIGNED); | |
| 305 __ bind(&last_15_much_overlap); | |
| 306 __ and_(count, 0xF); | |
| 307 __ j(zero, &pop_and_return); | |
| 308 __ cmp(count, kSmallCopySize); | |
| 309 __ j(below_equal, &small_size); | |
| 310 __ jmp(&medium_size); | |
| 311 } | |
| 312 | |
| 313 { | |
| 314 // |dst| is a higher address than |src|. Copy backwards. | |
| 315 Label unaligned_source, move_first_15, skip_last_move; | |
| 316 __ bind(&backward); | |
| 317 // |dst| and |src| always point to the end of what's left to copy. | |
| 318 __ add(dst, count); | |
| 319 __ add(src, count); | |
| 320 __ mov(eax, dst); | |
| 321 __ sub(eax, src); | |
| 322 __ cmp(eax, kMinMoveDistance); | |
| 323 __ j(below, &backward_much_overlap); | |
| 324 // Copy last 16 bytes. | |
| 325 __ movdqu(xmm0, Operand(src, -0x10)); | |
| 326 __ movdqu(Operand(dst, -0x10), xmm0); | |
| 327 // Find distance to alignment: dst & 0xF | |
| 328 __ mov(edx, dst); | |
| 329 __ and_(edx, 0xF); | |
| 330 __ sub(dst, edx); | |
| 331 __ sub(src, edx); | |
| 332 __ sub(count, edx); | |
| 333 // dst is now aligned. Main copy loop. | |
| 334 __ mov(loop_count, count); | |
| 335 __ shr(loop_count, 6); | |
| 336 // Check if src is also aligned. | |
| 337 __ test(src, Immediate(0xF)); | |
| 338 __ j(not_zero, &unaligned_source); | |
| 339 // Copy loop for aligned source and destination. | |
| 340 MemMoveEmitMainLoop(&masm, &move_first_15, BACKWARD, MOVE_ALIGNED); | |
| 341 // At most 15 bytes to copy. Copy 16 bytes at beginning of string. | |
| 342 __ bind(&move_first_15); | |
| 343 __ and_(count, 0xF); | |
| 344 __ j(zero, &skip_last_move, Label::kNear); | |
| 345 __ sub(src, count); | |
| 346 __ sub(dst, count); | |
| 347 __ movdqu(xmm0, Operand(src, 0)); | |
| 348 __ movdqu(Operand(dst, 0), xmm0); | |
| 349 __ bind(&skip_last_move); | |
| 350 MemMoveEmitPopAndReturn(&masm); | |
| 351 | |
| 352 // Copy loop for unaligned source and aligned destination. | |
| 353 __ bind(&unaligned_source); | |
| 354 MemMoveEmitMainLoop(&masm, &move_first_15, BACKWARD, MOVE_UNALIGNED); | |
| 355 __ jmp(&move_first_15); | |
| 356 | |
| 357 // Less than kMinMoveDistance offset between dst and src. | |
| 358 Label loop_until_aligned, first_15_much_overlap; | |
| 359 __ bind(&loop_until_aligned); | |
| 360 __ dec(src); | |
| 361 __ dec(dst); | |
| 362 __ mov_b(eax, Operand(src, 0)); | |
| 363 __ mov_b(Operand(dst, 0), eax); | |
| 364 __ dec(count); | |
| 365 __ bind(&backward_much_overlap); // Entry point into this block. | |
| 366 __ test(dst, Immediate(0xF)); | |
| 367 __ j(not_zero, &loop_until_aligned); | |
| 368 // dst is now aligned, src can't be. Main copy loop. | |
| 369 __ mov(loop_count, count); | |
| 370 __ shr(loop_count, 6); | |
| 371 MemMoveEmitMainLoop(&masm, &first_15_much_overlap, | |
| 372 BACKWARD, MOVE_UNALIGNED); | |
| 373 __ bind(&first_15_much_overlap); | |
| 374 __ and_(count, 0xF); | |
| 375 __ j(zero, &pop_and_return); | |
| 376 // Small/medium handlers expect dst/src to point to the beginning. | |
| 377 __ sub(dst, count); | |
| 378 __ sub(src, count); | |
| 379 __ cmp(count, kSmallCopySize); | |
| 380 __ j(below_equal, &small_size); | |
| 381 __ jmp(&medium_size); | |
| 382 } | 148 } |
| 383 { | 149 { |
| 384 // Special handlers for 9 <= copy_size < 64. No assumptions about | 150 // Simple backward copier. |
| 385 // alignment or move distance, so all reads must be unaligned and | 151 Label backward_loop_1byte, backward_loop_4byte, entry_shortcut; |
| 386 // must happen before any writes. | 152 __ bind(&backward); |
| 387 Label medium_handlers, f9_16, f17_32, f33_48, f49_63; | 153 __ add(src, count); |
| 154 __ add(dst, count); |
| 155 __ cmp(count, 3); |
| 156 __ j(below_equal, &entry_shortcut); |
| 388 | 157 |
| 389 __ bind(&f9_16); | 158 __ bind(&backward_loop_4byte); |
| 390 __ movsd(xmm0, Operand(src, 0)); | 159 __ sub(src, Immediate(4)); |
| 391 __ movsd(xmm1, Operand(src, count, times_1, -8)); | 160 __ sub(count, Immediate(4)); |
| 392 __ movsd(Operand(dst, 0), xmm0); | 161 __ mov(eax, Operand(src, 0)); |
| 393 __ movsd(Operand(dst, count, times_1, -8), xmm1); | 162 __ sub(dst, Immediate(4)); |
| 394 MemMoveEmitPopAndReturn(&masm); | 163 __ mov(Operand(dst, 0), eax); |
| 395 | 164 __ cmp(count, 3); |
| 396 __ bind(&f17_32); | 165 __ j(above, &backward_loop_4byte); |
| 397 __ movdqu(xmm0, Operand(src, 0)); | 166 __ bind(&backward_loop_1byte); |
| 398 __ movdqu(xmm1, Operand(src, count, times_1, -0x10)); | 167 __ cmp(count, 0); |
| 399 __ movdqu(Operand(dst, 0x00), xmm0); | 168 __ j(below_equal, &pop_and_return); |
| 400 __ movdqu(Operand(dst, count, times_1, -0x10), xmm1); | 169 __ bind(&entry_shortcut); |
| 401 MemMoveEmitPopAndReturn(&masm); | 170 __ dec(src); |
| 402 | 171 __ dec(count); |
| 403 __ bind(&f33_48); | |
| 404 __ movdqu(xmm0, Operand(src, 0x00)); | |
| 405 __ movdqu(xmm1, Operand(src, 0x10)); | |
| 406 __ movdqu(xmm2, Operand(src, count, times_1, -0x10)); | |
| 407 __ movdqu(Operand(dst, 0x00), xmm0); | |
| 408 __ movdqu(Operand(dst, 0x10), xmm1); | |
| 409 __ movdqu(Operand(dst, count, times_1, -0x10), xmm2); | |
| 410 MemMoveEmitPopAndReturn(&masm); | |
| 411 | |
| 412 __ bind(&f49_63); | |
| 413 __ movdqu(xmm0, Operand(src, 0x00)); | |
| 414 __ movdqu(xmm1, Operand(src, 0x10)); | |
| 415 __ movdqu(xmm2, Operand(src, 0x20)); | |
| 416 __ movdqu(xmm3, Operand(src, count, times_1, -0x10)); | |
| 417 __ movdqu(Operand(dst, 0x00), xmm0); | |
| 418 __ movdqu(Operand(dst, 0x10), xmm1); | |
| 419 __ movdqu(Operand(dst, 0x20), xmm2); | |
| 420 __ movdqu(Operand(dst, count, times_1, -0x10), xmm3); | |
| 421 MemMoveEmitPopAndReturn(&masm); | |
| 422 | |
| 423 __ bind(&medium_handlers); | |
| 424 __ dd(conv.address(&f9_16)); | |
| 425 __ dd(conv.address(&f17_32)); | |
| 426 __ dd(conv.address(&f33_48)); | |
| 427 __ dd(conv.address(&f49_63)); | |
| 428 | |
| 429 __ bind(&medium_size); // Entry point into this block. | |
| 430 __ mov(eax, count); | |
| 431 __ dec(eax); | |
| 432 __ shr(eax, 4); | |
| 433 if (FLAG_debug_code) { | |
| 434 Label ok; | |
| 435 __ cmp(eax, 3); | |
| 436 __ j(below_equal, &ok); | |
| 437 __ int3(); | |
| 438 __ bind(&ok); | |
| 439 } | |
| 440 __ mov(eax, Operand(eax, times_4, conv.address(&medium_handlers))); | |
| 441 __ jmp(eax); | |
| 442 } | |
| 443 { | |
| 444 // Specialized copiers for copy_size <= 8 bytes. | |
| 445 Label small_handlers, f0, f1, f2, f3, f4, f5_8; | |
| 446 __ bind(&f0); | |
| 447 MemMoveEmitPopAndReturn(&masm); | |
| 448 | |
| 449 __ bind(&f1); | |
| 450 __ mov_b(eax, Operand(src, 0)); | 172 __ mov_b(eax, Operand(src, 0)); |
| 173 __ dec(dst); |
| 451 __ mov_b(Operand(dst, 0), eax); | 174 __ mov_b(Operand(dst, 0), eax); |
| 452 MemMoveEmitPopAndReturn(&masm); | 175 __ jmp(&backward_loop_1byte); |
| 453 | |
| 454 __ bind(&f2); | |
| 455 __ mov_w(eax, Operand(src, 0)); | |
| 456 __ mov_w(Operand(dst, 0), eax); | |
| 457 MemMoveEmitPopAndReturn(&masm); | |
| 458 | |
| 459 __ bind(&f3); | |
| 460 __ mov_w(eax, Operand(src, 0)); | |
| 461 __ mov_b(edx, Operand(src, 2)); | |
| 462 __ mov_w(Operand(dst, 0), eax); | |
| 463 __ mov_b(Operand(dst, 2), edx); | |
| 464 MemMoveEmitPopAndReturn(&masm); | |
| 465 | |
| 466 __ bind(&f4); | |
| 467 __ mov(eax, Operand(src, 0)); | |
| 468 __ mov(Operand(dst, 0), eax); | |
| 469 MemMoveEmitPopAndReturn(&masm); | |
| 470 | |
| 471 __ bind(&f5_8); | |
| 472 __ mov(eax, Operand(src, 0)); | |
| 473 __ mov(edx, Operand(src, count, times_1, -4)); | |
| 474 __ mov(Operand(dst, 0), eax); | |
| 475 __ mov(Operand(dst, count, times_1, -4), edx); | |
| 476 MemMoveEmitPopAndReturn(&masm); | |
| 477 | |
| 478 __ bind(&small_handlers); | |
| 479 __ dd(conv.address(&f0)); | |
| 480 __ dd(conv.address(&f1)); | |
| 481 __ dd(conv.address(&f2)); | |
| 482 __ dd(conv.address(&f3)); | |
| 483 __ dd(conv.address(&f4)); | |
| 484 __ dd(conv.address(&f5_8)); | |
| 485 __ dd(conv.address(&f5_8)); | |
| 486 __ dd(conv.address(&f5_8)); | |
| 487 __ dd(conv.address(&f5_8)); | |
| 488 | |
| 489 __ bind(&small_size); // Entry point into this block. | |
| 490 if (FLAG_debug_code) { | |
| 491 Label ok; | |
| 492 __ cmp(count, 8); | |
| 493 __ j(below_equal, &ok); | |
| 494 __ int3(); | |
| 495 __ bind(&ok); | |
| 496 } | |
| 497 __ mov(eax, Operand(count, times_4, conv.address(&small_handlers))); | |
| 498 __ jmp(eax); | |
| 499 } | 176 } |
| 500 | 177 |
| 501 __ bind(&pop_and_return); | 178 __ bind(&pop_and_return); |
| 502 MemMoveEmitPopAndReturn(&masm); | 179 MemMoveEmitPopAndReturn(&masm); |
| 503 | 180 |
| 504 CodeDesc desc; | 181 CodeDesc desc; |
| 505 masm.GetCode(&desc); | 182 masm.GetCode(&desc); |
| 506 ASSERT(!RelocInfo::RequiresRelocation(desc)); | 183 ASSERT(!RelocInfo::RequiresRelocation(desc)); |
| 507 CPU::FlushICache(buffer, actual_size); | 184 CPU::FlushICache(buffer, actual_size); |
| 508 OS::ProtectCode(buffer, actual_size); | 185 OS::ProtectCode(buffer, actual_size); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 534 ASSERT(allocation_memento_found != NULL); | 211 ASSERT(allocation_memento_found != NULL); |
| 535 __ JumpIfJSArrayHasAllocationMemento(edx, edi, allocation_memento_found); | 212 __ JumpIfJSArrayHasAllocationMemento(edx, edi, allocation_memento_found); |
| 536 } | 213 } |
| 537 | 214 |
| 538 // Set transitioned map. | 215 // Set transitioned map. |
| 539 __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx); | 216 __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx); |
| 540 __ RecordWriteField(edx, | 217 __ RecordWriteField(edx, |
| 541 HeapObject::kMapOffset, | 218 HeapObject::kMapOffset, |
| 542 ebx, | 219 ebx, |
| 543 edi, | 220 edi, |
| 544 kDontSaveFPRegs, | |
| 545 EMIT_REMEMBERED_SET, | 221 EMIT_REMEMBERED_SET, |
| 546 OMIT_SMI_CHECK); | 222 OMIT_SMI_CHECK); |
| 547 } | 223 } |
| 548 | 224 |
| 549 | 225 |
| 550 void ElementsTransitionGenerator::GenerateSmiToDouble( | 226 void ElementsTransitionGenerator::GenerateSmiToDouble( |
| 551 MacroAssembler* masm, AllocationSiteMode mode, Label* fail) { | 227 MacroAssembler* masm, AllocationSiteMode mode, Label* fail) { |
| 552 // ----------- S t a t e ------------- | 228 // ----------- S t a t e ------------- |
| 553 // -- eax : value | 229 // -- eax : value |
| 554 // -- ebx : target map | 230 // -- ebx : target map |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 Immediate(masm->isolate()->factory()->fixed_double_array_map())); | 264 Immediate(masm->isolate()->factory()->fixed_double_array_map())); |
| 589 __ mov(FieldOperand(eax, FixedDoubleArray::kLengthOffset), edi); | 265 __ mov(FieldOperand(eax, FixedDoubleArray::kLengthOffset), edi); |
| 590 __ mov(esi, FieldOperand(edx, JSObject::kElementsOffset)); | 266 __ mov(esi, FieldOperand(edx, JSObject::kElementsOffset)); |
| 591 // Replace receiver's backing store with newly created FixedDoubleArray. | 267 // Replace receiver's backing store with newly created FixedDoubleArray. |
| 592 __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax); | 268 __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax); |
| 593 __ mov(ebx, eax); | 269 __ mov(ebx, eax); |
| 594 __ RecordWriteField(edx, | 270 __ RecordWriteField(edx, |
| 595 JSObject::kElementsOffset, | 271 JSObject::kElementsOffset, |
| 596 ebx, | 272 ebx, |
| 597 edi, | 273 edi, |
| 598 kDontSaveFPRegs, | |
| 599 EMIT_REMEMBERED_SET, | 274 EMIT_REMEMBERED_SET, |
| 600 OMIT_SMI_CHECK); | 275 OMIT_SMI_CHECK); |
| 601 | 276 |
| 602 __ mov(edi, FieldOperand(esi, FixedArray::kLengthOffset)); | 277 __ mov(edi, FieldOperand(esi, FixedArray::kLengthOffset)); |
| 603 | 278 |
| 604 // Prepare for conversion loop. | 279 // Prepare for conversion loop. |
| 605 ExternalReference canonical_the_hole_nan_reference = | 280 ExternalReference canonical_the_hole_nan_reference = |
| 606 ExternalReference::address_of_the_hole_nan(); | 281 ExternalReference::address_of_the_hole_nan(); |
| 607 XMMRegister the_hole_nan = xmm1; | |
| 608 __ movsd(the_hole_nan, | |
| 609 Operand::StaticVariable(canonical_the_hole_nan_reference)); | |
| 610 __ jmp(&entry); | 282 __ jmp(&entry); |
| 611 | 283 |
| 612 // Call into runtime if GC is required. | 284 // Call into runtime if GC is required. |
| 613 __ bind(&gc_required); | 285 __ bind(&gc_required); |
| 614 // Restore registers before jumping into runtime. | 286 // Restore registers before jumping into runtime. |
| 615 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 287 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 616 __ pop(ebx); | 288 __ pop(ebx); |
| 617 __ pop(eax); | 289 __ pop(eax); |
| 618 __ jmp(fail); | 290 __ jmp(fail); |
| 619 | 291 |
| 620 // Convert and copy elements | 292 // Convert and copy elements |
| 621 // esi: source FixedArray | 293 // esi: source FixedArray |
| 622 __ bind(&loop); | 294 __ bind(&loop); |
| 623 __ mov(ebx, FieldOperand(esi, edi, times_2, FixedArray::kHeaderSize)); | 295 __ mov(ebx, FieldOperand(esi, edi, times_2, FixedArray::kHeaderSize)); |
| 624 // ebx: current element from source | 296 // ebx: current element from source |
| 625 // edi: index of current element | 297 // edi: index of current element |
| 626 __ JumpIfNotSmi(ebx, &convert_hole); | 298 __ JumpIfNotSmi(ebx, &convert_hole); |
| 627 | 299 |
| 628 // Normal smi, convert it to double and store. | 300 // Normal smi, convert it to double and store. |
| 629 __ SmiUntag(ebx); | 301 __ SmiUntag(ebx); |
| 630 __ Cvtsi2sd(xmm0, ebx); | 302 __ push(ebx); |
| 631 __ movsd(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize), | 303 __ fild_s(Operand(esp, 0)); |
| 632 xmm0); | 304 __ pop(ebx); |
| 305 __ fstp_d(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize)); |
| 633 __ jmp(&entry); | 306 __ jmp(&entry); |
| 634 | 307 |
| 635 // Found hole, store hole_nan_as_double instead. | 308 // Found hole, store hole_nan_as_double instead. |
| 636 __ bind(&convert_hole); | 309 __ bind(&convert_hole); |
| 637 | 310 |
| 638 if (FLAG_debug_code) { | 311 if (FLAG_debug_code) { |
| 639 __ cmp(ebx, masm->isolate()->factory()->the_hole_value()); | 312 __ cmp(ebx, masm->isolate()->factory()->the_hole_value()); |
| 640 __ Assert(equal, kObjectFoundInSmiOnlyArray); | 313 __ Assert(equal, kObjectFoundInSmiOnlyArray); |
| 641 } | 314 } |
| 642 | 315 |
| 643 __ movsd(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize), | 316 __ fld_d(Operand::StaticVariable(canonical_the_hole_nan_reference)); |
| 644 the_hole_nan); | 317 __ fstp_d(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize)); |
| 645 | 318 |
| 646 __ bind(&entry); | 319 __ bind(&entry); |
| 647 __ sub(edi, Immediate(Smi::FromInt(1))); | 320 __ sub(edi, Immediate(Smi::FromInt(1))); |
| 648 __ j(not_sign, &loop); | 321 __ j(not_sign, &loop); |
| 649 | 322 |
| 650 __ pop(ebx); | 323 __ pop(ebx); |
| 651 __ pop(eax); | 324 __ pop(eax); |
| 652 | 325 |
| 653 // Restore esi. | 326 // Restore esi. |
| 654 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 327 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 655 | 328 |
| 656 __ bind(&only_change_map); | 329 __ bind(&only_change_map); |
| 657 // eax: value | 330 // eax: value |
| 658 // ebx: target map | 331 // ebx: target map |
| 659 // Set transitioned map. | 332 // Set transitioned map. |
| 660 __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx); | 333 __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx); |
| 661 __ RecordWriteField(edx, | 334 __ RecordWriteField(edx, |
| 662 HeapObject::kMapOffset, | 335 HeapObject::kMapOffset, |
| 663 ebx, | 336 ebx, |
| 664 edi, | 337 edi, |
| 665 kDontSaveFPRegs, | |
| 666 OMIT_REMEMBERED_SET, | 338 OMIT_REMEMBERED_SET, |
| 667 OMIT_SMI_CHECK); | 339 OMIT_SMI_CHECK); |
| 668 } | 340 } |
| 669 | 341 |
| 670 | 342 |
| 671 void ElementsTransitionGenerator::GenerateDoubleToObject( | 343 void ElementsTransitionGenerator::GenerateDoubleToObject( |
| 672 MacroAssembler* masm, AllocationSiteMode mode, Label* fail) { | 344 MacroAssembler* masm, AllocationSiteMode mode, Label* fail) { |
| 673 // ----------- S t a t e ------------- | 345 // ----------- S t a t e ------------- |
| 674 // -- eax : value | 346 // -- eax : value |
| 675 // -- ebx : target map | 347 // -- ebx : target map |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 711 | 383 |
| 712 // ebx: target map | 384 // ebx: target map |
| 713 // edx: receiver | 385 // edx: receiver |
| 714 // Set transitioned map. | 386 // Set transitioned map. |
| 715 __ bind(&only_change_map); | 387 __ bind(&only_change_map); |
| 716 __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx); | 388 __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx); |
| 717 __ RecordWriteField(edx, | 389 __ RecordWriteField(edx, |
| 718 HeapObject::kMapOffset, | 390 HeapObject::kMapOffset, |
| 719 ebx, | 391 ebx, |
| 720 edi, | 392 edi, |
| 721 kDontSaveFPRegs, | |
| 722 OMIT_REMEMBERED_SET, | 393 OMIT_REMEMBERED_SET, |
| 723 OMIT_SMI_CHECK); | 394 OMIT_SMI_CHECK); |
| 724 __ jmp(&success); | 395 __ jmp(&success); |
| 725 | 396 |
| 726 // Call into runtime if GC is required. | 397 // Call into runtime if GC is required. |
| 727 __ bind(&gc_required); | 398 __ bind(&gc_required); |
| 728 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 399 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 729 __ pop(ebx); | 400 __ pop(ebx); |
| 730 __ pop(edx); | 401 __ pop(edx); |
| 731 __ pop(eax); | 402 __ pop(eax); |
| 732 __ jmp(fail); | 403 __ jmp(fail); |
| 733 | 404 |
| 734 // Box doubles into heap numbers. | 405 // Box doubles into heap numbers. |
| 735 // edi: source FixedDoubleArray | 406 // edi: source FixedDoubleArray |
| 736 // eax: destination FixedArray | 407 // eax: destination FixedArray |
| 737 __ bind(&loop); | 408 __ bind(&loop); |
| 738 // ebx: index of current element (smi-tagged) | 409 // ebx: index of current element (smi-tagged) |
| 739 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); | 410 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); |
| 740 __ cmp(FieldOperand(edi, ebx, times_4, offset), Immediate(kHoleNanUpper32)); | 411 __ cmp(FieldOperand(edi, ebx, times_4, offset), Immediate(kHoleNanUpper32)); |
| 741 __ j(equal, &convert_hole); | 412 __ j(equal, &convert_hole); |
| 742 | 413 |
| 743 // Non-hole double, copy value into a heap number. | 414 // Non-hole double, copy value into a heap number. |
| 744 __ AllocateHeapNumber(edx, esi, no_reg, &gc_required); | 415 __ AllocateHeapNumber(edx, esi, no_reg, &gc_required); |
| 745 // edx: new heap number | 416 // edx: new heap number |
| 746 __ movsd(xmm0, | 417 __ mov(esi, FieldOperand(edi, ebx, times_4, FixedDoubleArray::kHeaderSize)); |
| 747 FieldOperand(edi, ebx, times_4, FixedDoubleArray::kHeaderSize)); | 418 __ mov(FieldOperand(edx, HeapNumber::kValueOffset), esi); |
| 748 __ movsd(FieldOperand(edx, HeapNumber::kValueOffset), xmm0); | 419 __ mov(esi, FieldOperand(edi, ebx, times_4, offset)); |
| 420 __ mov(FieldOperand(edx, HeapNumber::kValueOffset + kPointerSize), esi); |
| 749 __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize), edx); | 421 __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize), edx); |
| 750 __ mov(esi, ebx); | 422 __ mov(esi, ebx); |
| 751 __ RecordWriteArray(eax, | 423 __ RecordWriteArray(eax, |
| 752 edx, | 424 edx, |
| 753 esi, | 425 esi, |
| 754 kDontSaveFPRegs, | |
| 755 EMIT_REMEMBERED_SET, | 426 EMIT_REMEMBERED_SET, |
| 756 OMIT_SMI_CHECK); | 427 OMIT_SMI_CHECK); |
| 757 __ jmp(&entry, Label::kNear); | 428 __ jmp(&entry, Label::kNear); |
| 758 | 429 |
| 759 // Replace the-hole NaN with the-hole pointer. | 430 // Replace the-hole NaN with the-hole pointer. |
| 760 __ bind(&convert_hole); | 431 __ bind(&convert_hole); |
| 761 __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize), | 432 __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize), |
| 762 masm->isolate()->factory()->the_hole_value()); | 433 masm->isolate()->factory()->the_hole_value()); |
| 763 | 434 |
| 764 __ bind(&entry); | 435 __ bind(&entry); |
| 765 __ sub(ebx, Immediate(Smi::FromInt(1))); | 436 __ sub(ebx, Immediate(Smi::FromInt(1))); |
| 766 __ j(not_sign, &loop); | 437 __ j(not_sign, &loop); |
| 767 | 438 |
| 768 __ pop(ebx); | 439 __ pop(ebx); |
| 769 __ pop(edx); | 440 __ pop(edx); |
| 770 // ebx: target map | 441 // ebx: target map |
| 771 // edx: receiver | 442 // edx: receiver |
| 772 // Set transitioned map. | 443 // Set transitioned map. |
| 773 __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx); | 444 __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx); |
| 774 __ RecordWriteField(edx, | 445 __ RecordWriteField(edx, |
| 775 HeapObject::kMapOffset, | 446 HeapObject::kMapOffset, |
| 776 ebx, | 447 ebx, |
| 777 edi, | 448 edi, |
| 778 kDontSaveFPRegs, | |
| 779 OMIT_REMEMBERED_SET, | 449 OMIT_REMEMBERED_SET, |
| 780 OMIT_SMI_CHECK); | 450 OMIT_SMI_CHECK); |
| 781 // Replace receiver's backing store with newly created and filled FixedArray. | 451 // Replace receiver's backing store with newly created and filled FixedArray. |
| 782 __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax); | 452 __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax); |
| 783 __ RecordWriteField(edx, | 453 __ RecordWriteField(edx, |
| 784 JSObject::kElementsOffset, | 454 JSObject::kElementsOffset, |
| 785 eax, | 455 eax, |
| 786 edi, | 456 edi, |
| 787 kDontSaveFPRegs, | |
| 788 EMIT_REMEMBERED_SET, | 457 EMIT_REMEMBERED_SET, |
| 789 OMIT_SMI_CHECK); | 458 OMIT_SMI_CHECK); |
| 790 | 459 |
| 791 // Restore registers. | 460 // Restore registers. |
| 792 __ pop(eax); | 461 __ pop(eax); |
| 793 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 462 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 794 | 463 |
| 795 __ bind(&success); | 464 __ bind(&success); |
| 796 } | 465 } |
| 797 | 466 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 // Load the byte into the result register. | 562 // Load the byte into the result register. |
| 894 __ bind(&ascii); | 563 __ bind(&ascii); |
| 895 __ movzx_b(result, FieldOperand(string, | 564 __ movzx_b(result, FieldOperand(string, |
| 896 index, | 565 index, |
| 897 times_1, | 566 times_1, |
| 898 SeqOneByteString::kHeaderSize)); | 567 SeqOneByteString::kHeaderSize)); |
| 899 __ bind(&done); | 568 __ bind(&done); |
| 900 } | 569 } |
| 901 | 570 |
| 902 | 571 |
| 903 static Operand ExpConstant(int index) { | |
| 904 return Operand::StaticVariable(ExternalReference::math_exp_constants(index)); | |
| 905 } | |
| 906 | |
| 907 | |
| 908 void MathExpGenerator::EmitMathExp(MacroAssembler* masm, | |
| 909 XMMRegister input, | |
| 910 XMMRegister result, | |
| 911 XMMRegister double_scratch, | |
| 912 Register temp1, | |
| 913 Register temp2) { | |
| 914 ASSERT(!input.is(double_scratch)); | |
| 915 ASSERT(!input.is(result)); | |
| 916 ASSERT(!result.is(double_scratch)); | |
| 917 ASSERT(!temp1.is(temp2)); | |
| 918 ASSERT(ExternalReference::math_exp_constants(0).address() != NULL); | |
| 919 | |
| 920 Label done; | |
| 921 | |
| 922 __ movsd(double_scratch, ExpConstant(0)); | |
| 923 __ xorpd(result, result); | |
| 924 __ ucomisd(double_scratch, input); | |
| 925 __ j(above_equal, &done); | |
| 926 __ ucomisd(input, ExpConstant(1)); | |
| 927 __ movsd(result, ExpConstant(2)); | |
| 928 __ j(above_equal, &done); | |
| 929 __ movsd(double_scratch, ExpConstant(3)); | |
| 930 __ movsd(result, ExpConstant(4)); | |
| 931 __ mulsd(double_scratch, input); | |
| 932 __ addsd(double_scratch, result); | |
| 933 __ movd(temp2, double_scratch); | |
| 934 __ subsd(double_scratch, result); | |
| 935 __ movsd(result, ExpConstant(6)); | |
| 936 __ mulsd(double_scratch, ExpConstant(5)); | |
| 937 __ subsd(double_scratch, input); | |
| 938 __ subsd(result, double_scratch); | |
| 939 __ movsd(input, double_scratch); | |
| 940 __ mulsd(input, double_scratch); | |
| 941 __ mulsd(result, input); | |
| 942 __ mov(temp1, temp2); | |
| 943 __ mulsd(result, ExpConstant(7)); | |
| 944 __ subsd(result, double_scratch); | |
| 945 __ add(temp1, Immediate(0x1ff800)); | |
| 946 __ addsd(result, ExpConstant(8)); | |
| 947 __ and_(temp2, Immediate(0x7ff)); | |
| 948 __ shr(temp1, 11); | |
| 949 __ shl(temp1, 20); | |
| 950 __ movd(input, temp1); | |
| 951 __ pshufd(input, input, static_cast<uint8_t>(0xe1)); // Order: 11 10 00 01 | |
| 952 __ movsd(double_scratch, Operand::StaticArray( | |
| 953 temp2, times_8, ExternalReference::math_exp_log_table())); | |
| 954 __ orps(input, double_scratch); | |
| 955 __ mulsd(result, input); | |
| 956 __ bind(&done); | |
| 957 } | |
| 958 | |
| 959 #undef __ | 572 #undef __ |
| 960 | 573 |
| 961 | 574 |
| 962 CodeAgingHelper::CodeAgingHelper() { | 575 CodeAgingHelper::CodeAgingHelper() { |
| 963 ASSERT(young_sequence_.length() == kNoCodeAgeSequenceLength); | 576 ASSERT(young_sequence_.length() == kNoCodeAgeSequenceLength); |
| 964 CodePatcher patcher(young_sequence_.start(), young_sequence_.length()); | 577 CodePatcher patcher(young_sequence_.start(), young_sequence_.length()); |
| 965 patcher.masm()->push(ebp); | 578 patcher.masm()->push(ebp); |
| 966 patcher.masm()->mov(ebp, esp); | 579 patcher.masm()->mov(ebp, esp); |
| 967 patcher.masm()->push(esi); | 580 patcher.masm()->push(esi); |
| 968 patcher.masm()->push(edi); | 581 patcher.masm()->push(edi); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1009 } else { | 622 } else { |
| 1010 Code* stub = GetCodeAgeStub(isolate, age, parity); | 623 Code* stub = GetCodeAgeStub(isolate, age, parity); |
| 1011 CodePatcher patcher(sequence, young_length); | 624 CodePatcher patcher(sequence, young_length); |
| 1012 patcher.masm()->call(stub->instruction_start(), RelocInfo::NONE32); | 625 patcher.masm()->call(stub->instruction_start(), RelocInfo::NONE32); |
| 1013 } | 626 } |
| 1014 } | 627 } |
| 1015 | 628 |
| 1016 | 629 |
| 1017 } } // namespace v8::internal | 630 } } // namespace v8::internal |
| 1018 | 631 |
| 1019 #endif // V8_TARGET_ARCH_IA32 | 632 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |