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

Side by Side Diff: src/ia32/ic-ia32.cc

Issue 6880010: Merge (7265, 7271] from bleeding_edge to experimental/gc branch.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 8 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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 86
87 GenerateGlobalInstanceTypeCheck(masm, r0, miss); 87 GenerateGlobalInstanceTypeCheck(masm, r0, miss);
88 88
89 // Check for non-global object that requires access check. 89 // Check for non-global object that requires access check.
90 __ test_b(FieldOperand(r1, Map::kBitFieldOffset), 90 __ test_b(FieldOperand(r1, Map::kBitFieldOffset),
91 (1 << Map::kIsAccessCheckNeeded) | 91 (1 << Map::kIsAccessCheckNeeded) |
92 (1 << Map::kHasNamedInterceptor)); 92 (1 << Map::kHasNamedInterceptor));
93 __ j(not_zero, miss, not_taken); 93 __ j(not_zero, miss, not_taken);
94 94
95 __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); 95 __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset));
96 __ CheckMap(r0, Factory::hash_table_map(), miss, true); 96 __ CheckMap(r0, FACTORY->hash_table_map(), miss, true);
97 } 97 }
98 98
99 99
100 // Probe the string dictionary in the |elements| register. Jump to the 100 // Probe the string dictionary in the |elements| register. Jump to the
101 // |done| label if a property with the given name is found leaving the 101 // |done| label if a property with the given name is found leaving the
102 // index into the dictionary in |r0|. Jump to the |miss| label 102 // index into the dictionary in |r0|. Jump to the |miss| label
103 // otherwise. 103 // otherwise.
104 static void GenerateStringDictionaryProbes(MacroAssembler* masm, 104 static void GenerateStringDictionaryProbes(MacroAssembler* masm,
105 Label* miss, 105 Label* miss,
106 Label* done, 106 Label* done,
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 // receiver - holds the receiver and is unchanged. 468 // receiver - holds the receiver and is unchanged.
469 // key - holds the key and is unchanged (must be a smi). 469 // key - holds the key and is unchanged (must be a smi).
470 // Scratch registers: 470 // Scratch registers:
471 // scratch - used to hold elements of the receiver and the loaded value. 471 // scratch - used to hold elements of the receiver and the loaded value.
472 // result - holds the result on exit if the load succeeds and 472 // result - holds the result on exit if the load succeeds and
473 // we fall through. 473 // we fall through.
474 474
475 __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset)); 475 __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset));
476 if (not_fast_array != NULL) { 476 if (not_fast_array != NULL) {
477 // Check that the object is in fast mode and writable. 477 // Check that the object is in fast mode and writable.
478 __ CheckMap(scratch, Factory::fixed_array_map(), not_fast_array, true); 478 __ CheckMap(scratch, FACTORY->fixed_array_map(), not_fast_array, true);
479 } else { 479 } else {
480 __ AssertFastElements(scratch); 480 __ AssertFastElements(scratch);
481 } 481 }
482 // Check that the key (index) is within bounds. 482 // Check that the key (index) is within bounds.
483 __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset)); 483 __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset));
484 __ j(above_equal, out_of_range); 484 __ j(above_equal, out_of_range);
485 // Fast case: Do the load. 485 // Fast case: Do the load.
486 ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); 486 ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0));
487 __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize)); 487 __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize));
488 __ cmp(Operand(scratch), Immediate(Factory::the_hole_value())); 488 __ cmp(Operand(scratch), Immediate(FACTORY->the_hole_value()));
489 // In case the loaded value is the_hole we have to consult GetProperty 489 // In case the loaded value is the_hole we have to consult GetProperty
490 // to ensure the prototype chain is searched. 490 // to ensure the prototype chain is searched.
491 __ j(equal, out_of_range); 491 __ j(equal, out_of_range);
492 if (!result.is(scratch)) { 492 if (!result.is(scratch)) {
493 __ mov(result, scratch); 493 __ mov(result, scratch);
494 } 494 }
495 } 495 }
496 496
497 497
498 // Checks whether a key is an array index string or a symbol string. 498 // Checks whether a key is an array index string or a symbol string.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 1 << Map::kHasFastElements); 548 1 << Map::kHasFastElements);
549 __ j(zero, &check_number_dictionary, not_taken); 549 __ j(zero, &check_number_dictionary, not_taken);
550 550
551 GenerateFastArrayLoad(masm, 551 GenerateFastArrayLoad(masm,
552 edx, 552 edx,
553 eax, 553 eax,
554 ecx, 554 ecx,
555 eax, 555 eax,
556 NULL, 556 NULL,
557 &slow); 557 &slow);
558 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 558 __ IncrementCounter(COUNTERS->keyed_load_generic_smi(), 1);
559 __ ret(0); 559 __ ret(0);
560 560
561 __ bind(&check_number_dictionary); 561 __ bind(&check_number_dictionary);
562 __ mov(ebx, eax); 562 __ mov(ebx, eax);
563 __ SmiUntag(ebx); 563 __ SmiUntag(ebx);
564 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 564 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
565 565
566 // Check whether the elements is a number dictionary. 566 // Check whether the elements is a number dictionary.
567 // edx: receiver 567 // edx: receiver
568 // ebx: untagged index 568 // ebx: untagged index
569 // eax: key 569 // eax: key
570 // ecx: elements 570 // ecx: elements
571 __ CheckMap(ecx, Factory::hash_table_map(), &slow, true); 571 __ CheckMap(ecx, FACTORY->hash_table_map(), &slow, true);
572 Label slow_pop_receiver; 572 Label slow_pop_receiver;
573 // Push receiver on the stack to free up a register for the dictionary 573 // Push receiver on the stack to free up a register for the dictionary
574 // probing. 574 // probing.
575 __ push(edx); 575 __ push(edx);
576 GenerateNumberDictionaryLoad(masm, 576 GenerateNumberDictionaryLoad(masm,
577 &slow_pop_receiver, 577 &slow_pop_receiver,
578 ecx, 578 ecx,
579 eax, 579 eax,
580 ebx, 580 ebx,
581 edx, 581 edx,
582 edi, 582 edi,
583 eax); 583 eax);
584 // Pop receiver before returning. 584 // Pop receiver before returning.
585 __ pop(edx); 585 __ pop(edx);
586 __ ret(0); 586 __ ret(0);
587 587
588 __ bind(&slow_pop_receiver); 588 __ bind(&slow_pop_receiver);
589 // Pop the receiver from the stack and jump to runtime. 589 // Pop the receiver from the stack and jump to runtime.
590 __ pop(edx); 590 __ pop(edx);
591 591
592 __ bind(&slow); 592 __ bind(&slow);
593 // Slow case: jump to runtime. 593 // Slow case: jump to runtime.
594 // edx: receiver 594 // edx: receiver
595 // eax: key 595 // eax: key
596 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); 596 __ IncrementCounter(COUNTERS->keyed_load_generic_slow(), 1);
597 GenerateRuntimeGetProperty(masm); 597 GenerateRuntimeGetProperty(masm);
598 598
599 __ bind(&check_string); 599 __ bind(&check_string);
600 GenerateKeyStringCheck(masm, eax, ecx, ebx, &index_string, &slow); 600 GenerateKeyStringCheck(masm, eax, ecx, ebx, &index_string, &slow);
601 601
602 GenerateKeyedLoadReceiverCheck( 602 GenerateKeyedLoadReceiverCheck(
603 masm, edx, ecx, Map::kHasNamedInterceptor, &slow); 603 masm, edx, ecx, Map::kHasNamedInterceptor, &slow);
604 604
605 // If the receiver is a fast-case object, check the keyed lookup 605 // If the receiver is a fast-case object, check the keyed lookup
606 // cache. Otherwise probe the dictionary. 606 // cache. Otherwise probe the dictionary.
607 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); 607 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
608 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 608 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
609 Immediate(Factory::hash_table_map())); 609 Immediate(FACTORY->hash_table_map()));
610 __ j(equal, &probe_dictionary); 610 __ j(equal, &probe_dictionary);
611 611
612 // Load the map of the receiver, compute the keyed lookup cache hash 612 // Load the map of the receiver, compute the keyed lookup cache hash
613 // based on 32 bits of the map pointer and the string hash. 613 // based on 32 bits of the map pointer and the string hash.
614 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 614 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
615 __ mov(ecx, ebx); 615 __ mov(ecx, ebx);
616 __ shr(ecx, KeyedLookupCache::kMapHashShift); 616 __ shr(ecx, KeyedLookupCache::kMapHashShift);
617 __ mov(edi, FieldOperand(eax, String::kHashFieldOffset)); 617 __ mov(edi, FieldOperand(eax, String::kHashFieldOffset));
618 __ shr(edi, String::kHashShift); 618 __ shr(edi, String::kHashShift);
619 __ xor_(ecx, Operand(edi)); 619 __ xor_(ecx, Operand(edi));
(...skipping 21 matching lines...) Expand all
641 __ mov(edi, 641 __ mov(edi,
642 Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets)); 642 Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets));
643 __ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset)); 643 __ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset));
644 __ sub(edi, Operand(ecx)); 644 __ sub(edi, Operand(ecx));
645 __ j(above_equal, &property_array_property); 645 __ j(above_equal, &property_array_property);
646 646
647 // Load in-object property. 647 // Load in-object property.
648 __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset)); 648 __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset));
649 __ add(ecx, Operand(edi)); 649 __ add(ecx, Operand(edi));
650 __ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0)); 650 __ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0));
651 __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1); 651 __ IncrementCounter(COUNTERS->keyed_load_generic_lookup_cache(), 1);
652 __ ret(0); 652 __ ret(0);
653 653
654 // Load property array property. 654 // Load property array property.
655 __ bind(&property_array_property); 655 __ bind(&property_array_property);
656 __ mov(eax, FieldOperand(edx, JSObject::kPropertiesOffset)); 656 __ mov(eax, FieldOperand(edx, JSObject::kPropertiesOffset));
657 __ mov(eax, FieldOperand(eax, edi, times_pointer_size, 657 __ mov(eax, FieldOperand(eax, edi, times_pointer_size,
658 FixedArray::kHeaderSize)); 658 FixedArray::kHeaderSize));
659 __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1); 659 __ IncrementCounter(COUNTERS->keyed_load_generic_lookup_cache(), 1);
660 __ ret(0); 660 __ ret(0);
661 661
662 // Do a quick inline probe of the receiver's dictionary, if it 662 // Do a quick inline probe of the receiver's dictionary, if it
663 // exists. 663 // exists.
664 __ bind(&probe_dictionary); 664 __ bind(&probe_dictionary);
665 665
666 __ mov(ecx, FieldOperand(edx, JSObject::kMapOffset)); 666 __ mov(ecx, FieldOperand(edx, JSObject::kMapOffset));
667 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 667 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
668 GenerateGlobalInstanceTypeCheck(masm, ecx, &slow); 668 GenerateGlobalInstanceTypeCheck(masm, ecx, &slow);
669 669
670 GenerateDictionaryLoad(masm, &slow, ebx, eax, ecx, edi, eax); 670 GenerateDictionaryLoad(masm, &slow, ebx, eax, ecx, edi, eax);
671 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); 671 __ IncrementCounter(COUNTERS->keyed_load_generic_symbol(), 1);
672 __ ret(0); 672 __ ret(0);
673 673
674 __ bind(&index_string); 674 __ bind(&index_string);
675 __ IndexFromHash(ebx, eax); 675 __ IndexFromHash(ebx, eax);
676 // Now jump to the place where smi keys are handled. 676 // Now jump to the place where smi keys are handled.
677 __ jmp(&index_smi); 677 __ jmp(&index_smi);
678 } 678 }
679 679
680 680
681 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { 681 void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 // Check that the object is some kind of JS object. 782 // Check that the object is some kind of JS object.
783 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); 783 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE);
784 __ j(below, &slow, not_taken); 784 __ j(below, &slow, not_taken);
785 785
786 // Object case: Check key against length in the elements array. 786 // Object case: Check key against length in the elements array.
787 // eax: value 787 // eax: value
788 // edx: JSObject 788 // edx: JSObject
789 // ecx: key (a smi) 789 // ecx: key (a smi)
790 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 790 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
791 // Check that the object is in fast mode and writable. 791 // Check that the object is in fast mode and writable.
792 __ CheckMap(edi, Factory::fixed_array_map(), &slow, true); 792 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, true);
793 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); 793 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
794 __ j(below, &fast, taken); 794 __ j(below, &fast, taken);
795 795
796 // Slow case: call runtime. 796 // Slow case: call runtime.
797 __ bind(&slow); 797 __ bind(&slow);
798 GenerateRuntimeSetProperty(masm, strict_mode); 798 GenerateRuntimeSetProperty(masm, strict_mode);
799 799
800 // Extra capacity case: Check if there is extra capacity to 800 // Extra capacity case: Check if there is extra capacity to
801 // perform the store and update the length. Used for adding one 801 // perform the store and update the length. Used for adding one
802 // element to the array by writing to array[array.length]. 802 // element to the array by writing to array[array.length].
(...skipping 12 matching lines...) Expand all
815 __ jmp(&fast); 815 __ jmp(&fast);
816 816
817 // Array case: Get the length and the elements array from the JS 817 // Array case: Get the length and the elements array from the JS
818 // array. Check that the array is in fast mode (and writable); if it 818 // array. Check that the array is in fast mode (and writable); if it
819 // is the length is always a smi. 819 // is the length is always a smi.
820 __ bind(&array); 820 __ bind(&array);
821 // eax: value 821 // eax: value
822 // edx: receiver, a JSArray 822 // edx: receiver, a JSArray
823 // ecx: key, a smi. 823 // ecx: key, a smi.
824 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 824 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
825 __ CheckMap(edi, Factory::fixed_array_map(), &slow, true); 825 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, true);
826 826
827 // Check the key against the length in the array, compute the 827 // Check the key against the length in the array, compute the
828 // address to store into and fall through to fast case. 828 // address to store into and fall through to fast case.
829 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. 829 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis.
830 __ j(above_equal, &extra, not_taken); 830 __ j(above_equal, &extra, not_taken);
831 831
832 // Fast case: Do the store. 832 // Fast case: Do the store.
833 __ bind(&fast); 833 __ bind(&fast);
834 // eax: value 834 // eax: value
835 // ecx: key (a smi) 835 // ecx: key (a smi)
(...skipping 19 matching lines...) Expand all
855 // ----------------------------------- 855 // -----------------------------------
856 Label number, non_number, non_string, boolean, probe, miss; 856 Label number, non_number, non_string, boolean, probe, miss;
857 857
858 // Probe the stub cache. 858 // Probe the stub cache.
859 Code::Flags flags = Code::ComputeFlags(kind, 859 Code::Flags flags = Code::ComputeFlags(kind,
860 NOT_IN_LOOP, 860 NOT_IN_LOOP,
861 MONOMORPHIC, 861 MONOMORPHIC,
862 Code::kNoExtraICState, 862 Code::kNoExtraICState,
863 NORMAL, 863 NORMAL,
864 argc); 864 argc);
865 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, eax); 865 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx,
866 eax);
866 867
867 // If the stub cache probing failed, the receiver might be a value. 868 // If the stub cache probing failed, the receiver might be a value.
868 // For value objects, we use the map of the prototype objects for 869 // For value objects, we use the map of the prototype objects for
869 // the corresponding JSValue for the cache and that is what we need 870 // the corresponding JSValue for the cache and that is what we need
870 // to probe. 871 // to probe.
871 // 872 //
872 // Check for number. 873 // Check for number.
873 __ test(edx, Immediate(kSmiTagMask)); 874 __ test(edx, Immediate(kSmiTagMask));
874 __ j(zero, &number, not_taken); 875 __ j(zero, &number, not_taken);
875 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx); 876 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx);
876 __ j(not_equal, &non_number, taken); 877 __ j(not_equal, &non_number, taken);
877 __ bind(&number); 878 __ bind(&number);
878 StubCompiler::GenerateLoadGlobalFunctionPrototype( 879 StubCompiler::GenerateLoadGlobalFunctionPrototype(
879 masm, Context::NUMBER_FUNCTION_INDEX, edx); 880 masm, Context::NUMBER_FUNCTION_INDEX, edx);
880 __ jmp(&probe); 881 __ jmp(&probe);
881 882
882 // Check for string. 883 // Check for string.
883 __ bind(&non_number); 884 __ bind(&non_number);
884 __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE); 885 __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE);
885 __ j(above_equal, &non_string, taken); 886 __ j(above_equal, &non_string, taken);
886 StubCompiler::GenerateLoadGlobalFunctionPrototype( 887 StubCompiler::GenerateLoadGlobalFunctionPrototype(
887 masm, Context::STRING_FUNCTION_INDEX, edx); 888 masm, Context::STRING_FUNCTION_INDEX, edx);
888 __ jmp(&probe); 889 __ jmp(&probe);
889 890
890 // Check for boolean. 891 // Check for boolean.
891 __ bind(&non_string); 892 __ bind(&non_string);
892 __ cmp(edx, Factory::true_value()); 893 __ cmp(edx, FACTORY->true_value());
893 __ j(equal, &boolean, not_taken); 894 __ j(equal, &boolean, not_taken);
894 __ cmp(edx, Factory::false_value()); 895 __ cmp(edx, FACTORY->false_value());
895 __ j(not_equal, &miss, taken); 896 __ j(not_equal, &miss, taken);
896 __ bind(&boolean); 897 __ bind(&boolean);
897 StubCompiler::GenerateLoadGlobalFunctionPrototype( 898 StubCompiler::GenerateLoadGlobalFunctionPrototype(
898 masm, Context::BOOLEAN_FUNCTION_INDEX, edx); 899 masm, Context::BOOLEAN_FUNCTION_INDEX, edx);
899 900
900 // Probe the stub cache for the value object. 901 // Probe the stub cache for the value object.
901 __ bind(&probe); 902 __ bind(&probe);
902 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); 903 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx,
904 no_reg);
903 __ bind(&miss); 905 __ bind(&miss);
904 } 906 }
905 907
906 908
907 static void GenerateFunctionTailCall(MacroAssembler* masm, 909 static void GenerateFunctionTailCall(MacroAssembler* masm,
908 int argc, 910 int argc,
909 Label* miss) { 911 Label* miss) {
910 // ----------- S t a t e ------------- 912 // ----------- S t a t e -------------
911 // -- ecx : name 913 // -- ecx : name
912 // -- edi : function 914 // -- edi : function
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
959 IC::UtilityId id) { 961 IC::UtilityId id) {
960 // ----------- S t a t e ------------- 962 // ----------- S t a t e -------------
961 // -- ecx : name 963 // -- ecx : name
962 // -- esp[0] : return address 964 // -- esp[0] : return address
963 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 965 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
964 // -- ... 966 // -- ...
965 // -- esp[(argc + 1) * 4] : receiver 967 // -- esp[(argc + 1) * 4] : receiver
966 // ----------------------------------- 968 // -----------------------------------
967 969
968 if (id == IC::kCallIC_Miss) { 970 if (id == IC::kCallIC_Miss) {
969 __ IncrementCounter(&Counters::call_miss, 1); 971 __ IncrementCounter(COUNTERS->call_miss(), 1);
970 } else { 972 } else {
971 __ IncrementCounter(&Counters::keyed_call_miss, 1); 973 __ IncrementCounter(COUNTERS->keyed_call_miss(), 1);
972 } 974 }
973 975
974 // Get the receiver of the function from the stack; 1 ~ return address. 976 // Get the receiver of the function from the stack; 1 ~ return address.
975 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 977 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
976 978
977 // Enter an internal frame. 979 // Enter an internal frame.
978 __ EnterInternalFrame(); 980 __ EnterInternalFrame();
979 981
980 // Push the receiver and the name of the function. 982 // Push the receiver and the name of the function.
981 __ push(edx); 983 __ push(edx);
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1083 1085
1084 __ bind(&index_smi); 1086 __ bind(&index_smi);
1085 // Now the key is known to be a smi. This place is also jumped to from 1087 // Now the key is known to be a smi. This place is also jumped to from
1086 // where a numeric string is converted to a smi. 1088 // where a numeric string is converted to a smi.
1087 1089
1088 GenerateKeyedLoadReceiverCheck( 1090 GenerateKeyedLoadReceiverCheck(
1089 masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call); 1091 masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call);
1090 1092
1091 GenerateFastArrayLoad( 1093 GenerateFastArrayLoad(
1092 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load); 1094 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load);
1093 __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1); 1095 __ IncrementCounter(COUNTERS->keyed_call_generic_smi_fast(), 1);
1094 1096
1095 __ bind(&do_call); 1097 __ bind(&do_call);
1096 // receiver in edx is not used after this point. 1098 // receiver in edx is not used after this point.
1097 // ecx: key 1099 // ecx: key
1098 // edi: function 1100 // edi: function
1099 GenerateFunctionTailCall(masm, argc, &slow_call); 1101 GenerateFunctionTailCall(masm, argc, &slow_call);
1100 1102
1101 __ bind(&check_number_dictionary); 1103 __ bind(&check_number_dictionary);
1102 // eax: elements 1104 // eax: elements
1103 // ecx: smi key 1105 // ecx: smi key
1104 // Check whether the elements is a number dictionary. 1106 // Check whether the elements is a number dictionary.
1105 __ CheckMap(eax, Factory::hash_table_map(), &slow_load, true); 1107 __ CheckMap(eax, FACTORY->hash_table_map(), &slow_load, true);
1106 __ mov(ebx, ecx); 1108 __ mov(ebx, ecx);
1107 __ SmiUntag(ebx); 1109 __ SmiUntag(ebx);
1108 // ebx: untagged index 1110 // ebx: untagged index
1109 // Receiver in edx will be clobbered, need to reload it on miss. 1111 // Receiver in edx will be clobbered, need to reload it on miss.
1110 GenerateNumberDictionaryLoad( 1112 GenerateNumberDictionaryLoad(
1111 masm, &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi); 1113 masm, &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi);
1112 __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1); 1114 __ IncrementCounter(COUNTERS->keyed_call_generic_smi_dict(), 1);
1113 __ jmp(&do_call); 1115 __ jmp(&do_call);
1114 1116
1115 __ bind(&slow_reload_receiver); 1117 __ bind(&slow_reload_receiver);
1116 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1118 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1117 1119
1118 __ bind(&slow_load); 1120 __ bind(&slow_load);
1119 // This branch is taken when calling KeyedCallIC_Miss is neither required 1121 // This branch is taken when calling KeyedCallIC_Miss is neither required
1120 // nor beneficial. 1122 // nor beneficial.
1121 __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1); 1123 __ IncrementCounter(COUNTERS->keyed_call_generic_slow_load(), 1);
1122 __ EnterInternalFrame(); 1124 __ EnterInternalFrame();
1123 __ push(ecx); // save the key 1125 __ push(ecx); // save the key
1124 __ push(edx); // pass the receiver 1126 __ push(edx); // pass the receiver
1125 __ push(ecx); // pass the key 1127 __ push(ecx); // pass the key
1126 __ CallRuntime(Runtime::kKeyedGetProperty, 2); 1128 __ CallRuntime(Runtime::kKeyedGetProperty, 2);
1127 __ pop(ecx); // restore the key 1129 __ pop(ecx); // restore the key
1128 __ LeaveInternalFrame(); 1130 __ LeaveInternalFrame();
1129 __ mov(edi, eax); 1131 __ mov(edi, eax);
1130 __ jmp(&do_call); 1132 __ jmp(&do_call);
1131 1133
1132 __ bind(&check_string); 1134 __ bind(&check_string);
1133 GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow_call); 1135 GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow_call);
1134 1136
1135 // The key is known to be a symbol. 1137 // The key is known to be a symbol.
1136 // If the receiver is a regular JS object with slow properties then do 1138 // If the receiver is a regular JS object with slow properties then do
1137 // a quick inline probe of the receiver's dictionary. 1139 // a quick inline probe of the receiver's dictionary.
1138 // Otherwise do the monomorphic cache probe. 1140 // Otherwise do the monomorphic cache probe.
1139 GenerateKeyedLoadReceiverCheck( 1141 GenerateKeyedLoadReceiverCheck(
1140 masm, edx, eax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache); 1142 masm, edx, eax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache);
1141 1143
1142 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); 1144 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
1143 __ CheckMap(ebx, Factory::hash_table_map(), &lookup_monomorphic_cache, true); 1145 __ CheckMap(ebx, FACTORY->hash_table_map(), &lookup_monomorphic_cache, true);
1144 1146
1145 GenerateDictionaryLoad(masm, &slow_load, ebx, ecx, eax, edi, edi); 1147 GenerateDictionaryLoad(masm, &slow_load, ebx, ecx, eax, edi, edi);
1146 __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1); 1148 __ IncrementCounter(COUNTERS->keyed_call_generic_lookup_dict(), 1);
1147 __ jmp(&do_call); 1149 __ jmp(&do_call);
1148 1150
1149 __ bind(&lookup_monomorphic_cache); 1151 __ bind(&lookup_monomorphic_cache);
1150 __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1); 1152 __ IncrementCounter(COUNTERS->keyed_call_generic_lookup_cache(), 1);
1151 GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC); 1153 GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC);
1152 // Fall through on miss. 1154 // Fall through on miss.
1153 1155
1154 __ bind(&slow_call); 1156 __ bind(&slow_call);
1155 // This branch is taken if: 1157 // This branch is taken if:
1156 // - the receiver requires boxing or access check, 1158 // - the receiver requires boxing or access check,
1157 // - the key is neither smi nor symbol, 1159 // - the key is neither smi nor symbol,
1158 // - the value loaded is not a function, 1160 // - the value loaded is not a function,
1159 // - there is hope that the runtime will create a monomorphic call stub 1161 // - there is hope that the runtime will create a monomorphic call stub
1160 // that will get fetched next time. 1162 // that will get fetched next time.
1161 __ IncrementCounter(&Counters::keyed_call_generic_slow, 1); 1163 __ IncrementCounter(COUNTERS->keyed_call_generic_slow(), 1);
1162 GenerateMiss(masm, argc); 1164 GenerateMiss(masm, argc);
1163 1165
1164 __ bind(&index_string); 1166 __ bind(&index_string);
1165 __ IndexFromHash(ebx, ecx); 1167 __ IndexFromHash(ebx, ecx);
1166 // Now jump to the place where smi keys are handled. 1168 // Now jump to the place where smi keys are handled.
1167 __ jmp(&index_smi); 1169 __ jmp(&index_smi);
1168 } 1170 }
1169 1171
1170 1172
1171 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { 1173 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1206 // ----------- S t a t e ------------- 1208 // ----------- S t a t e -------------
1207 // -- eax : receiver 1209 // -- eax : receiver
1208 // -- ecx : name 1210 // -- ecx : name
1209 // -- esp[0] : return address 1211 // -- esp[0] : return address
1210 // ----------------------------------- 1212 // -----------------------------------
1211 1213
1212 // Probe the stub cache. 1214 // Probe the stub cache.
1213 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, 1215 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
1214 NOT_IN_LOOP, 1216 NOT_IN_LOOP,
1215 MONOMORPHIC); 1217 MONOMORPHIC);
1216 StubCache::GenerateProbe(masm, flags, eax, ecx, ebx, edx); 1218 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, eax, ecx, ebx,
1219 edx);
1217 1220
1218 // Cache miss: Jump to runtime. 1221 // Cache miss: Jump to runtime.
1219 GenerateMiss(masm); 1222 GenerateMiss(masm);
1220 } 1223 }
1221 1224
1222 1225
1223 void LoadIC::GenerateNormal(MacroAssembler* masm) { 1226 void LoadIC::GenerateNormal(MacroAssembler* masm) {
1224 // ----------- S t a t e ------------- 1227 // ----------- S t a t e -------------
1225 // -- eax : receiver 1228 // -- eax : receiver
1226 // -- ecx : name 1229 // -- ecx : name
(...skipping 14 matching lines...) Expand all
1241 } 1244 }
1242 1245
1243 1246
1244 void LoadIC::GenerateMiss(MacroAssembler* masm) { 1247 void LoadIC::GenerateMiss(MacroAssembler* masm) {
1245 // ----------- S t a t e ------------- 1248 // ----------- S t a t e -------------
1246 // -- eax : receiver 1249 // -- eax : receiver
1247 // -- ecx : name 1250 // -- ecx : name
1248 // -- esp[0] : return address 1251 // -- esp[0] : return address
1249 // ----------------------------------- 1252 // -----------------------------------
1250 1253
1251 __ IncrementCounter(&Counters::load_miss, 1); 1254 __ IncrementCounter(COUNTERS->load_miss(), 1);
1252 1255
1253 __ pop(ebx); 1256 __ pop(ebx);
1254 __ push(eax); // receiver 1257 __ push(eax); // receiver
1255 __ push(ecx); // name 1258 __ push(ecx); // name
1256 __ push(ebx); // return address 1259 __ push(ebx); // return address
1257 1260
1258 // Perform tail call to the entry. 1261 // Perform tail call to the entry.
1259 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); 1262 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss));
1260 __ TailCallExternalReference(ref, 2, 1); 1263 __ TailCallExternalReference(ref, 2, 1);
1261 } 1264 }
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1369 *(reinterpret_cast<Object**>(map_address)) = map; 1372 *(reinterpret_cast<Object**>(map_address)) = map;
1370 1373
1371 // Patch the offset in the store instruction. The offset is in the 1374 // Patch the offset in the store instruction. The offset is in the
1372 // last 4 bytes of a six byte register-to-memory move instruction. 1375 // last 4 bytes of a six byte register-to-memory move instruction.
1373 Address offset_address = 1376 Address offset_address =
1374 map_check_address + StoreIC::kOffsetToStoreInstruction + 2; 1377 map_check_address + StoreIC::kOffsetToStoreInstruction + 2;
1375 // The offset should have initial value (kMaxInt - 1), cleared value 1378 // The offset should have initial value (kMaxInt - 1), cleared value
1376 // (-1) or we should be clearing the inlined version. 1379 // (-1) or we should be clearing the inlined version.
1377 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt - 1 || 1380 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt - 1 ||
1378 *reinterpret_cast<int*>(offset_address) == -1 || 1381 *reinterpret_cast<int*>(offset_address) == -1 ||
1379 (offset == 0 && map == Heap::null_value())); 1382 (offset == 0 && map == HEAP->null_value()));
1380 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; 1383 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag;
1381 1384
1382 // Patch the offset in the write-barrier code. The offset is the 1385 // Patch the offset in the write-barrier code. The offset is the
1383 // last 4 bytes of a six byte lea instruction. 1386 // last 4 bytes of a six byte lea instruction.
1384 offset_address = map_check_address + delta_to_record_write + 2; 1387 offset_address = map_check_address + delta_to_record_write + 2;
1385 // The offset should have initial value (kMaxInt), cleared value 1388 // The offset should have initial value (kMaxInt), cleared value
1386 // (-1) or we should be clearing the inlined version. 1389 // (-1) or we should be clearing the inlined version.
1387 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt || 1390 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt ||
1388 *reinterpret_cast<int*>(offset_address) == -1 || 1391 *reinterpret_cast<int*>(offset_address) == -1 ||
1389 (offset == 0 && map == Heap::null_value())); 1392 (offset == 0 && map == HEAP->null_value()));
1390 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; 1393 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag;
1391 1394
1392 return true; 1395 return true;
1393 } 1396 }
1394 1397
1395 1398
1396 static bool PatchInlinedMapCheck(Address address, Object* map) { 1399 static bool PatchInlinedMapCheck(Address address, Object* map) {
1397 if (V8::UseCrankshaft()) return false; 1400 if (V8::UseCrankshaft()) return false;
1398 1401
1399 Address test_instruction_address = 1402 Address test_instruction_address =
(...skipping 27 matching lines...) Expand all
1427 } 1430 }
1428 1431
1429 1432
1430 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 1433 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
1431 // ----------- S t a t e ------------- 1434 // ----------- S t a t e -------------
1432 // -- eax : key 1435 // -- eax : key
1433 // -- edx : receiver 1436 // -- edx : receiver
1434 // -- esp[0] : return address 1437 // -- esp[0] : return address
1435 // ----------------------------------- 1438 // -----------------------------------
1436 1439
1437 __ IncrementCounter(&Counters::keyed_load_miss, 1); 1440 __ IncrementCounter(COUNTERS->keyed_load_miss(), 1);
1438 1441
1439 __ pop(ebx); 1442 __ pop(ebx);
1440 __ push(edx); // receiver 1443 __ push(edx); // receiver
1441 __ push(eax); // name 1444 __ push(eax); // name
1442 __ push(ebx); // return address 1445 __ push(ebx); // return address
1443 1446
1444 // Perform tail call to the entry. 1447 // Perform tail call to the entry.
1445 ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss)); 1448 ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss));
1446 __ TailCallExternalReference(ref, 2, 1); 1449 __ TailCallExternalReference(ref, 2, 1);
1447 } 1450 }
(...skipping 22 matching lines...) Expand all
1470 // -- eax : value 1473 // -- eax : value
1471 // -- ecx : name 1474 // -- ecx : name
1472 // -- edx : receiver 1475 // -- edx : receiver
1473 // -- esp[0] : return address 1476 // -- esp[0] : return address
1474 // ----------------------------------- 1477 // -----------------------------------
1475 1478
1476 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, 1479 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
1477 NOT_IN_LOOP, 1480 NOT_IN_LOOP,
1478 MONOMORPHIC, 1481 MONOMORPHIC,
1479 strict_mode); 1482 strict_mode);
1480 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); 1483 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx,
1484 no_reg);
1481 1485
1482 // Cache miss: Jump to runtime. 1486 // Cache miss: Jump to runtime.
1483 GenerateMiss(masm); 1487 GenerateMiss(masm);
1484 } 1488 }
1485 1489
1486 1490
1487 void StoreIC::GenerateMiss(MacroAssembler* masm) { 1491 void StoreIC::GenerateMiss(MacroAssembler* masm) {
1488 // ----------- S t a t e ------------- 1492 // ----------- S t a t e -------------
1489 // -- eax : value 1493 // -- eax : value
1490 // -- ecx : name 1494 // -- ecx : name
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1574 Label miss, restore_miss; 1578 Label miss, restore_miss;
1575 1579
1576 GenerateStringDictionaryReceiverCheck(masm, edx, ebx, edi, &miss); 1580 GenerateStringDictionaryReceiverCheck(masm, edx, ebx, edi, &miss);
1577 1581
1578 // A lot of registers are needed for storing to slow case 1582 // A lot of registers are needed for storing to slow case
1579 // objects. Push and restore receiver but rely on 1583 // objects. Push and restore receiver but rely on
1580 // GenerateDictionaryStore preserving the value and name. 1584 // GenerateDictionaryStore preserving the value and name.
1581 __ push(edx); 1585 __ push(edx);
1582 GenerateDictionaryStore(masm, &restore_miss, ebx, ecx, eax, edx, edi); 1586 GenerateDictionaryStore(masm, &restore_miss, ebx, ecx, eax, edx, edi);
1583 __ Drop(1); 1587 __ Drop(1);
1584 __ IncrementCounter(&Counters::store_normal_hit, 1); 1588 __ IncrementCounter(COUNTERS->store_normal_hit(), 1);
1585 __ ret(0); 1589 __ ret(0);
1586 1590
1587 __ bind(&restore_miss); 1591 __ bind(&restore_miss);
1588 __ pop(edx); 1592 __ pop(edx);
1589 1593
1590 __ bind(&miss); 1594 __ bind(&miss);
1591 __ IncrementCounter(&Counters::store_normal_miss, 1); 1595 __ IncrementCounter(COUNTERS->store_normal_miss(), 1);
1592 GenerateMiss(masm); 1596 GenerateMiss(masm);
1593 } 1597 }
1594 1598
1595 1599
1596 void StoreIC::GenerateGlobalProxy(MacroAssembler* masm, 1600 void StoreIC::GenerateGlobalProxy(MacroAssembler* masm,
1597 StrictModeFlag strict_mode) { 1601 StrictModeFlag strict_mode) {
1598 // ----------- S t a t e ------------- 1602 // ----------- S t a t e -------------
1599 // -- eax : value 1603 // -- eax : value
1600 // -- ecx : name 1604 // -- ecx : name
1601 // -- edx : receiver 1605 // -- edx : receiver
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1752 Condition cc = *jmp_address == Assembler::kJncShortOpcode 1756 Condition cc = *jmp_address == Assembler::kJncShortOpcode
1753 ? not_zero 1757 ? not_zero
1754 : zero; 1758 : zero;
1755 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); 1759 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
1756 } 1760 }
1757 1761
1758 1762
1759 } } // namespace v8::internal 1763 } } // namespace v8::internal
1760 1764
1761 #endif // V8_TARGET_ARCH_IA32 1765 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698