Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(597)

Side by Side Diff: src/ia32/macro-assembler-ia32.cc

Issue 8086021: Clean up the x86 assembler API. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 Register object, 57 Register object,
58 Register scratch, 58 Register scratch,
59 Condition cc, 59 Condition cc,
60 Label* condition_met, 60 Label* condition_met,
61 Label::Distance condition_met_distance) { 61 Label::Distance condition_met_distance) {
62 ASSERT(cc == equal || cc == not_equal); 62 ASSERT(cc == equal || cc == not_equal);
63 if (scratch.is(object)) { 63 if (scratch.is(object)) {
64 and_(scratch, Immediate(~Page::kPageAlignmentMask)); 64 and_(scratch, Immediate(~Page::kPageAlignmentMask));
65 } else { 65 } else {
66 mov(scratch, Immediate(~Page::kPageAlignmentMask)); 66 mov(scratch, Immediate(~Page::kPageAlignmentMask));
67 and_(scratch, Operand(object)); 67 and_(scratch, object);
68 } 68 }
69 // Check that we can use a test_b. 69 // Check that we can use a test_b.
70 ASSERT(MemoryChunk::IN_FROM_SPACE < 8); 70 ASSERT(MemoryChunk::IN_FROM_SPACE < 8);
71 ASSERT(MemoryChunk::IN_TO_SPACE < 8); 71 ASSERT(MemoryChunk::IN_TO_SPACE < 8);
72 int mask = (1 << MemoryChunk::IN_FROM_SPACE) 72 int mask = (1 << MemoryChunk::IN_FROM_SPACE)
73 | (1 << MemoryChunk::IN_TO_SPACE); 73 | (1 << MemoryChunk::IN_TO_SPACE);
74 // If non-zero, the page belongs to new-space. 74 // If non-zero, the page belongs to new-space.
75 test_b(Operand(scratch, MemoryChunk::kFlagsOffset), 75 test_b(Operand(scratch, MemoryChunk::kFlagsOffset),
76 static_cast<uint8_t>(mask)); 76 static_cast<uint8_t>(mask));
77 j(cc, condition_met, condition_met_distance); 77 j(cc, condition_met, condition_met_distance);
(...skipping 13 matching lines...) Expand all
91 int3(); 91 int3();
92 bind(&ok); 92 bind(&ok);
93 } 93 }
94 // Load store buffer top. 94 // Load store buffer top.
95 ExternalReference store_buffer = 95 ExternalReference store_buffer =
96 ExternalReference::store_buffer_top(isolate()); 96 ExternalReference::store_buffer_top(isolate());
97 mov(scratch, Operand::StaticVariable(store_buffer)); 97 mov(scratch, Operand::StaticVariable(store_buffer));
98 // Store pointer to buffer. 98 // Store pointer to buffer.
99 mov(Operand(scratch, 0), addr); 99 mov(Operand(scratch, 0), addr);
100 // Increment buffer top. 100 // Increment buffer top.
101 add(Operand(scratch), Immediate(kPointerSize)); 101 add(scratch, Immediate(kPointerSize));
102 // Write back new top of buffer. 102 // Write back new top of buffer.
103 mov(Operand::StaticVariable(store_buffer), scratch); 103 mov(Operand::StaticVariable(store_buffer), scratch);
104 // Call stub on end of buffer. 104 // Call stub on end of buffer.
105 // Check for end of buffer. 105 // Check for end of buffer.
106 test(scratch, Immediate(StoreBuffer::kStoreBufferOverflowBit)); 106 test(scratch, Immediate(StoreBuffer::kStoreBufferOverflowBit));
107 if (and_then == kReturnAtEnd) { 107 if (and_then == kReturnAtEnd) {
108 Label buffer_overflowed; 108 Label buffer_overflowed;
109 j(not_equal, &buffer_overflowed, Label::kNear); 109 j(not_equal, &buffer_overflowed, Label::kNear);
110 ret(0); 110 ret(0);
111 bind(&buffer_overflowed); 111 bind(&buffer_overflowed);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 JumpIfSmi(value, &done, Label::kNear); 210 JumpIfSmi(value, &done, Label::kNear);
211 } 211 }
212 212
213 // Although the object register is tagged, the offset is relative to the start 213 // Although the object register is tagged, the offset is relative to the start
214 // of the object, so so offset must be a multiple of kPointerSize. 214 // of the object, so so offset must be a multiple of kPointerSize.
215 ASSERT(IsAligned(offset, kPointerSize)); 215 ASSERT(IsAligned(offset, kPointerSize));
216 216
217 lea(dst, FieldOperand(object, offset)); 217 lea(dst, FieldOperand(object, offset));
218 if (emit_debug_code()) { 218 if (emit_debug_code()) {
219 Label ok; 219 Label ok;
220 test_b(Operand(dst), (1 << kPointerSizeLog2) - 1); 220 test_b(dst, (1 << kPointerSizeLog2) - 1);
221 j(zero, &ok, Label::kNear); 221 j(zero, &ok, Label::kNear);
222 int3(); 222 int3();
223 bind(&ok); 223 bind(&ok);
224 } 224 }
225 225
226 RecordWrite( 226 RecordWrite(
227 object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK); 227 object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK);
228 228
229 bind(&done); 229 bind(&done);
230 230
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 Set(eax, Immediate(0)); 304 Set(eax, Immediate(0));
305 mov(ebx, Immediate(ExternalReference(Runtime::kDebugBreak, isolate()))); 305 mov(ebx, Immediate(ExternalReference(Runtime::kDebugBreak, isolate())));
306 CEntryStub ces(1); 306 CEntryStub ces(1);
307 call(ces.GetCode(), RelocInfo::DEBUG_BREAK); 307 call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
308 } 308 }
309 #endif 309 #endif
310 310
311 311
312 void MacroAssembler::Set(Register dst, const Immediate& x) { 312 void MacroAssembler::Set(Register dst, const Immediate& x) {
313 if (x.is_zero()) { 313 if (x.is_zero()) {
314 xor_(dst, Operand(dst)); // Shorter than mov. 314 xor_(dst, dst); // Shorter than mov.
315 } else { 315 } else {
316 mov(dst, x); 316 mov(dst, x);
317 } 317 }
318 } 318 }
319 319
320 320
321 void MacroAssembler::Set(const Operand& dst, const Immediate& x) { 321 void MacroAssembler::Set(const Operand& dst, const Immediate& x) {
322 mov(dst, x); 322 mov(dst, x);
323 } 323 }
324 324
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 } 459 }
460 jmp(&have_double_value, Label::kNear); 460 jmp(&have_double_value, Label::kNear);
461 461
462 bind(&smi_value); 462 bind(&smi_value);
463 // Value is a smi. Convert to a double and store. 463 // Value is a smi. Convert to a double and store.
464 // Preserve original value. 464 // Preserve original value.
465 mov(scratch1, maybe_number); 465 mov(scratch1, maybe_number);
466 SmiUntag(scratch1); 466 SmiUntag(scratch1);
467 if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) { 467 if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) {
468 CpuFeatures::Scope fscope(SSE2); 468 CpuFeatures::Scope fscope(SSE2);
469 cvtsi2sd(scratch2, Operand(scratch1)); 469 cvtsi2sd(scratch2, scratch1);
470 movdbl(FieldOperand(elements, key, times_4, FixedDoubleArray::kHeaderSize), 470 movdbl(FieldOperand(elements, key, times_4, FixedDoubleArray::kHeaderSize),
471 scratch2); 471 scratch2);
472 } else { 472 } else {
473 push(scratch1); 473 push(scratch1);
474 fild_s(Operand(esp, 0)); 474 fild_s(Operand(esp, 0));
475 pop(scratch1); 475 pop(scratch1);
476 fstp_d(FieldOperand(elements, key, times_4, FixedDoubleArray::kHeaderSize)); 476 fstp_d(FieldOperand(elements, key, times_4, FixedDoubleArray::kHeaderSize));
477 } 477 }
478 bind(&done); 478 bind(&done);
479 } 479 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 Label* fail) { 523 Label* fail) {
524 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); 524 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
525 IsInstanceJSObjectType(map, scratch, fail); 525 IsInstanceJSObjectType(map, scratch, fail);
526 } 526 }
527 527
528 528
529 void MacroAssembler::IsInstanceJSObjectType(Register map, 529 void MacroAssembler::IsInstanceJSObjectType(Register map,
530 Register scratch, 530 Register scratch,
531 Label* fail) { 531 Label* fail) {
532 movzx_b(scratch, FieldOperand(map, Map::kInstanceTypeOffset)); 532 movzx_b(scratch, FieldOperand(map, Map::kInstanceTypeOffset));
533 sub(Operand(scratch), Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 533 sub(scratch, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
534 cmp(scratch, 534 cmp(scratch,
535 LAST_NONCALLABLE_SPEC_OBJECT_TYPE - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); 535 LAST_NONCALLABLE_SPEC_OBJECT_TYPE - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
536 j(above, fail); 536 j(above, fail);
537 } 537 }
538 538
539 539
540 void MacroAssembler::FCmp() { 540 void MacroAssembler::FCmp() {
541 if (CpuFeatures::IsSupported(CMOV)) { 541 if (CpuFeatures::IsSupported(CMOV)) {
542 fucomip(); 542 fucomip();
543 ffree(0); 543 ffree(0);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 580
581 581
582 void MacroAssembler::AbortIfSmi(Register object) { 582 void MacroAssembler::AbortIfSmi(Register object) {
583 test(object, Immediate(kSmiTagMask)); 583 test(object, Immediate(kSmiTagMask));
584 Assert(not_equal, "Operand is a smi"); 584 Assert(not_equal, "Operand is a smi");
585 } 585 }
586 586
587 587
588 void MacroAssembler::EnterFrame(StackFrame::Type type) { 588 void MacroAssembler::EnterFrame(StackFrame::Type type) {
589 push(ebp); 589 push(ebp);
590 mov(ebp, Operand(esp)); 590 mov(ebp, esp);
591 push(esi); 591 push(esi);
592 push(Immediate(Smi::FromInt(type))); 592 push(Immediate(Smi::FromInt(type)));
593 push(Immediate(CodeObject())); 593 push(Immediate(CodeObject()));
594 if (emit_debug_code()) { 594 if (emit_debug_code()) {
595 cmp(Operand(esp, 0), Immediate(isolate()->factory()->undefined_value())); 595 cmp(Operand(esp, 0), Immediate(isolate()->factory()->undefined_value()));
596 Check(not_equal, "code object not properly patched"); 596 Check(not_equal, "code object not properly patched");
597 } 597 }
598 } 598 }
599 599
600 600
601 void MacroAssembler::LeaveFrame(StackFrame::Type type) { 601 void MacroAssembler::LeaveFrame(StackFrame::Type type) {
602 if (emit_debug_code()) { 602 if (emit_debug_code()) {
603 cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), 603 cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset),
604 Immediate(Smi::FromInt(type))); 604 Immediate(Smi::FromInt(type)));
605 Check(equal, "stack frame types must match"); 605 Check(equal, "stack frame types must match");
606 } 606 }
607 leave(); 607 leave();
608 } 608 }
609 609
610 610
611 void MacroAssembler::EnterExitFramePrologue() { 611 void MacroAssembler::EnterExitFramePrologue() {
612 // Setup the frame structure on the stack. 612 // Setup the frame structure on the stack.
613 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); 613 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize);
614 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); 614 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
615 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); 615 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize);
616 push(ebp); 616 push(ebp);
617 mov(ebp, Operand(esp)); 617 mov(ebp, esp);
618 618
619 // Reserve room for entry stack pointer and push the code object. 619 // Reserve room for entry stack pointer and push the code object.
620 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); 620 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize);
621 push(Immediate(0)); // Saved entry sp, patched before call. 621 push(Immediate(0)); // Saved entry sp, patched before call.
622 push(Immediate(CodeObject())); // Accessed from ExitFrame::code_slot. 622 push(Immediate(CodeObject())); // Accessed from ExitFrame::code_slot.
623 623
624 // Save the frame pointer and the context in top. 624 // Save the frame pointer and the context in top.
625 ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, 625 ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress,
626 isolate()); 626 isolate());
627 ExternalReference context_address(Isolate::kContextAddress, 627 ExternalReference context_address(Isolate::kContextAddress,
628 isolate()); 628 isolate());
629 mov(Operand::StaticVariable(c_entry_fp_address), ebp); 629 mov(Operand::StaticVariable(c_entry_fp_address), ebp);
630 mov(Operand::StaticVariable(context_address), esi); 630 mov(Operand::StaticVariable(context_address), esi);
631 } 631 }
632 632
633 633
634 void MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) { 634 void MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) {
635 // Optionally save all XMM registers. 635 // Optionally save all XMM registers.
636 if (save_doubles) { 636 if (save_doubles) {
637 CpuFeatures::Scope scope(SSE2); 637 CpuFeatures::Scope scope(SSE2);
638 int space = XMMRegister::kNumRegisters * kDoubleSize + argc * kPointerSize; 638 int space = XMMRegister::kNumRegisters * kDoubleSize + argc * kPointerSize;
639 sub(Operand(esp), Immediate(space)); 639 sub(esp, Immediate(space));
640 const int offset = -2 * kPointerSize; 640 const int offset = -2 * kPointerSize;
641 for (int i = 0; i < XMMRegister::kNumRegisters; i++) { 641 for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
642 XMMRegister reg = XMMRegister::from_code(i); 642 XMMRegister reg = XMMRegister::from_code(i);
643 movdbl(Operand(ebp, offset - ((i + 1) * kDoubleSize)), reg); 643 movdbl(Operand(ebp, offset - ((i + 1) * kDoubleSize)), reg);
644 } 644 }
645 } else { 645 } else {
646 sub(Operand(esp), Immediate(argc * kPointerSize)); 646 sub(esp, Immediate(argc * kPointerSize));
647 } 647 }
648 648
649 // Get the required frame alignment for the OS. 649 // Get the required frame alignment for the OS.
650 const int kFrameAlignment = OS::ActivationFrameAlignment(); 650 const int kFrameAlignment = OS::ActivationFrameAlignment();
651 if (kFrameAlignment > 0) { 651 if (kFrameAlignment > 0) {
652 ASSERT(IsPowerOf2(kFrameAlignment)); 652 ASSERT(IsPowerOf2(kFrameAlignment));
653 and_(esp, -kFrameAlignment); 653 and_(esp, -kFrameAlignment);
654 } 654 }
655 655
656 // Patch the saved entry sp. 656 // Patch the saved entry sp.
657 mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp); 657 mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp);
658 } 658 }
659 659
660 660
661 void MacroAssembler::EnterExitFrame(bool save_doubles) { 661 void MacroAssembler::EnterExitFrame(bool save_doubles) {
662 EnterExitFramePrologue(); 662 EnterExitFramePrologue();
663 663
664 // Setup argc and argv in callee-saved registers. 664 // Setup argc and argv in callee-saved registers.
665 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; 665 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
666 mov(edi, Operand(eax)); 666 mov(edi, eax);
667 lea(esi, Operand(ebp, eax, times_4, offset)); 667 lea(esi, Operand(ebp, eax, times_4, offset));
668 668
669 // Reserve space for argc, argv and isolate. 669 // Reserve space for argc, argv and isolate.
670 EnterExitFrameEpilogue(3, save_doubles); 670 EnterExitFrameEpilogue(3, save_doubles);
671 } 671 }
672 672
673 673
674 void MacroAssembler::EnterApiExitFrame(int argc) { 674 void MacroAssembler::EnterApiExitFrame(int argc) {
675 EnterExitFramePrologue(); 675 EnterExitFramePrologue();
676 EnterExitFrameEpilogue(argc, false); 676 EnterExitFrameEpilogue(argc, false);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 #endif 710 #endif
711 711
712 // Clear the top frame. 712 // Clear the top frame.
713 ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, 713 ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress,
714 isolate()); 714 isolate());
715 mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0)); 715 mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0));
716 } 716 }
717 717
718 718
719 void MacroAssembler::LeaveApiExitFrame() { 719 void MacroAssembler::LeaveApiExitFrame() {
720 mov(esp, Operand(ebp)); 720 mov(esp, ebp);
721 pop(ebp); 721 pop(ebp);
722 722
723 LeaveExitFrameEpilogue(); 723 LeaveExitFrameEpilogue();
724 } 724 }
725 725
726 726
727 void MacroAssembler::PushTryHandler(CodeLocation try_location, 727 void MacroAssembler::PushTryHandler(CodeLocation try_location,
728 HandlerType type) { 728 HandlerType type) {
729 // Adjust this code if not the case. 729 // Adjust this code if not the case.
730 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); 730 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
(...skipping 27 matching lines...) Expand all
758 mov(Operand::StaticVariable(ExternalReference(Isolate::kHandlerAddress, 758 mov(Operand::StaticVariable(ExternalReference(Isolate::kHandlerAddress,
759 isolate())), 759 isolate())),
760 esp); 760 esp);
761 } 761 }
762 762
763 763
764 void MacroAssembler::PopTryHandler() { 764 void MacroAssembler::PopTryHandler() {
765 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 765 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
766 pop(Operand::StaticVariable(ExternalReference(Isolate::kHandlerAddress, 766 pop(Operand::StaticVariable(ExternalReference(Isolate::kHandlerAddress,
767 isolate()))); 767 isolate())));
768 add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize)); 768 add(esp, Immediate(StackHandlerConstants::kSize - kPointerSize));
769 } 769 }
770 770
771 771
772 void MacroAssembler::Throw(Register value) { 772 void MacroAssembler::Throw(Register value) {
773 // Adjust this code if not the case. 773 // Adjust this code if not the case.
774 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); 774 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
775 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 775 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
776 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 1 * kPointerSize); 776 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 1 * kPointerSize);
777 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); 777 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
778 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize); 778 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize);
(...skipping 11 matching lines...) Expand all
790 // Restore next handler, context, and frame pointer; discard handler state. 790 // Restore next handler, context, and frame pointer; discard handler state.
791 pop(Operand::StaticVariable(handler_address)); 791 pop(Operand::StaticVariable(handler_address));
792 pop(esi); // Context. 792 pop(esi); // Context.
793 pop(ebp); // Frame pointer. 793 pop(ebp); // Frame pointer.
794 pop(edx); // State. 794 pop(edx); // State.
795 795
796 // If the handler is a JS frame, restore the context to the frame. 796 // If the handler is a JS frame, restore the context to the frame.
797 // (edx == ENTRY) == (ebp == 0) == (esi == 0), so we could test any 797 // (edx == ENTRY) == (ebp == 0) == (esi == 0), so we could test any
798 // of them. 798 // of them.
799 Label skip; 799 Label skip;
800 cmp(Operand(edx), Immediate(StackHandler::ENTRY)); 800 cmp(edx, Immediate(StackHandler::ENTRY));
801 j(equal, &skip, Label::kNear); 801 j(equal, &skip, Label::kNear);
802 mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); 802 mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
803 bind(&skip); 803 bind(&skip);
804 804
805 ret(0); 805 ret(0);
806 } 806 }
807 807
808 808
809 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, 809 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
810 Register value) { 810 Register value) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
874 Label* miss) { 874 Label* miss) {
875 Label same_contexts; 875 Label same_contexts;
876 876
877 ASSERT(!holder_reg.is(scratch)); 877 ASSERT(!holder_reg.is(scratch));
878 878
879 // Load current lexical context from the stack frame. 879 // Load current lexical context from the stack frame.
880 mov(scratch, Operand(ebp, StandardFrameConstants::kContextOffset)); 880 mov(scratch, Operand(ebp, StandardFrameConstants::kContextOffset));
881 881
882 // When generating debug code, make sure the lexical context is set. 882 // When generating debug code, make sure the lexical context is set.
883 if (emit_debug_code()) { 883 if (emit_debug_code()) {
884 cmp(Operand(scratch), Immediate(0)); 884 cmp(scratch, Immediate(0));
885 Check(not_equal, "we should not have an empty lexical context"); 885 Check(not_equal, "we should not have an empty lexical context");
886 } 886 }
887 // Load the global context of the current context. 887 // Load the global context of the current context.
888 int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 888 int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
889 mov(scratch, FieldOperand(scratch, offset)); 889 mov(scratch, FieldOperand(scratch, offset));
890 mov(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); 890 mov(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset));
891 891
892 // Check the context is a global context. 892 // Check the context is a global context.
893 if (emit_debug_code()) { 893 if (emit_debug_code()) {
894 push(scratch); 894 push(scratch);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
962 962
963 Label done; 963 Label done;
964 964
965 // Compute the hash code from the untagged key. This must be kept in sync 965 // Compute the hash code from the untagged key. This must be kept in sync
966 // with ComputeIntegerHash in utils.h. 966 // with ComputeIntegerHash in utils.h.
967 // 967 //
968 // hash = ~hash + (hash << 15); 968 // hash = ~hash + (hash << 15);
969 mov(r1, r0); 969 mov(r1, r0);
970 not_(r0); 970 not_(r0);
971 shl(r1, 15); 971 shl(r1, 15);
972 add(r0, Operand(r1)); 972 add(r0, r1);
973 // hash = hash ^ (hash >> 12); 973 // hash = hash ^ (hash >> 12);
974 mov(r1, r0); 974 mov(r1, r0);
975 shr(r1, 12); 975 shr(r1, 12);
976 xor_(r0, Operand(r1)); 976 xor_(r0, r1);
977 // hash = hash + (hash << 2); 977 // hash = hash + (hash << 2);
978 lea(r0, Operand(r0, r0, times_4, 0)); 978 lea(r0, Operand(r0, r0, times_4, 0));
979 // hash = hash ^ (hash >> 4); 979 // hash = hash ^ (hash >> 4);
980 mov(r1, r0); 980 mov(r1, r0);
981 shr(r1, 4); 981 shr(r1, 4);
982 xor_(r0, Operand(r1)); 982 xor_(r0, r1);
983 // hash = hash * 2057; 983 // hash = hash * 2057;
984 imul(r0, r0, 2057); 984 imul(r0, r0, 2057);
985 // hash = hash ^ (hash >> 16); 985 // hash = hash ^ (hash >> 16);
986 mov(r1, r0); 986 mov(r1, r0);
987 shr(r1, 16); 987 shr(r1, 16);
988 xor_(r0, Operand(r1)); 988 xor_(r0, r1);
989 989
990 // Compute capacity mask. 990 // Compute capacity mask.
991 mov(r1, FieldOperand(elements, NumberDictionary::kCapacityOffset)); 991 mov(r1, FieldOperand(elements, NumberDictionary::kCapacityOffset));
992 shr(r1, kSmiTagSize); // convert smi to int 992 shr(r1, kSmiTagSize); // convert smi to int
993 dec(r1); 993 dec(r1);
994 994
995 // Generate an unrolled loop that performs a few probes before giving up. 995 // Generate an unrolled loop that performs a few probes before giving up.
996 const int kProbes = 4; 996 const int kProbes = 4;
997 for (int i = 0; i < kProbes; i++) { 997 for (int i = 0; i < kProbes; i++) {
998 // Use r2 for index calculations and keep the hash intact in r0. 998 // Use r2 for index calculations and keep the hash intact in r0.
999 mov(r2, r0); 999 mov(r2, r0);
1000 // Compute the masked index: (hash + i + i * i) & mask. 1000 // Compute the masked index: (hash + i + i * i) & mask.
1001 if (i > 0) { 1001 if (i > 0) {
1002 add(Operand(r2), Immediate(NumberDictionary::GetProbeOffset(i))); 1002 add(r2, Immediate(NumberDictionary::GetProbeOffset(i)));
1003 } 1003 }
1004 and_(r2, Operand(r1)); 1004 and_(r2, r1);
1005 1005
1006 // Scale the index by multiplying by the entry size. 1006 // Scale the index by multiplying by the entry size.
1007 ASSERT(NumberDictionary::kEntrySize == 3); 1007 ASSERT(NumberDictionary::kEntrySize == 3);
1008 lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 1008 lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3
1009 1009
1010 // Check if the key matches. 1010 // Check if the key matches.
1011 cmp(key, FieldOperand(elements, 1011 cmp(key, FieldOperand(elements,
1012 r2, 1012 r2,
1013 times_pointer_size, 1013 times_pointer_size,
1014 NumberDictionary::kElementsStartOffset)); 1014 NumberDictionary::kElementsStartOffset));
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 cmp(result, Operand::StaticVariable(new_space_allocation_top)); 1050 cmp(result, Operand::StaticVariable(new_space_allocation_top));
1051 Check(equal, "Unexpected allocation top"); 1051 Check(equal, "Unexpected allocation top");
1052 #endif 1052 #endif
1053 return; 1053 return;
1054 } 1054 }
1055 1055
1056 // Move address of new object to result. Use scratch register if available. 1056 // Move address of new object to result. Use scratch register if available.
1057 if (scratch.is(no_reg)) { 1057 if (scratch.is(no_reg)) {
1058 mov(result, Operand::StaticVariable(new_space_allocation_top)); 1058 mov(result, Operand::StaticVariable(new_space_allocation_top));
1059 } else { 1059 } else {
1060 mov(Operand(scratch), Immediate(new_space_allocation_top)); 1060 mov(scratch, Immediate(new_space_allocation_top));
1061 mov(result, Operand(scratch, 0)); 1061 mov(result, Operand(scratch, 0));
1062 } 1062 }
1063 } 1063 }
1064 1064
1065 1065
1066 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, 1066 void MacroAssembler::UpdateAllocationTopHelper(Register result_end,
1067 Register scratch) { 1067 Register scratch) {
1068 if (emit_debug_code()) { 1068 if (emit_debug_code()) {
1069 test(result_end, Immediate(kObjectAlignmentMask)); 1069 test(result_end, Immediate(kObjectAlignmentMask));
1070 Check(zero, "Unaligned allocation in new space"); 1070 Check(zero, "Unaligned allocation in new space");
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1109 1109
1110 Register top_reg = result_end.is_valid() ? result_end : result; 1110 Register top_reg = result_end.is_valid() ? result_end : result;
1111 1111
1112 // Calculate new top and bail out if new space is exhausted. 1112 // Calculate new top and bail out if new space is exhausted.
1113 ExternalReference new_space_allocation_limit = 1113 ExternalReference new_space_allocation_limit =
1114 ExternalReference::new_space_allocation_limit_address(isolate()); 1114 ExternalReference::new_space_allocation_limit_address(isolate());
1115 1115
1116 if (!top_reg.is(result)) { 1116 if (!top_reg.is(result)) {
1117 mov(top_reg, result); 1117 mov(top_reg, result);
1118 } 1118 }
1119 add(Operand(top_reg), Immediate(object_size)); 1119 add(top_reg, Immediate(object_size));
1120 j(carry, gc_required); 1120 j(carry, gc_required);
1121 cmp(top_reg, Operand::StaticVariable(new_space_allocation_limit)); 1121 cmp(top_reg, Operand::StaticVariable(new_space_allocation_limit));
1122 j(above, gc_required); 1122 j(above, gc_required);
1123 1123
1124 // Update allocation top. 1124 // Update allocation top.
1125 UpdateAllocationTopHelper(top_reg, scratch); 1125 UpdateAllocationTopHelper(top_reg, scratch);
1126 1126
1127 // Tag result if requested. 1127 // Tag result if requested.
1128 if (top_reg.is(result)) { 1128 if (top_reg.is(result)) {
1129 if ((flags & TAG_OBJECT) != 0) { 1129 if ((flags & TAG_OBJECT) != 0) {
1130 sub(Operand(result), Immediate(object_size - kHeapObjectTag)); 1130 sub(result, Immediate(object_size - kHeapObjectTag));
1131 } else { 1131 } else {
1132 sub(Operand(result), Immediate(object_size)); 1132 sub(result, Immediate(object_size));
1133 } 1133 }
1134 } else if ((flags & TAG_OBJECT) != 0) { 1134 } else if ((flags & TAG_OBJECT) != 0) {
1135 add(Operand(result), Immediate(kHeapObjectTag)); 1135 add(result, Immediate(kHeapObjectTag));
1136 } 1136 }
1137 } 1137 }
1138 1138
1139 1139
1140 void MacroAssembler::AllocateInNewSpace(int header_size, 1140 void MacroAssembler::AllocateInNewSpace(int header_size,
1141 ScaleFactor element_size, 1141 ScaleFactor element_size,
1142 Register element_count, 1142 Register element_count,
1143 Register result, 1143 Register result,
1144 Register result_end, 1144 Register result_end,
1145 Register scratch, 1145 Register scratch,
(...skipping 17 matching lines...) Expand all
1163 // Load address of new object into result. 1163 // Load address of new object into result.
1164 LoadAllocationTopHelper(result, scratch, flags); 1164 LoadAllocationTopHelper(result, scratch, flags);
1165 1165
1166 // Calculate new top and bail out if new space is exhausted. 1166 // Calculate new top and bail out if new space is exhausted.
1167 ExternalReference new_space_allocation_limit = 1167 ExternalReference new_space_allocation_limit =
1168 ExternalReference::new_space_allocation_limit_address(isolate()); 1168 ExternalReference::new_space_allocation_limit_address(isolate());
1169 1169
1170 // We assume that element_count*element_size + header_size does not 1170 // We assume that element_count*element_size + header_size does not
1171 // overflow. 1171 // overflow.
1172 lea(result_end, Operand(element_count, element_size, header_size)); 1172 lea(result_end, Operand(element_count, element_size, header_size));
1173 add(result_end, Operand(result)); 1173 add(result_end, result);
1174 j(carry, gc_required); 1174 j(carry, gc_required);
1175 cmp(result_end, Operand::StaticVariable(new_space_allocation_limit)); 1175 cmp(result_end, Operand::StaticVariable(new_space_allocation_limit));
1176 j(above, gc_required); 1176 j(above, gc_required);
1177 1177
1178 // Tag result if requested. 1178 // Tag result if requested.
1179 if ((flags & TAG_OBJECT) != 0) { 1179 if ((flags & TAG_OBJECT) != 0) {
1180 lea(result, Operand(result, kHeapObjectTag)); 1180 lea(result, Operand(result, kHeapObjectTag));
1181 } 1181 }
1182 1182
1183 // Update allocation top. 1183 // Update allocation top.
(...skipping 24 matching lines...) Expand all
1208 1208
1209 // Load address of new object into result. 1209 // Load address of new object into result.
1210 LoadAllocationTopHelper(result, scratch, flags); 1210 LoadAllocationTopHelper(result, scratch, flags);
1211 1211
1212 // Calculate new top and bail out if new space is exhausted. 1212 // Calculate new top and bail out if new space is exhausted.
1213 ExternalReference new_space_allocation_limit = 1213 ExternalReference new_space_allocation_limit =
1214 ExternalReference::new_space_allocation_limit_address(isolate()); 1214 ExternalReference::new_space_allocation_limit_address(isolate());
1215 if (!object_size.is(result_end)) { 1215 if (!object_size.is(result_end)) {
1216 mov(result_end, object_size); 1216 mov(result_end, object_size);
1217 } 1217 }
1218 add(result_end, Operand(result)); 1218 add(result_end, result);
1219 j(carry, gc_required); 1219 j(carry, gc_required);
1220 cmp(result_end, Operand::StaticVariable(new_space_allocation_limit)); 1220 cmp(result_end, Operand::StaticVariable(new_space_allocation_limit));
1221 j(above, gc_required); 1221 j(above, gc_required);
1222 1222
1223 // Tag result if requested. 1223 // Tag result if requested.
1224 if ((flags & TAG_OBJECT) != 0) { 1224 if ((flags & TAG_OBJECT) != 0) {
1225 lea(result, Operand(result, kHeapObjectTag)); 1225 lea(result, Operand(result, kHeapObjectTag));
1226 } 1226 }
1227 1227
1228 // Update allocation top. 1228 // Update allocation top.
1229 UpdateAllocationTopHelper(result_end, scratch); 1229 UpdateAllocationTopHelper(result_end, scratch);
1230 } 1230 }
1231 1231
1232 1232
1233 void MacroAssembler::UndoAllocationInNewSpace(Register object) { 1233 void MacroAssembler::UndoAllocationInNewSpace(Register object) {
1234 ExternalReference new_space_allocation_top = 1234 ExternalReference new_space_allocation_top =
1235 ExternalReference::new_space_allocation_top_address(isolate()); 1235 ExternalReference::new_space_allocation_top_address(isolate());
1236 1236
1237 // Make sure the object has no tag before resetting top. 1237 // Make sure the object has no tag before resetting top.
1238 and_(Operand(object), Immediate(~kHeapObjectTagMask)); 1238 and_(object, Immediate(~kHeapObjectTagMask));
1239 #ifdef DEBUG 1239 #ifdef DEBUG
1240 cmp(object, Operand::StaticVariable(new_space_allocation_top)); 1240 cmp(object, Operand::StaticVariable(new_space_allocation_top));
1241 Check(below, "Undo allocation of non allocated memory"); 1241 Check(below, "Undo allocation of non allocated memory");
1242 #endif 1242 #endif
1243 mov(Operand::StaticVariable(new_space_allocation_top), object); 1243 mov(Operand::StaticVariable(new_space_allocation_top), object);
1244 } 1244 }
1245 1245
1246 1246
1247 void MacroAssembler::AllocateHeapNumber(Register result, 1247 void MacroAssembler::AllocateHeapNumber(Register result,
1248 Register scratch1, 1248 Register scratch1,
(...skipping 18 matching lines...) Expand all
1267 Register scratch1, 1267 Register scratch1,
1268 Register scratch2, 1268 Register scratch2,
1269 Register scratch3, 1269 Register scratch3,
1270 Label* gc_required) { 1270 Label* gc_required) {
1271 // Calculate the number of bytes needed for the characters in the string while 1271 // Calculate the number of bytes needed for the characters in the string while
1272 // observing object alignment. 1272 // observing object alignment.
1273 ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); 1273 ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
1274 ASSERT(kShortSize == 2); 1274 ASSERT(kShortSize == 2);
1275 // scratch1 = length * 2 + kObjectAlignmentMask. 1275 // scratch1 = length * 2 + kObjectAlignmentMask.
1276 lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask)); 1276 lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask));
1277 and_(Operand(scratch1), Immediate(~kObjectAlignmentMask)); 1277 and_(scratch1, Immediate(~kObjectAlignmentMask));
1278 1278
1279 // Allocate two byte string in new space. 1279 // Allocate two byte string in new space.
1280 AllocateInNewSpace(SeqTwoByteString::kHeaderSize, 1280 AllocateInNewSpace(SeqTwoByteString::kHeaderSize,
1281 times_1, 1281 times_1,
1282 scratch1, 1282 scratch1,
1283 result, 1283 result,
1284 scratch2, 1284 scratch2,
1285 scratch3, 1285 scratch3,
1286 gc_required, 1286 gc_required,
1287 TAG_OBJECT); 1287 TAG_OBJECT);
(...skipping 13 matching lines...) Expand all
1301 Register length, 1301 Register length,
1302 Register scratch1, 1302 Register scratch1,
1303 Register scratch2, 1303 Register scratch2,
1304 Register scratch3, 1304 Register scratch3,
1305 Label* gc_required) { 1305 Label* gc_required) {
1306 // Calculate the number of bytes needed for the characters in the string while 1306 // Calculate the number of bytes needed for the characters in the string while
1307 // observing object alignment. 1307 // observing object alignment.
1308 ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); 1308 ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0);
1309 mov(scratch1, length); 1309 mov(scratch1, length);
1310 ASSERT(kCharSize == 1); 1310 ASSERT(kCharSize == 1);
1311 add(Operand(scratch1), Immediate(kObjectAlignmentMask)); 1311 add(scratch1, Immediate(kObjectAlignmentMask));
1312 and_(Operand(scratch1), Immediate(~kObjectAlignmentMask)); 1312 and_(scratch1, Immediate(~kObjectAlignmentMask));
1313 1313
1314 // Allocate ascii string in new space. 1314 // Allocate ascii string in new space.
1315 AllocateInNewSpace(SeqAsciiString::kHeaderSize, 1315 AllocateInNewSpace(SeqAsciiString::kHeaderSize,
1316 times_1, 1316 times_1,
1317 scratch1, 1317 scratch1,
1318 result, 1318 result,
1319 scratch2, 1319 scratch2,
1320 scratch3, 1320 scratch3,
1321 gc_required, 1321 gc_required,
1322 TAG_OBJECT); 1322 TAG_OBJECT);
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1436 // have been tried here already, and this is fastest. 1436 // have been tried here already, and this is fastest.
1437 // A simpler loop is faster on small copies, but 30% slower on large ones. 1437 // A simpler loop is faster on small copies, but 30% slower on large ones.
1438 // The cld() instruction must have been emitted, to set the direction flag(), 1438 // The cld() instruction must have been emitted, to set the direction flag(),
1439 // before calling this function. 1439 // before calling this function.
1440 void MacroAssembler::CopyBytes(Register source, 1440 void MacroAssembler::CopyBytes(Register source,
1441 Register destination, 1441 Register destination,
1442 Register length, 1442 Register length,
1443 Register scratch) { 1443 Register scratch) {
1444 Label loop, done, short_string, short_loop; 1444 Label loop, done, short_string, short_loop;
1445 // Experimentation shows that the short string loop is faster if length < 10. 1445 // Experimentation shows that the short string loop is faster if length < 10.
1446 cmp(Operand(length), Immediate(10)); 1446 cmp(length, Immediate(10));
1447 j(less_equal, &short_string); 1447 j(less_equal, &short_string);
1448 1448
1449 ASSERT(source.is(esi)); 1449 ASSERT(source.is(esi));
1450 ASSERT(destination.is(edi)); 1450 ASSERT(destination.is(edi));
1451 ASSERT(length.is(ecx)); 1451 ASSERT(length.is(ecx));
1452 1452
1453 // Because source is 4-byte aligned in our uses of this function, 1453 // Because source is 4-byte aligned in our uses of this function,
1454 // we keep source aligned for the rep_movs call by copying the odd bytes 1454 // we keep source aligned for the rep_movs call by copying the odd bytes
1455 // at the end of the ranges. 1455 // at the end of the ranges.
1456 mov(scratch, Operand(source, length, times_1, -4)); 1456 mov(scratch, Operand(source, length, times_1, -4));
1457 mov(Operand(destination, length, times_1, -4), scratch); 1457 mov(Operand(destination, length, times_1, -4), scratch);
1458 mov(scratch, ecx); 1458 mov(scratch, ecx);
1459 shr(ecx, 2); 1459 shr(ecx, 2);
1460 rep_movs(); 1460 rep_movs();
1461 and_(Operand(scratch), Immediate(0x3)); 1461 and_(scratch, Immediate(0x3));
1462 add(destination, Operand(scratch)); 1462 add(destination, scratch);
1463 jmp(&done); 1463 jmp(&done);
1464 1464
1465 bind(&short_string); 1465 bind(&short_string);
1466 test(length, Operand(length)); 1466 test(length, length);
1467 j(zero, &done); 1467 j(zero, &done);
1468 1468
1469 bind(&short_loop); 1469 bind(&short_loop);
1470 mov_b(scratch, Operand(source, 0)); 1470 mov_b(scratch, Operand(source, 0));
1471 mov_b(Operand(destination, 0), scratch); 1471 mov_b(Operand(destination, 0), scratch);
1472 inc(source); 1472 inc(source);
1473 inc(destination); 1473 inc(destination);
1474 dec(length); 1474 dec(length);
1475 j(not_zero, &short_loop); 1475 j(not_zero, &short_loop);
1476 1476
1477 bind(&done); 1477 bind(&done);
1478 } 1478 }
1479 1479
1480 1480
1481 void MacroAssembler::InitializeFieldsWithFiller(Register start_offset, 1481 void MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
1482 Register end_offset, 1482 Register end_offset,
1483 Register filler) { 1483 Register filler) {
1484 Label loop, entry; 1484 Label loop, entry;
1485 jmp(&entry); 1485 jmp(&entry);
1486 bind(&loop); 1486 bind(&loop);
1487 mov(Operand(start_offset, 0), filler); 1487 mov(Operand(start_offset, 0), filler);
1488 add(Operand(start_offset), Immediate(kPointerSize)); 1488 add(start_offset, Immediate(kPointerSize));
1489 bind(&entry); 1489 bind(&entry);
1490 cmp(start_offset, Operand(end_offset)); 1490 cmp(start_offset, end_offset);
1491 j(less, &loop); 1491 j(less, &loop);
1492 } 1492 }
1493 1493
1494 1494
1495 void MacroAssembler::NegativeZeroTest(Register result, 1495 void MacroAssembler::NegativeZeroTest(Register result,
1496 Register op, 1496 Register op,
1497 Label* then_label) { 1497 Label* then_label) {
1498 Label ok; 1498 Label ok;
1499 test(result, Operand(result)); 1499 test(result, result);
1500 j(not_zero, &ok); 1500 j(not_zero, &ok);
1501 test(op, Operand(op)); 1501 test(op, op);
1502 j(sign, then_label); 1502 j(sign, then_label);
1503 bind(&ok); 1503 bind(&ok);
1504 } 1504 }
1505 1505
1506 1506
1507 void MacroAssembler::NegativeZeroTest(Register result, 1507 void MacroAssembler::NegativeZeroTest(Register result,
1508 Register op1, 1508 Register op1,
1509 Register op2, 1509 Register op2,
1510 Register scratch, 1510 Register scratch,
1511 Label* then_label) { 1511 Label* then_label) {
1512 Label ok; 1512 Label ok;
1513 test(result, Operand(result)); 1513 test(result, result);
1514 j(not_zero, &ok); 1514 j(not_zero, &ok);
1515 mov(scratch, Operand(op1)); 1515 mov(scratch, op1);
1516 or_(scratch, Operand(op2)); 1516 or_(scratch, op2);
1517 j(sign, then_label); 1517 j(sign, then_label);
1518 bind(&ok); 1518 bind(&ok);
1519 } 1519 }
1520 1520
1521 1521
1522 void MacroAssembler::TryGetFunctionPrototype(Register function, 1522 void MacroAssembler::TryGetFunctionPrototype(Register function,
1523 Register result, 1523 Register result,
1524 Register scratch, 1524 Register scratch,
1525 Label* miss) { 1525 Label* miss) {
1526 // Check that the receiver isn't a smi. 1526 // Check that the receiver isn't a smi.
1527 JumpIfSmi(function, miss); 1527 JumpIfSmi(function, miss);
1528 1528
1529 // Check that the function really is a function. 1529 // Check that the function really is a function.
1530 CmpObjectType(function, JS_FUNCTION_TYPE, result); 1530 CmpObjectType(function, JS_FUNCTION_TYPE, result);
1531 j(not_equal, miss); 1531 j(not_equal, miss);
1532 1532
1533 // Make sure that the function has an instance prototype. 1533 // Make sure that the function has an instance prototype.
1534 Label non_instance; 1534 Label non_instance;
1535 movzx_b(scratch, FieldOperand(result, Map::kBitFieldOffset)); 1535 movzx_b(scratch, FieldOperand(result, Map::kBitFieldOffset));
1536 test(scratch, Immediate(1 << Map::kHasNonInstancePrototype)); 1536 test(scratch, Immediate(1 << Map::kHasNonInstancePrototype));
1537 j(not_zero, &non_instance); 1537 j(not_zero, &non_instance);
1538 1538
1539 // Get the prototype or initial map from the function. 1539 // Get the prototype or initial map from the function.
1540 mov(result, 1540 mov(result,
1541 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 1541 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
1542 1542
1543 // If the prototype or initial map is the hole, don't return it and 1543 // If the prototype or initial map is the hole, don't return it and
1544 // simply miss the cache instead. This will allow us to allocate a 1544 // simply miss the cache instead. This will allow us to allocate a
1545 // prototype object on-demand in the runtime system. 1545 // prototype object on-demand in the runtime system.
1546 cmp(Operand(result), Immediate(isolate()->factory()->the_hole_value())); 1546 cmp(result, Immediate(isolate()->factory()->the_hole_value()));
1547 j(equal, miss); 1547 j(equal, miss);
1548 1548
1549 // If the function does not have an initial map, we're done. 1549 // If the function does not have an initial map, we're done.
1550 Label done; 1550 Label done;
1551 CmpObjectType(result, MAP_TYPE, scratch); 1551 CmpObjectType(result, MAP_TYPE, scratch);
1552 j(not_equal, &done); 1552 j(not_equal, &done);
1553 1553
1554 // Get the prototype from the initial map. 1554 // Get the prototype from the initial map.
1555 mov(result, FieldOperand(result, Map::kPrototypeOffset)); 1555 mov(result, FieldOperand(result, Map::kPrototypeOffset));
1556 jmp(&done); 1556 jmp(&done);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1605 1605
1606 1606
1607 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { 1607 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
1608 if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false; 1608 if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false;
1609 return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe(); 1609 return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe();
1610 } 1610 }
1611 1611
1612 1612
1613 void MacroAssembler::IllegalOperation(int num_arguments) { 1613 void MacroAssembler::IllegalOperation(int num_arguments) {
1614 if (num_arguments > 0) { 1614 if (num_arguments > 0) {
1615 add(Operand(esp), Immediate(num_arguments * kPointerSize)); 1615 add(esp, Immediate(num_arguments * kPointerSize));
1616 } 1616 }
1617 mov(eax, Immediate(isolate()->factory()->undefined_value())); 1617 mov(eax, Immediate(isolate()->factory()->undefined_value()));
1618 } 1618 }
1619 1619
1620 1620
1621 void MacroAssembler::IndexFromHash(Register hash, Register index) { 1621 void MacroAssembler::IndexFromHash(Register hash, Register index) {
1622 // The assert checks that the constants for the maximum number of digits 1622 // The assert checks that the constants for the maximum number of digits
1623 // for an array index cached in the hash field and the number of bits 1623 // for an array index cached in the hash field and the number of bits
1624 // reserved for it does not conflict. 1624 // reserved for it does not conflict.
1625 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < 1625 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
1819 mov(eax, Operand(esi, 0)); 1819 mov(eax, Operand(esi, 0));
1820 } 1820 }
1821 1821
1822 Label empty_handle; 1822 Label empty_handle;
1823 Label prologue; 1823 Label prologue;
1824 Label promote_scheduled_exception; 1824 Label promote_scheduled_exception;
1825 Label delete_allocated_handles; 1825 Label delete_allocated_handles;
1826 Label leave_exit_frame; 1826 Label leave_exit_frame;
1827 1827
1828 // Check if the result handle holds 0. 1828 // Check if the result handle holds 0.
1829 test(eax, Operand(eax)); 1829 test(eax, eax);
1830 j(zero, &empty_handle); 1830 j(zero, &empty_handle);
1831 // It was non-zero. Dereference to get the result value. 1831 // It was non-zero. Dereference to get the result value.
1832 mov(eax, Operand(eax, 0)); 1832 mov(eax, Operand(eax, 0));
1833 bind(&prologue); 1833 bind(&prologue);
1834 // No more valid handles (the result handle was the last one). Restore 1834 // No more valid handles (the result handle was the last one). Restore
1835 // previous handle scope. 1835 // previous handle scope.
1836 mov(Operand::StaticVariable(next_address), ebx); 1836 mov(Operand::StaticVariable(next_address), ebx);
1837 sub(Operand::StaticVariable(level_address), Immediate(1)); 1837 sub(Operand::StaticVariable(level_address), Immediate(1));
1838 Assert(above_equal, "Invalid HandleScope level"); 1838 Assert(above_equal, "Invalid HandleScope level");
1839 cmp(edi, Operand::StaticVariable(limit_address)); 1839 cmp(edi, Operand::StaticVariable(limit_address));
(...skipping 20 matching lines...) Expand all
1860 jmp(&prologue); 1860 jmp(&prologue);
1861 1861
1862 // HandleScope limit has changed. Delete allocated extensions. 1862 // HandleScope limit has changed. Delete allocated extensions.
1863 ExternalReference delete_extensions = 1863 ExternalReference delete_extensions =
1864 ExternalReference::delete_handle_scope_extensions(isolate()); 1864 ExternalReference::delete_handle_scope_extensions(isolate());
1865 bind(&delete_allocated_handles); 1865 bind(&delete_allocated_handles);
1866 mov(Operand::StaticVariable(limit_address), edi); 1866 mov(Operand::StaticVariable(limit_address), edi);
1867 mov(edi, eax); 1867 mov(edi, eax);
1868 mov(Operand(esp, 0), Immediate(ExternalReference::isolate_address())); 1868 mov(Operand(esp, 0), Immediate(ExternalReference::isolate_address()));
1869 mov(eax, Immediate(delete_extensions)); 1869 mov(eax, Immediate(delete_extensions));
1870 call(Operand(eax)); 1870 call(eax);
1871 mov(eax, edi); 1871 mov(eax, edi);
1872 jmp(&leave_exit_frame); 1872 jmp(&leave_exit_frame);
1873 1873
1874 return result; 1874 return result;
1875 } 1875 }
1876 1876
1877 1877
1878 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext) { 1878 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext) {
1879 // Set the entry point and jump to the C entry runtime stub. 1879 // Set the entry point and jump to the C entry runtime stub.
1880 mov(ebx, Immediate(ext)); 1880 mov(ebx, Immediate(ext));
(...skipping 13 matching lines...) Expand all
1894 1894
1895 void MacroAssembler::SetCallKind(Register dst, CallKind call_kind) { 1895 void MacroAssembler::SetCallKind(Register dst, CallKind call_kind) {
1896 // This macro takes the dst register to make the code more readable 1896 // This macro takes the dst register to make the code more readable
1897 // at the call sites. However, the dst register has to be ecx to 1897 // at the call sites. However, the dst register has to be ecx to
1898 // follow the calling convention which requires the call type to be 1898 // follow the calling convention which requires the call type to be
1899 // in ecx. 1899 // in ecx.
1900 ASSERT(dst.is(ecx)); 1900 ASSERT(dst.is(ecx));
1901 if (call_kind == CALL_AS_FUNCTION) { 1901 if (call_kind == CALL_AS_FUNCTION) {
1902 // Set to some non-zero smi by updating the least significant 1902 // Set to some non-zero smi by updating the least significant
1903 // byte. 1903 // byte.
1904 mov_b(Operand(dst), 1 << kSmiTagSize); 1904 mov_b(dst, 1 << kSmiTagSize);
1905 } else { 1905 } else {
1906 // Set to smi zero by clearing the register. 1906 // Set to smi zero by clearing the register.
1907 xor_(dst, Operand(dst)); 1907 xor_(dst, dst);
1908 } 1908 }
1909 } 1909 }
1910 1910
1911 1911
1912 void MacroAssembler::InvokePrologue(const ParameterCount& expected, 1912 void MacroAssembler::InvokePrologue(const ParameterCount& expected,
1913 const ParameterCount& actual, 1913 const ParameterCount& actual,
1914 Handle<Code> code_constant, 1914 Handle<Code> code_constant,
1915 const Operand& code_operand, 1915 const Operand& code_operand,
1916 Label* done, 1916 Label* done,
1917 InvokeFlag flag, 1917 InvokeFlag flag,
(...skipping 24 matching lines...) Expand all
1942 // Expected is in register, actual is immediate. This is the 1942 // Expected is in register, actual is immediate. This is the
1943 // case when we invoke function values without going through the 1943 // case when we invoke function values without going through the
1944 // IC mechanism. 1944 // IC mechanism.
1945 cmp(expected.reg(), actual.immediate()); 1945 cmp(expected.reg(), actual.immediate());
1946 j(equal, &invoke); 1946 j(equal, &invoke);
1947 ASSERT(expected.reg().is(ebx)); 1947 ASSERT(expected.reg().is(ebx));
1948 mov(eax, actual.immediate()); 1948 mov(eax, actual.immediate());
1949 } else if (!expected.reg().is(actual.reg())) { 1949 } else if (!expected.reg().is(actual.reg())) {
1950 // Both expected and actual are in (different) registers. This 1950 // Both expected and actual are in (different) registers. This
1951 // is the case when we invoke functions using call and apply. 1951 // is the case when we invoke functions using call and apply.
1952 cmp(expected.reg(), Operand(actual.reg())); 1952 cmp(expected.reg(), actual.reg());
1953 j(equal, &invoke); 1953 j(equal, &invoke);
1954 ASSERT(actual.reg().is(eax)); 1954 ASSERT(actual.reg().is(eax));
1955 ASSERT(expected.reg().is(ebx)); 1955 ASSERT(expected.reg().is(ebx));
1956 } 1956 }
1957 } 1957 }
1958 1958
1959 if (!definitely_matches) { 1959 if (!definitely_matches) {
1960 Handle<Code> adaptor = 1960 Handle<Code> adaptor =
1961 isolate()->builtins()->ArgumentsAdaptorTrampoline(); 1961 isolate()->builtins()->ArgumentsAdaptorTrampoline();
1962 if (!code_constant.is_null()) { 1962 if (!code_constant.is_null()) {
1963 mov(edx, Immediate(code_constant)); 1963 mov(edx, Immediate(code_constant));
1964 add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag)); 1964 add(edx, Immediate(Code::kHeaderSize - kHeapObjectTag));
1965 } else if (!code_operand.is_reg(edx)) { 1965 } else if (!code_operand.is_reg(edx)) {
1966 mov(edx, code_operand); 1966 mov(edx, code_operand);
1967 } 1967 }
1968 1968
1969 if (flag == CALL_FUNCTION) { 1969 if (flag == CALL_FUNCTION) {
1970 call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET)); 1970 call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET));
1971 SetCallKind(ecx, call_kind); 1971 SetCallKind(ecx, call_kind);
1972 call(adaptor, RelocInfo::CODE_TARGET); 1972 call(adaptor, RelocInfo::CODE_TARGET);
1973 call_wrapper.AfterCall(); 1973 call_wrapper.AfterCall();
1974 jmp(done, done_near); 1974 jmp(done, done_near);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2012 const ParameterCount& expected, 2012 const ParameterCount& expected,
2013 const ParameterCount& actual, 2013 const ParameterCount& actual,
2014 RelocInfo::Mode rmode, 2014 RelocInfo::Mode rmode,
2015 InvokeFlag flag, 2015 InvokeFlag flag,
2016 const CallWrapper& call_wrapper, 2016 const CallWrapper& call_wrapper,
2017 CallKind call_kind) { 2017 CallKind call_kind) {
2018 // You can't call a function without a valid frame. 2018 // You can't call a function without a valid frame.
2019 ASSERT(flag == JUMP_FUNCTION || has_frame()); 2019 ASSERT(flag == JUMP_FUNCTION || has_frame());
2020 2020
2021 Label done; 2021 Label done;
2022 Operand dummy(eax); 2022 Operand dummy(eax, 0);
2023 InvokePrologue(expected, actual, code, dummy, &done, flag, Label::kNear, 2023 InvokePrologue(expected, actual, code, dummy, &done, flag, Label::kNear,
2024 call_wrapper, call_kind); 2024 call_wrapper, call_kind);
2025 if (flag == CALL_FUNCTION) { 2025 if (flag == CALL_FUNCTION) {
2026 call_wrapper.BeforeCall(CallSize(code, rmode)); 2026 call_wrapper.BeforeCall(CallSize(code, rmode));
2027 SetCallKind(ecx, call_kind); 2027 SetCallKind(ecx, call_kind);
2028 call(code, rmode); 2028 call(code, rmode);
2029 call_wrapper.AfterCall(); 2029 call_wrapper.AfterCall();
2030 } else { 2030 } else {
2031 ASSERT(flag == JUMP_FUNCTION); 2031 ASSERT(flag == JUMP_FUNCTION);
2032 SetCallKind(ecx, call_kind); 2032 SetCallKind(ecx, call_kind);
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
2204 void MacroAssembler::Ret() { 2204 void MacroAssembler::Ret() {
2205 ret(0); 2205 ret(0);
2206 } 2206 }
2207 2207
2208 2208
2209 void MacroAssembler::Ret(int bytes_dropped, Register scratch) { 2209 void MacroAssembler::Ret(int bytes_dropped, Register scratch) {
2210 if (is_uint16(bytes_dropped)) { 2210 if (is_uint16(bytes_dropped)) {
2211 ret(bytes_dropped); 2211 ret(bytes_dropped);
2212 } else { 2212 } else {
2213 pop(scratch); 2213 pop(scratch);
2214 add(Operand(esp), Immediate(bytes_dropped)); 2214 add(esp, Immediate(bytes_dropped));
2215 push(scratch); 2215 push(scratch);
2216 ret(0); 2216 ret(0);
2217 } 2217 }
2218 } 2218 }
2219 2219
2220 2220
2221 2221
2222 2222
2223 void MacroAssembler::Drop(int stack_elements) { 2223 void MacroAssembler::Drop(int stack_elements) {
2224 if (stack_elements > 0) { 2224 if (stack_elements > 0) {
2225 add(Operand(esp), Immediate(stack_elements * kPointerSize)); 2225 add(esp, Immediate(stack_elements * kPointerSize));
2226 } 2226 }
2227 } 2227 }
2228 2228
2229 2229
2230 void MacroAssembler::Move(Register dst, Register src) { 2230 void MacroAssembler::Move(Register dst, Register src) {
2231 if (!dst.is(src)) { 2231 if (!dst.is(src)) {
2232 mov(dst, src); 2232 mov(dst, src);
2233 } 2233 }
2234 } 2234 }
2235 2235
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
2393 bind(&not_smi); 2393 bind(&not_smi);
2394 } 2394 }
2395 2395
2396 2396
2397 void MacroAssembler::LoadPowerOf2(XMMRegister dst, 2397 void MacroAssembler::LoadPowerOf2(XMMRegister dst,
2398 Register scratch, 2398 Register scratch,
2399 int power) { 2399 int power) {
2400 ASSERT(is_uintn(power + HeapNumber::kExponentBias, 2400 ASSERT(is_uintn(power + HeapNumber::kExponentBias,
2401 HeapNumber::kExponentBits)); 2401 HeapNumber::kExponentBits));
2402 mov(scratch, Immediate(power + HeapNumber::kExponentBias)); 2402 mov(scratch, Immediate(power + HeapNumber::kExponentBias));
2403 movd(dst, Operand(scratch)); 2403 movd(dst, scratch);
2404 psllq(dst, HeapNumber::kMantissaBits); 2404 psllq(dst, HeapNumber::kMantissaBits);
2405 } 2405 }
2406 2406
2407 2407
2408 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii( 2408 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(
2409 Register instance_type, 2409 Register instance_type,
2410 Register scratch, 2410 Register scratch,
2411 Label* failure) { 2411 Label* failure) {
2412 if (!scratch.is(instance_type)) { 2412 if (!scratch.is(instance_type)) {
2413 mov(scratch, instance_type); 2413 mov(scratch, instance_type);
2414 } 2414 }
2415 and_(scratch, 2415 and_(scratch,
2416 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask); 2416 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask);
2417 cmp(scratch, kStringTag | kSeqStringTag | kAsciiStringTag); 2417 cmp(scratch, kStringTag | kSeqStringTag | kAsciiStringTag);
2418 j(not_equal, failure); 2418 j(not_equal, failure);
2419 } 2419 }
2420 2420
2421 2421
2422 void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register object1, 2422 void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register object1,
2423 Register object2, 2423 Register object2,
2424 Register scratch1, 2424 Register scratch1,
2425 Register scratch2, 2425 Register scratch2,
2426 Label* failure) { 2426 Label* failure) {
2427 // Check that both objects are not smis. 2427 // Check that both objects are not smis.
2428 STATIC_ASSERT(kSmiTag == 0); 2428 STATIC_ASSERT(kSmiTag == 0);
2429 mov(scratch1, Operand(object1)); 2429 mov(scratch1, object1);
2430 and_(scratch1, Operand(object2)); 2430 and_(scratch1, object2);
2431 JumpIfSmi(scratch1, failure); 2431 JumpIfSmi(scratch1, failure);
2432 2432
2433 // Load instance type for both strings. 2433 // Load instance type for both strings.
2434 mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset)); 2434 mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset));
2435 mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset)); 2435 mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset));
2436 movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); 2436 movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
2437 movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); 2437 movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
2438 2438
2439 // Check that both are flat ascii strings. 2439 // Check that both are flat ascii strings.
2440 const int kFlatAsciiStringMask = 2440 const int kFlatAsciiStringMask =
2441 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; 2441 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
2442 const int kFlatAsciiStringTag = ASCII_STRING_TYPE; 2442 const int kFlatAsciiStringTag = ASCII_STRING_TYPE;
2443 // Interleave bits from both instance types and compare them in one check. 2443 // Interleave bits from both instance types and compare them in one check.
2444 ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); 2444 ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3));
2445 and_(scratch1, kFlatAsciiStringMask); 2445 and_(scratch1, kFlatAsciiStringMask);
2446 and_(scratch2, kFlatAsciiStringMask); 2446 and_(scratch2, kFlatAsciiStringMask);
2447 lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); 2447 lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
2448 cmp(scratch1, kFlatAsciiStringTag | (kFlatAsciiStringTag << 3)); 2448 cmp(scratch1, kFlatAsciiStringTag | (kFlatAsciiStringTag << 3));
2449 j(not_equal, failure); 2449 j(not_equal, failure);
2450 } 2450 }
2451 2451
2452 2452
2453 void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) { 2453 void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
2454 int frame_alignment = OS::ActivationFrameAlignment(); 2454 int frame_alignment = OS::ActivationFrameAlignment();
2455 if (frame_alignment != 0) { 2455 if (frame_alignment != 0) {
2456 // Make stack end at alignment and make room for num_arguments words 2456 // Make stack end at alignment and make room for num_arguments words
2457 // and the original value of esp. 2457 // and the original value of esp.
2458 mov(scratch, esp); 2458 mov(scratch, esp);
2459 sub(Operand(esp), Immediate((num_arguments + 1) * kPointerSize)); 2459 sub(esp, Immediate((num_arguments + 1) * kPointerSize));
2460 ASSERT(IsPowerOf2(frame_alignment)); 2460 ASSERT(IsPowerOf2(frame_alignment));
2461 and_(esp, -frame_alignment); 2461 and_(esp, -frame_alignment);
2462 mov(Operand(esp, num_arguments * kPointerSize), scratch); 2462 mov(Operand(esp, num_arguments * kPointerSize), scratch);
2463 } else { 2463 } else {
2464 sub(Operand(esp), Immediate(num_arguments * kPointerSize)); 2464 sub(esp, Immediate(num_arguments * kPointerSize));
2465 } 2465 }
2466 } 2466 }
2467 2467
2468 2468
2469 void MacroAssembler::CallCFunction(ExternalReference function, 2469 void MacroAssembler::CallCFunction(ExternalReference function,
2470 int num_arguments) { 2470 int num_arguments) {
2471 // Trashing eax is ok as it will be the return value. 2471 // Trashing eax is ok as it will be the return value.
2472 mov(Operand(eax), Immediate(function)); 2472 mov(eax, Immediate(function));
2473 CallCFunction(eax, num_arguments); 2473 CallCFunction(eax, num_arguments);
2474 } 2474 }
2475 2475
2476 2476
2477 void MacroAssembler::CallCFunction(Register function, 2477 void MacroAssembler::CallCFunction(Register function,
2478 int num_arguments) { 2478 int num_arguments) {
2479 ASSERT(has_frame()); 2479 ASSERT(has_frame());
2480 // Check stack alignment. 2480 // Check stack alignment.
2481 if (emit_debug_code()) { 2481 if (emit_debug_code()) {
2482 CheckStackAlignment(); 2482 CheckStackAlignment();
2483 } 2483 }
2484 2484
2485 call(Operand(function)); 2485 call(function);
2486 if (OS::ActivationFrameAlignment() != 0) { 2486 if (OS::ActivationFrameAlignment() != 0) {
2487 mov(esp, Operand(esp, num_arguments * kPointerSize)); 2487 mov(esp, Operand(esp, num_arguments * kPointerSize));
2488 } else { 2488 } else {
2489 add(Operand(esp), Immediate(num_arguments * kPointerSize)); 2489 add(esp, Immediate(num_arguments * kPointerSize));
2490 } 2490 }
2491 } 2491 }
2492 2492
2493 2493
2494 bool AreAliased(Register r1, Register r2, Register r3, Register r4) { 2494 bool AreAliased(Register r1, Register r2, Register r3, Register r4) {
2495 if (r1.is(r2)) return true; 2495 if (r1.is(r2)) return true;
2496 if (r1.is(r3)) return true; 2496 if (r1.is(r3)) return true;
2497 if (r1.is(r4)) return true; 2497 if (r1.is(r4)) return true;
2498 if (r2.is(r3)) return true; 2498 if (r2.is(r3)) return true;
2499 if (r2.is(r4)) return true; 2499 if (r2.is(r4)) return true;
(...skipping 28 matching lines...) Expand all
2528 Register scratch, 2528 Register scratch,
2529 int mask, 2529 int mask,
2530 Condition cc, 2530 Condition cc,
2531 Label* condition_met, 2531 Label* condition_met,
2532 Label::Distance condition_met_distance) { 2532 Label::Distance condition_met_distance) {
2533 ASSERT(cc == zero || cc == not_zero); 2533 ASSERT(cc == zero || cc == not_zero);
2534 if (scratch.is(object)) { 2534 if (scratch.is(object)) {
2535 and_(scratch, Immediate(~Page::kPageAlignmentMask)); 2535 and_(scratch, Immediate(~Page::kPageAlignmentMask));
2536 } else { 2536 } else {
2537 mov(scratch, Immediate(~Page::kPageAlignmentMask)); 2537 mov(scratch, Immediate(~Page::kPageAlignmentMask));
2538 and_(scratch, Operand(object)); 2538 and_(scratch, object);
2539 } 2539 }
2540 if (mask < (1 << kBitsPerByte)) { 2540 if (mask < (1 << kBitsPerByte)) {
2541 test_b(Operand(scratch, MemoryChunk::kFlagsOffset), 2541 test_b(Operand(scratch, MemoryChunk::kFlagsOffset),
2542 static_cast<uint8_t>(mask)); 2542 static_cast<uint8_t>(mask));
2543 } else { 2543 } else {
2544 test(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask)); 2544 test(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
2545 } 2545 }
2546 j(cc, condition_met, condition_met_distance); 2546 j(cc, condition_met, condition_met_distance);
2547 } 2547 }
2548 2548
(...skipping 17 matching lines...) Expand all
2566 Label::Distance has_color_distance, 2566 Label::Distance has_color_distance,
2567 int first_bit, 2567 int first_bit,
2568 int second_bit) { 2568 int second_bit) {
2569 ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, ecx)); 2569 ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, ecx));
2570 2570
2571 GetMarkBits(object, bitmap_scratch, mask_scratch); 2571 GetMarkBits(object, bitmap_scratch, mask_scratch);
2572 2572
2573 Label other_color, word_boundary; 2573 Label other_color, word_boundary;
2574 test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); 2574 test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
2575 j(first_bit == 1 ? zero : not_zero, &other_color, Label::kNear); 2575 j(first_bit == 1 ? zero : not_zero, &other_color, Label::kNear);
2576 add(mask_scratch, Operand(mask_scratch)); // Shift left 1 by adding. 2576 add(mask_scratch, mask_scratch); // Shift left 1 by adding.
2577 j(zero, &word_boundary, Label::kNear); 2577 j(zero, &word_boundary, Label::kNear);
2578 test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); 2578 test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
2579 j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance); 2579 j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
2580 jmp(&other_color, Label::kNear); 2580 jmp(&other_color, Label::kNear);
2581 2581
2582 bind(&word_boundary); 2582 bind(&word_boundary);
2583 test_b(Operand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize), 1); 2583 test_b(Operand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize), 1);
2584 2584
2585 j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance); 2585 j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
2586 bind(&other_color); 2586 bind(&other_color);
2587 } 2587 }
2588 2588
2589 2589
2590 void MacroAssembler::GetMarkBits(Register addr_reg, 2590 void MacroAssembler::GetMarkBits(Register addr_reg,
2591 Register bitmap_reg, 2591 Register bitmap_reg,
2592 Register mask_reg) { 2592 Register mask_reg) {
2593 ASSERT(!AreAliased(addr_reg, mask_reg, bitmap_reg, ecx)); 2593 ASSERT(!AreAliased(addr_reg, mask_reg, bitmap_reg, ecx));
2594 mov(bitmap_reg, Immediate(~Page::kPageAlignmentMask)); 2594 mov(bitmap_reg, Immediate(~Page::kPageAlignmentMask));
2595 and_(Operand(bitmap_reg), addr_reg); 2595 and_(bitmap_reg, addr_reg);
2596 mov(ecx, Operand(addr_reg)); 2596 mov(ecx, addr_reg);
2597 int shift = 2597 int shift =
2598 Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2; 2598 Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2;
2599 shr(ecx, shift); 2599 shr(ecx, shift);
2600 and_(ecx, 2600 and_(ecx,
2601 (Page::kPageAlignmentMask >> shift) & ~(Bitmap::kBytesPerCell - 1)); 2601 (Page::kPageAlignmentMask >> shift) & ~(Bitmap::kBytesPerCell - 1));
2602 2602
2603 add(bitmap_reg, Operand(ecx)); 2603 add(bitmap_reg, ecx);
2604 mov(ecx, Operand(addr_reg)); 2604 mov(ecx, addr_reg);
2605 shr(ecx, kPointerSizeLog2); 2605 shr(ecx, kPointerSizeLog2);
2606 and_(ecx, (1 << Bitmap::kBitsPerCellLog2) - 1); 2606 and_(ecx, (1 << Bitmap::kBitsPerCellLog2) - 1);
2607 mov(mask_reg, Immediate(1)); 2607 mov(mask_reg, Immediate(1));
2608 shl_cl(mask_reg); 2608 shl_cl(mask_reg);
2609 } 2609 }
2610 2610
2611 2611
2612 void MacroAssembler::EnsureNotWhite( 2612 void MacroAssembler::EnsureNotWhite(
2613 Register value, 2613 Register value,
2614 Register bitmap_scratch, 2614 Register bitmap_scratch,
(...skipping 14 matching lines...) Expand all
2629 // Since both black and grey have a 1 in the first position and white does 2629 // Since both black and grey have a 1 in the first position and white does
2630 // not have a 1 there we only need to check one bit. 2630 // not have a 1 there we only need to check one bit.
2631 test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); 2631 test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
2632 j(not_zero, &done, Label::kNear); 2632 j(not_zero, &done, Label::kNear);
2633 2633
2634 if (FLAG_debug_code) { 2634 if (FLAG_debug_code) {
2635 // Check for impossible bit pattern. 2635 // Check for impossible bit pattern.
2636 Label ok; 2636 Label ok;
2637 push(mask_scratch); 2637 push(mask_scratch);
2638 // shl. May overflow making the check conservative. 2638 // shl. May overflow making the check conservative.
2639 add(mask_scratch, Operand(mask_scratch)); 2639 add(mask_scratch, mask_scratch);
2640 test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); 2640 test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
2641 j(zero, &ok, Label::kNear); 2641 j(zero, &ok, Label::kNear);
2642 int3(); 2642 int3();
2643 bind(&ok); 2643 bind(&ok);
2644 pop(mask_scratch); 2644 pop(mask_scratch);
2645 } 2645 }
2646 2646
2647 // Value is white. We check whether it is data that doesn't need scanning. 2647 // Value is white. We check whether it is data that doesn't need scanning.
2648 // Currently only checks for HeapNumber and non-cons strings. 2648 // Currently only checks for HeapNumber and non-cons strings.
2649 Register map = ecx; // Holds map while checking type. 2649 Register map = ecx; // Holds map while checking type.
2650 Register length = ecx; // Holds length of object after checking type. 2650 Register length = ecx; // Holds length of object after checking type.
2651 Label not_heap_number; 2651 Label not_heap_number;
2652 Label is_data_object; 2652 Label is_data_object;
2653 2653
2654 // Check for heap-number 2654 // Check for heap-number
2655 mov(map, FieldOperand(value, HeapObject::kMapOffset)); 2655 mov(map, FieldOperand(value, HeapObject::kMapOffset));
2656 cmp(map, FACTORY->heap_number_map()); 2656 cmp(map, FACTORY->heap_number_map());
2657 j(not_equal, &not_heap_number, Label::kNear); 2657 j(not_equal, &not_heap_number, Label::kNear);
2658 mov(length, Immediate(HeapNumber::kSize)); 2658 mov(length, Immediate(HeapNumber::kSize));
2659 jmp(&is_data_object, Label::kNear); 2659 jmp(&is_data_object, Label::kNear);
2660 2660
2661 bind(&not_heap_number); 2661 bind(&not_heap_number);
2662 // Check for strings. 2662 // Check for strings.
2663 ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); 2663 ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
2664 ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); 2664 ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
2665 // If it's a string and it's not a cons string then it's an object containing 2665 // If it's a string and it's not a cons string then it's an object containing
2666 // no GC pointers. 2666 // no GC pointers.
2667 Register instance_type = ecx; 2667 Register instance_type = ecx;
2668 movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); 2668 movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
2669 test_b(Operand(instance_type), kIsIndirectStringMask | kIsNotStringMask); 2669 test_b(instance_type, kIsIndirectStringMask | kIsNotStringMask);
2670 j(not_zero, value_is_white_and_not_data); 2670 j(not_zero, value_is_white_and_not_data);
2671 // It's a non-indirect (non-cons and non-slice) string. 2671 // It's a non-indirect (non-cons and non-slice) string.
2672 // If it's external, the length is just ExternalString::kSize. 2672 // If it's external, the length is just ExternalString::kSize.
2673 // Otherwise it's String::kHeaderSize + string->length() * (1 or 2). 2673 // Otherwise it's String::kHeaderSize + string->length() * (1 or 2).
2674 Label not_external; 2674 Label not_external;
2675 // External strings are the only ones with the kExternalStringTag bit 2675 // External strings are the only ones with the kExternalStringTag bit
2676 // set. 2676 // set.
2677 ASSERT_EQ(0, kSeqStringTag & kExternalStringTag); 2677 ASSERT_EQ(0, kSeqStringTag & kExternalStringTag);
2678 ASSERT_EQ(0, kConsStringTag & kExternalStringTag); 2678 ASSERT_EQ(0, kConsStringTag & kExternalStringTag);
2679 test_b(Operand(instance_type), kExternalStringTag); 2679 test_b(instance_type, kExternalStringTag);
2680 j(zero, &not_external, Label::kNear); 2680 j(zero, &not_external, Label::kNear);
2681 mov(length, Immediate(ExternalString::kSize)); 2681 mov(length, Immediate(ExternalString::kSize));
2682 jmp(&is_data_object, Label::kNear); 2682 jmp(&is_data_object, Label::kNear);
2683 2683
2684 bind(&not_external); 2684 bind(&not_external);
2685 // Sequential string, either ASCII or UC16. 2685 // Sequential string, either ASCII or UC16.
2686 ASSERT(kAsciiStringTag == 0x04); 2686 ASSERT(kAsciiStringTag == 0x04);
2687 and_(Operand(length), Immediate(kStringEncodingMask)); 2687 and_(length, Immediate(kStringEncodingMask));
2688 xor_(Operand(length), Immediate(kStringEncodingMask)); 2688 xor_(length, Immediate(kStringEncodingMask));
2689 add(Operand(length), Immediate(0x04)); 2689 add(length, Immediate(0x04));
2690 // Value now either 4 (if ASCII) or 8 (if UC16), i.e., char-size shifted 2690 // Value now either 4 (if ASCII) or 8 (if UC16), i.e., char-size shifted
2691 // by 2. If we multiply the string length as smi by this, it still 2691 // by 2. If we multiply the string length as smi by this, it still
2692 // won't overflow a 32-bit value. 2692 // won't overflow a 32-bit value.
2693 ASSERT_EQ(SeqAsciiString::kMaxSize, SeqTwoByteString::kMaxSize); 2693 ASSERT_EQ(SeqAsciiString::kMaxSize, SeqTwoByteString::kMaxSize);
2694 ASSERT(SeqAsciiString::kMaxSize <= 2694 ASSERT(SeqAsciiString::kMaxSize <=
2695 static_cast<int>(0xffffffffu >> (2 + kSmiTagSize))); 2695 static_cast<int>(0xffffffffu >> (2 + kSmiTagSize)));
2696 imul(length, FieldOperand(value, String::kLengthOffset)); 2696 imul(length, FieldOperand(value, String::kLengthOffset));
2697 shr(length, 2 + kSmiTagSize + kSmiShiftSize); 2697 shr(length, 2 + kSmiTagSize + kSmiShiftSize);
2698 add(Operand(length), 2698 add(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask));
2699 Immediate(SeqString::kHeaderSize + kObjectAlignmentMask)); 2699 and_(length, Immediate(~kObjectAlignmentMask));
2700 and_(Operand(length),
2701 Immediate(~kObjectAlignmentMask));
2702 2700
2703 bind(&is_data_object); 2701 bind(&is_data_object);
2704 // Value is a data object, and it is white. Mark it black. Since we know 2702 // Value is a data object, and it is white. Mark it black. Since we know
2705 // that the object is white we can make it black by flipping one bit. 2703 // that the object is white we can make it black by flipping one bit.
2706 or_(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch); 2704 or_(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch);
2707 2705
2708 and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask)); 2706 and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask));
2709 add(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset), 2707 add(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset),
2710 length); 2708 length);
2711 if (FLAG_debug_code) { 2709 if (FLAG_debug_code) {
2712 mov(length, Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); 2710 mov(length, Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
2713 cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset)); 2711 cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset));
2714 Check(less_equal, "Live Bytes Count overflow chunk size"); 2712 Check(less_equal, "Live Bytes Count overflow chunk size");
2715 } 2713 }
2716 2714
2717 bind(&done); 2715 bind(&done);
2718 } 2716 }
2719 2717
2720 } } // namespace v8::internal 2718 } } // namespace v8::internal
2721 2719
2722 #endif // V8_TARGET_ARCH_IA32 2720 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698