OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 CPU::FlushICache(buffer, actual_size); | 170 CPU::FlushICache(buffer, actual_size); |
171 OS::ProtectCode(buffer, actual_size); | 171 OS::ProtectCode(buffer, actual_size); |
172 return FUNCTION_CAST<UnaryMathFunction>(buffer); | 172 return FUNCTION_CAST<UnaryMathFunction>(buffer); |
173 } | 173 } |
174 | 174 |
175 | 175 |
176 // Helper functions for CreateMemMoveFunction. | 176 // Helper functions for CreateMemMoveFunction. |
177 #undef __ | 177 #undef __ |
178 #define __ ACCESS_MASM(masm) | 178 #define __ ACCESS_MASM(masm) |
179 | 179 |
180 // Keep around global pointers to these objects so that Valgrind won't complain. | |
181 static size_t* medium_handlers = NULL; | |
182 static size_t* small_handlers = NULL; | |
183 | |
184 | |
185 enum Direction { FORWARD, BACKWARD }; | 180 enum Direction { FORWARD, BACKWARD }; |
186 enum Alignment { MOVE_ALIGNED, MOVE_UNALIGNED }; | 181 enum Alignment { MOVE_ALIGNED, MOVE_UNALIGNED }; |
187 | 182 |
188 // Expects registers: | 183 // Expects registers: |
189 // esi - source, aligned if alignment == ALIGNED | 184 // esi - source, aligned if alignment == ALIGNED |
190 // edi - destination, always aligned | 185 // edi - destination, always aligned |
191 // ecx - count (copy size in bytes) | 186 // ecx - count (copy size in bytes) |
192 // edx - loop count (number of 64 byte chunks) | 187 // edx - loop count (number of 64 byte chunks) |
193 void MemMoveEmitMainLoop(MacroAssembler* masm, | 188 void MemMoveEmitMainLoop(MacroAssembler* masm, |
194 Label* move_last_15, | 189 Label* move_last_15, |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 __ pop(esi); | 241 __ pop(esi); |
247 __ pop(edi); | 242 __ pop(edi); |
248 __ ret(0); | 243 __ ret(0); |
249 } | 244 } |
250 | 245 |
251 | 246 |
252 #undef __ | 247 #undef __ |
253 #define __ masm. | 248 #define __ masm. |
254 | 249 |
255 | 250 |
| 251 class LabelConverter { |
| 252 public: |
| 253 explicit LabelConverter(byte* buffer) : buffer_(buffer) {} |
| 254 int32_t address(Label* l) const { |
| 255 return reinterpret_cast<int32_t>(buffer_) + l->pos(); |
| 256 } |
| 257 private: |
| 258 byte* buffer_; |
| 259 }; |
| 260 |
| 261 |
256 OS::MemMoveFunction CreateMemMoveFunction() { | 262 OS::MemMoveFunction CreateMemMoveFunction() { |
257 size_t actual_size; | 263 size_t actual_size; |
258 // Allocate buffer in executable space. | 264 // Allocate buffer in executable space. |
259 byte* buffer = static_cast<byte*>(OS::Allocate(1 * KB, &actual_size, true)); | 265 byte* buffer = static_cast<byte*>(OS::Allocate(1 * KB, &actual_size, true)); |
260 if (buffer == NULL) return NULL; | 266 if (buffer == NULL) return NULL; |
261 MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size)); | 267 MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size)); |
| 268 LabelConverter conv(buffer); |
262 | 269 |
263 // Generated code is put into a fixed, unmovable buffer, and not into | 270 // Generated code is put into a fixed, unmovable buffer, and not into |
264 // the V8 heap. We can't, and don't, refer to any relocatable addresses | 271 // the V8 heap. We can't, and don't, refer to any relocatable addresses |
265 // (e.g. the JavaScript nan-object). | 272 // (e.g. the JavaScript nan-object). |
266 | 273 |
267 // 32-bit C declaration function calls pass arguments on stack. | 274 // 32-bit C declaration function calls pass arguments on stack. |
268 | 275 |
269 // Stack layout: | 276 // Stack layout: |
270 // esp[12]: Third argument, size. | 277 // esp[12]: Third argument, size. |
271 // esp[8]: Second argument, source pointer. | 278 // esp[8]: Second argument, source pointer. |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 __ sub(dst, count); | 452 __ sub(dst, count); |
446 __ sub(src, count); | 453 __ sub(src, count); |
447 __ cmp(count, kSmallCopySize); | 454 __ cmp(count, kSmallCopySize); |
448 __ j(below_equal, &small_size); | 455 __ j(below_equal, &small_size); |
449 __ jmp(&medium_size); | 456 __ jmp(&medium_size); |
450 } | 457 } |
451 { | 458 { |
452 // Special handlers for 9 <= copy_size < 64. No assumptions about | 459 // Special handlers for 9 <= copy_size < 64. No assumptions about |
453 // alignment or move distance, so all reads must be unaligned and | 460 // alignment or move distance, so all reads must be unaligned and |
454 // must happen before any writes. | 461 // must happen before any writes. |
455 Label f9_16, f17_32, f33_48, f49_63; | 462 Label medium_handlers, f9_16, f17_32, f33_48, f49_63; |
456 | 463 |
457 __ bind(&f9_16); | 464 __ bind(&f9_16); |
458 __ movdbl(xmm0, Operand(src, 0)); | 465 __ movdbl(xmm0, Operand(src, 0)); |
459 __ movdbl(xmm1, Operand(src, count, times_1, -8)); | 466 __ movdbl(xmm1, Operand(src, count, times_1, -8)); |
460 __ movdbl(Operand(dst, 0), xmm0); | 467 __ movdbl(Operand(dst, 0), xmm0); |
461 __ movdbl(Operand(dst, count, times_1, -8), xmm1); | 468 __ movdbl(Operand(dst, count, times_1, -8), xmm1); |
462 MemMoveEmitPopAndReturn(&masm); | 469 MemMoveEmitPopAndReturn(&masm); |
463 | 470 |
464 __ bind(&f17_32); | 471 __ bind(&f17_32); |
465 __ movdqu(xmm0, Operand(src, 0)); | 472 __ movdqu(xmm0, Operand(src, 0)); |
(...skipping 15 matching lines...) Expand all Loading... |
481 __ movdqu(xmm0, Operand(src, 0x00)); | 488 __ movdqu(xmm0, Operand(src, 0x00)); |
482 __ movdqu(xmm1, Operand(src, 0x10)); | 489 __ movdqu(xmm1, Operand(src, 0x10)); |
483 __ movdqu(xmm2, Operand(src, 0x20)); | 490 __ movdqu(xmm2, Operand(src, 0x20)); |
484 __ movdqu(xmm3, Operand(src, count, times_1, -0x10)); | 491 __ movdqu(xmm3, Operand(src, count, times_1, -0x10)); |
485 __ movdqu(Operand(dst, 0x00), xmm0); | 492 __ movdqu(Operand(dst, 0x00), xmm0); |
486 __ movdqu(Operand(dst, 0x10), xmm1); | 493 __ movdqu(Operand(dst, 0x10), xmm1); |
487 __ movdqu(Operand(dst, 0x20), xmm2); | 494 __ movdqu(Operand(dst, 0x20), xmm2); |
488 __ movdqu(Operand(dst, count, times_1, -0x10), xmm3); | 495 __ movdqu(Operand(dst, count, times_1, -0x10), xmm3); |
489 MemMoveEmitPopAndReturn(&masm); | 496 MemMoveEmitPopAndReturn(&masm); |
490 | 497 |
491 medium_handlers = new size_t[4]; | 498 __ bind(&medium_handlers); |
492 medium_handlers[0] = reinterpret_cast<intptr_t>(buffer) + f9_16.pos(); | 499 __ dd(conv.address(&f9_16)); |
493 medium_handlers[1] = reinterpret_cast<intptr_t>(buffer) + f17_32.pos(); | 500 __ dd(conv.address(&f17_32)); |
494 medium_handlers[2] = reinterpret_cast<intptr_t>(buffer) + f33_48.pos(); | 501 __ dd(conv.address(&f33_48)); |
495 medium_handlers[3] = reinterpret_cast<intptr_t>(buffer) + f49_63.pos(); | 502 __ dd(conv.address(&f49_63)); |
496 | 503 |
497 __ bind(&medium_size); // Entry point into this block. | 504 __ bind(&medium_size); // Entry point into this block. |
498 __ mov(eax, count); | 505 __ mov(eax, count); |
499 __ dec(eax); | 506 __ dec(eax); |
500 __ shr(eax, 4); | 507 __ shr(eax, 4); |
501 if (FLAG_debug_code) { | 508 if (FLAG_debug_code) { |
502 Label ok; | 509 Label ok; |
503 __ cmp(eax, 3); | 510 __ cmp(eax, 3); |
504 __ j(below_equal, &ok); | 511 __ j(below_equal, &ok); |
505 __ int3(); | 512 __ int3(); |
506 __ bind(&ok); | 513 __ bind(&ok); |
507 } | 514 } |
508 __ mov(eax, Operand(eax, times_4, | 515 __ mov(eax, Operand(eax, times_4, conv.address(&medium_handlers))); |
509 reinterpret_cast<intptr_t>(medium_handlers))); | |
510 __ jmp(eax); | 516 __ jmp(eax); |
511 } | 517 } |
512 { | 518 { |
513 // Specialized copiers for copy_size <= 8 bytes. | 519 // Specialized copiers for copy_size <= 8 bytes. |
514 Label f0, f1, f2, f3, f4, f5_8; | 520 Label small_handlers, f0, f1, f2, f3, f4, f5_8; |
515 __ bind(&f0); | 521 __ bind(&f0); |
516 MemMoveEmitPopAndReturn(&masm); | 522 MemMoveEmitPopAndReturn(&masm); |
517 | 523 |
518 __ bind(&f1); | 524 __ bind(&f1); |
519 __ mov_b(eax, Operand(src, 0)); | 525 __ mov_b(eax, Operand(src, 0)); |
520 __ mov_b(Operand(dst, 0), eax); | 526 __ mov_b(Operand(dst, 0), eax); |
521 MemMoveEmitPopAndReturn(&masm); | 527 MemMoveEmitPopAndReturn(&masm); |
522 | 528 |
523 __ bind(&f2); | 529 __ bind(&f2); |
524 __ mov_w(eax, Operand(src, 0)); | 530 __ mov_w(eax, Operand(src, 0)); |
(...skipping 12 matching lines...) Expand all Loading... |
537 __ mov(Operand(dst, 0), eax); | 543 __ mov(Operand(dst, 0), eax); |
538 MemMoveEmitPopAndReturn(&masm); | 544 MemMoveEmitPopAndReturn(&masm); |
539 | 545 |
540 __ bind(&f5_8); | 546 __ bind(&f5_8); |
541 __ mov(eax, Operand(src, 0)); | 547 __ mov(eax, Operand(src, 0)); |
542 __ mov(edx, Operand(src, count, times_1, -4)); | 548 __ mov(edx, Operand(src, count, times_1, -4)); |
543 __ mov(Operand(dst, 0), eax); | 549 __ mov(Operand(dst, 0), eax); |
544 __ mov(Operand(dst, count, times_1, -4), edx); | 550 __ mov(Operand(dst, count, times_1, -4), edx); |
545 MemMoveEmitPopAndReturn(&masm); | 551 MemMoveEmitPopAndReturn(&masm); |
546 | 552 |
547 small_handlers = new size_t[9]; | 553 __ bind(&small_handlers); |
548 small_handlers[0] = reinterpret_cast<intptr_t>(buffer) + f0.pos(); | 554 __ dd(conv.address(&f0)); |
549 small_handlers[1] = reinterpret_cast<intptr_t>(buffer) + f1.pos(); | 555 __ dd(conv.address(&f1)); |
550 small_handlers[2] = reinterpret_cast<intptr_t>(buffer) + f2.pos(); | 556 __ dd(conv.address(&f2)); |
551 small_handlers[3] = reinterpret_cast<intptr_t>(buffer) + f3.pos(); | 557 __ dd(conv.address(&f3)); |
552 small_handlers[4] = reinterpret_cast<intptr_t>(buffer) + f4.pos(); | 558 __ dd(conv.address(&f4)); |
553 small_handlers[5] = reinterpret_cast<intptr_t>(buffer) + f5_8.pos(); | 559 __ dd(conv.address(&f5_8)); |
554 small_handlers[6] = reinterpret_cast<intptr_t>(buffer) + f5_8.pos(); | 560 __ dd(conv.address(&f5_8)); |
555 small_handlers[7] = reinterpret_cast<intptr_t>(buffer) + f5_8.pos(); | 561 __ dd(conv.address(&f5_8)); |
556 small_handlers[8] = reinterpret_cast<intptr_t>(buffer) + f5_8.pos(); | 562 __ dd(conv.address(&f5_8)); |
557 | 563 |
558 __ bind(&small_size); // Entry point into this block. | 564 __ bind(&small_size); // Entry point into this block. |
559 if (FLAG_debug_code) { | 565 if (FLAG_debug_code) { |
560 Label ok; | 566 Label ok; |
561 __ cmp(count, 8); | 567 __ cmp(count, 8); |
562 __ j(below_equal, &ok); | 568 __ j(below_equal, &ok); |
563 __ int3(); | 569 __ int3(); |
564 __ bind(&ok); | 570 __ bind(&ok); |
565 } | 571 } |
566 __ mov(eax, Operand(count, times_4, | 572 __ mov(eax, Operand(count, times_4, conv.address(&small_handlers))); |
567 reinterpret_cast<intptr_t>(small_handlers))); | |
568 __ jmp(eax); | 573 __ jmp(eax); |
569 } | 574 } |
570 } else { | 575 } else { |
571 // No SSE2. | 576 // No SSE2. |
572 Label forward; | 577 Label forward; |
573 __ cmp(count, 0); | 578 __ cmp(count, 0); |
574 __ j(equal, &pop_and_return); | 579 __ j(equal, &pop_and_return); |
575 __ cmp(dst, src); | 580 __ cmp(dst, src); |
576 __ j(above, &backward); | 581 __ j(above, &backward); |
577 __ jmp(&forward); | 582 __ jmp(&forward); |
(...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1172 Code* stub = GetCodeAgeStub(age, parity); | 1177 Code* stub = GetCodeAgeStub(age, parity); |
1173 CodePatcher patcher(sequence, young_length); | 1178 CodePatcher patcher(sequence, young_length); |
1174 patcher.masm()->call(stub->instruction_start(), RelocInfo::NONE32); | 1179 patcher.masm()->call(stub->instruction_start(), RelocInfo::NONE32); |
1175 } | 1180 } |
1176 } | 1181 } |
1177 | 1182 |
1178 | 1183 |
1179 } } // namespace v8::internal | 1184 } } // namespace v8::internal |
1180 | 1185 |
1181 #endif // V8_TARGET_ARCH_IA32 | 1186 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |