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

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

Issue 6685088: Merge isolates to bleeding_edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 9 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
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | src/ia32/lithium-gap-resolver-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 18 matching lines...) Expand all
854 // ----------------------------------- 854 // -----------------------------------
855 Label number, non_number, non_string, boolean, probe, miss; 855 Label number, non_number, non_string, boolean, probe, miss;
856 856
857 // Probe the stub cache. 857 // Probe the stub cache.
858 Code::Flags flags = Code::ComputeFlags(kind, 858 Code::Flags flags = Code::ComputeFlags(kind,
859 NOT_IN_LOOP, 859 NOT_IN_LOOP,
860 MONOMORPHIC, 860 MONOMORPHIC,
861 Code::kNoExtraICState, 861 Code::kNoExtraICState,
862 NORMAL, 862 NORMAL,
863 argc); 863 argc);
864 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, eax); 864 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx,
865 eax);
865 866
866 // If the stub cache probing failed, the receiver might be a value. 867 // If the stub cache probing failed, the receiver might be a value.
867 // For value objects, we use the map of the prototype objects for 868 // For value objects, we use the map of the prototype objects for
868 // the corresponding JSValue for the cache and that is what we need 869 // the corresponding JSValue for the cache and that is what we need
869 // to probe. 870 // to probe.
870 // 871 //
871 // Check for number. 872 // Check for number.
872 __ test(edx, Immediate(kSmiTagMask)); 873 __ test(edx, Immediate(kSmiTagMask));
873 __ j(zero, &number, not_taken); 874 __ j(zero, &number, not_taken);
874 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx); 875 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx);
875 __ j(not_equal, &non_number, taken); 876 __ j(not_equal, &non_number, taken);
876 __ bind(&number); 877 __ bind(&number);
877 StubCompiler::GenerateLoadGlobalFunctionPrototype( 878 StubCompiler::GenerateLoadGlobalFunctionPrototype(
878 masm, Context::NUMBER_FUNCTION_INDEX, edx); 879 masm, Context::NUMBER_FUNCTION_INDEX, edx);
879 __ jmp(&probe); 880 __ jmp(&probe);
880 881
881 // Check for string. 882 // Check for string.
882 __ bind(&non_number); 883 __ bind(&non_number);
883 __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE); 884 __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE);
884 __ j(above_equal, &non_string, taken); 885 __ j(above_equal, &non_string, taken);
885 StubCompiler::GenerateLoadGlobalFunctionPrototype( 886 StubCompiler::GenerateLoadGlobalFunctionPrototype(
886 masm, Context::STRING_FUNCTION_INDEX, edx); 887 masm, Context::STRING_FUNCTION_INDEX, edx);
887 __ jmp(&probe); 888 __ jmp(&probe);
888 889
889 // Check for boolean. 890 // Check for boolean.
890 __ bind(&non_string); 891 __ bind(&non_string);
891 __ cmp(edx, Factory::true_value()); 892 __ cmp(edx, FACTORY->true_value());
892 __ j(equal, &boolean, not_taken); 893 __ j(equal, &boolean, not_taken);
893 __ cmp(edx, Factory::false_value()); 894 __ cmp(edx, FACTORY->false_value());
894 __ j(not_equal, &miss, taken); 895 __ j(not_equal, &miss, taken);
895 __ bind(&boolean); 896 __ bind(&boolean);
896 StubCompiler::GenerateLoadGlobalFunctionPrototype( 897 StubCompiler::GenerateLoadGlobalFunctionPrototype(
897 masm, Context::BOOLEAN_FUNCTION_INDEX, edx); 898 masm, Context::BOOLEAN_FUNCTION_INDEX, edx);
898 899
899 // Probe the stub cache for the value object. 900 // Probe the stub cache for the value object.
900 __ bind(&probe); 901 __ bind(&probe);
901 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); 902 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx,
903 no_reg);
902 __ bind(&miss); 904 __ bind(&miss);
903 } 905 }
904 906
905 907
906 static void GenerateFunctionTailCall(MacroAssembler* masm, 908 static void GenerateFunctionTailCall(MacroAssembler* masm,
907 int argc, 909 int argc,
908 Label* miss) { 910 Label* miss) {
909 // ----------- S t a t e ------------- 911 // ----------- S t a t e -------------
910 // -- ecx : name 912 // -- ecx : name
911 // -- edi : function 913 // -- edi : function
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
958 IC::UtilityId id) { 960 IC::UtilityId id) {
959 // ----------- S t a t e ------------- 961 // ----------- S t a t e -------------
960 // -- ecx : name 962 // -- ecx : name
961 // -- esp[0] : return address 963 // -- esp[0] : return address
962 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 964 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
963 // -- ... 965 // -- ...
964 // -- esp[(argc + 1) * 4] : receiver 966 // -- esp[(argc + 1) * 4] : receiver
965 // ----------------------------------- 967 // -----------------------------------
966 968
967 if (id == IC::kCallIC_Miss) { 969 if (id == IC::kCallIC_Miss) {
968 __ IncrementCounter(&Counters::call_miss, 1); 970 __ IncrementCounter(COUNTERS->call_miss(), 1);
969 } else { 971 } else {
970 __ IncrementCounter(&Counters::keyed_call_miss, 1); 972 __ IncrementCounter(COUNTERS->keyed_call_miss(), 1);
971 } 973 }
972 974
973 // Get the receiver of the function from the stack; 1 ~ return address. 975 // Get the receiver of the function from the stack; 1 ~ return address.
974 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 976 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
975 977
976 // Enter an internal frame. 978 // Enter an internal frame.
977 __ EnterInternalFrame(); 979 __ EnterInternalFrame();
978 980
979 // Push the receiver and the name of the function. 981 // Push the receiver and the name of the function.
980 __ push(edx); 982 __ push(edx);
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1082 1084
1083 __ bind(&index_smi); 1085 __ bind(&index_smi);
1084 // Now the key is known to be a smi. This place is also jumped to from 1086 // Now the key is known to be a smi. This place is also jumped to from
1085 // where a numeric string is converted to a smi. 1087 // where a numeric string is converted to a smi.
1086 1088
1087 GenerateKeyedLoadReceiverCheck( 1089 GenerateKeyedLoadReceiverCheck(
1088 masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call); 1090 masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call);
1089 1091
1090 GenerateFastArrayLoad( 1092 GenerateFastArrayLoad(
1091 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load); 1093 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load);
1092 __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1); 1094 __ IncrementCounter(COUNTERS->keyed_call_generic_smi_fast(), 1);
1093 1095
1094 __ bind(&do_call); 1096 __ bind(&do_call);
1095 // receiver in edx is not used after this point. 1097 // receiver in edx is not used after this point.
1096 // ecx: key 1098 // ecx: key
1097 // edi: function 1099 // edi: function
1098 GenerateFunctionTailCall(masm, argc, &slow_call); 1100 GenerateFunctionTailCall(masm, argc, &slow_call);
1099 1101
1100 __ bind(&check_number_dictionary); 1102 __ bind(&check_number_dictionary);
1101 // eax: elements 1103 // eax: elements
1102 // ecx: smi key 1104 // ecx: smi key
1103 // Check whether the elements is a number dictionary. 1105 // Check whether the elements is a number dictionary.
1104 __ CheckMap(eax, Factory::hash_table_map(), &slow_load, true); 1106 __ CheckMap(eax, FACTORY->hash_table_map(), &slow_load, true);
1105 __ mov(ebx, ecx); 1107 __ mov(ebx, ecx);
1106 __ SmiUntag(ebx); 1108 __ SmiUntag(ebx);
1107 // ebx: untagged index 1109 // ebx: untagged index
1108 // Receiver in edx will be clobbered, need to reload it on miss. 1110 // Receiver in edx will be clobbered, need to reload it on miss.
1109 GenerateNumberDictionaryLoad( 1111 GenerateNumberDictionaryLoad(
1110 masm, &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi); 1112 masm, &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi);
1111 __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1); 1113 __ IncrementCounter(COUNTERS->keyed_call_generic_smi_dict(), 1);
1112 __ jmp(&do_call); 1114 __ jmp(&do_call);
1113 1115
1114 __ bind(&slow_reload_receiver); 1116 __ bind(&slow_reload_receiver);
1115 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1117 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1116 1118
1117 __ bind(&slow_load); 1119 __ bind(&slow_load);
1118 // This branch is taken when calling KeyedCallIC_Miss is neither required 1120 // This branch is taken when calling KeyedCallIC_Miss is neither required
1119 // nor beneficial. 1121 // nor beneficial.
1120 __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1); 1122 __ IncrementCounter(COUNTERS->keyed_call_generic_slow_load(), 1);
1121 __ EnterInternalFrame(); 1123 __ EnterInternalFrame();
1122 __ push(ecx); // save the key 1124 __ push(ecx); // save the key
1123 __ push(edx); // pass the receiver 1125 __ push(edx); // pass the receiver
1124 __ push(ecx); // pass the key 1126 __ push(ecx); // pass the key
1125 __ CallRuntime(Runtime::kKeyedGetProperty, 2); 1127 __ CallRuntime(Runtime::kKeyedGetProperty, 2);
1126 __ pop(ecx); // restore the key 1128 __ pop(ecx); // restore the key
1127 __ LeaveInternalFrame(); 1129 __ LeaveInternalFrame();
1128 __ mov(edi, eax); 1130 __ mov(edi, eax);
1129 __ jmp(&do_call); 1131 __ jmp(&do_call);
1130 1132
1131 __ bind(&check_string); 1133 __ bind(&check_string);
1132 GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow_call); 1134 GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow_call);
1133 1135
1134 // The key is known to be a symbol. 1136 // The key is known to be a symbol.
1135 // If the receiver is a regular JS object with slow properties then do 1137 // If the receiver is a regular JS object with slow properties then do
1136 // a quick inline probe of the receiver's dictionary. 1138 // a quick inline probe of the receiver's dictionary.
1137 // Otherwise do the monomorphic cache probe. 1139 // Otherwise do the monomorphic cache probe.
1138 GenerateKeyedLoadReceiverCheck( 1140 GenerateKeyedLoadReceiverCheck(
1139 masm, edx, eax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache); 1141 masm, edx, eax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache);
1140 1142
1141 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); 1143 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
1142 __ CheckMap(ebx, Factory::hash_table_map(), &lookup_monomorphic_cache, true); 1144 __ CheckMap(ebx, FACTORY->hash_table_map(), &lookup_monomorphic_cache, true);
1143 1145
1144 GenerateDictionaryLoad(masm, &slow_load, ebx, ecx, eax, edi, edi); 1146 GenerateDictionaryLoad(masm, &slow_load, ebx, ecx, eax, edi, edi);
1145 __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1); 1147 __ IncrementCounter(COUNTERS->keyed_call_generic_lookup_dict(), 1);
1146 __ jmp(&do_call); 1148 __ jmp(&do_call);
1147 1149
1148 __ bind(&lookup_monomorphic_cache); 1150 __ bind(&lookup_monomorphic_cache);
1149 __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1); 1151 __ IncrementCounter(COUNTERS->keyed_call_generic_lookup_cache(), 1);
1150 GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC); 1152 GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC);
1151 // Fall through on miss. 1153 // Fall through on miss.
1152 1154
1153 __ bind(&slow_call); 1155 __ bind(&slow_call);
1154 // This branch is taken if: 1156 // This branch is taken if:
1155 // - the receiver requires boxing or access check, 1157 // - the receiver requires boxing or access check,
1156 // - the key is neither smi nor symbol, 1158 // - the key is neither smi nor symbol,
1157 // - the value loaded is not a function, 1159 // - the value loaded is not a function,
1158 // - there is hope that the runtime will create a monomorphic call stub 1160 // - there is hope that the runtime will create a monomorphic call stub
1159 // that will get fetched next time. 1161 // that will get fetched next time.
1160 __ IncrementCounter(&Counters::keyed_call_generic_slow, 1); 1162 __ IncrementCounter(COUNTERS->keyed_call_generic_slow(), 1);
1161 GenerateMiss(masm, argc); 1163 GenerateMiss(masm, argc);
1162 1164
1163 __ bind(&index_string); 1165 __ bind(&index_string);
1164 __ IndexFromHash(ebx, ecx); 1166 __ IndexFromHash(ebx, ecx);
1165 // Now jump to the place where smi keys are handled. 1167 // Now jump to the place where smi keys are handled.
1166 __ jmp(&index_smi); 1168 __ jmp(&index_smi);
1167 } 1169 }
1168 1170
1169 1171
1170 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { 1172 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1205 // ----------- S t a t e ------------- 1207 // ----------- S t a t e -------------
1206 // -- eax : receiver 1208 // -- eax : receiver
1207 // -- ecx : name 1209 // -- ecx : name
1208 // -- esp[0] : return address 1210 // -- esp[0] : return address
1209 // ----------------------------------- 1211 // -----------------------------------
1210 1212
1211 // Probe the stub cache. 1213 // Probe the stub cache.
1212 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, 1214 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
1213 NOT_IN_LOOP, 1215 NOT_IN_LOOP,
1214 MONOMORPHIC); 1216 MONOMORPHIC);
1215 StubCache::GenerateProbe(masm, flags, eax, ecx, ebx, edx); 1217 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, eax, ecx, ebx,
1218 edx);
1216 1219
1217 // Cache miss: Jump to runtime. 1220 // Cache miss: Jump to runtime.
1218 GenerateMiss(masm); 1221 GenerateMiss(masm);
1219 } 1222 }
1220 1223
1221 1224
1222 void LoadIC::GenerateNormal(MacroAssembler* masm) { 1225 void LoadIC::GenerateNormal(MacroAssembler* masm) {
1223 // ----------- S t a t e ------------- 1226 // ----------- S t a t e -------------
1224 // -- eax : receiver 1227 // -- eax : receiver
1225 // -- ecx : name 1228 // -- ecx : name
(...skipping 14 matching lines...) Expand all
1240 } 1243 }
1241 1244
1242 1245
1243 void LoadIC::GenerateMiss(MacroAssembler* masm) { 1246 void LoadIC::GenerateMiss(MacroAssembler* masm) {
1244 // ----------- S t a t e ------------- 1247 // ----------- S t a t e -------------
1245 // -- eax : receiver 1248 // -- eax : receiver
1246 // -- ecx : name 1249 // -- ecx : name
1247 // -- esp[0] : return address 1250 // -- esp[0] : return address
1248 // ----------------------------------- 1251 // -----------------------------------
1249 1252
1250 __ IncrementCounter(&Counters::load_miss, 1); 1253 __ IncrementCounter(COUNTERS->load_miss(), 1);
1251 1254
1252 __ pop(ebx); 1255 __ pop(ebx);
1253 __ push(eax); // receiver 1256 __ push(eax); // receiver
1254 __ push(ecx); // name 1257 __ push(ecx); // name
1255 __ push(ebx); // return address 1258 __ push(ebx); // return address
1256 1259
1257 // Perform tail call to the entry. 1260 // Perform tail call to the entry.
1258 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); 1261 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss));
1259 __ TailCallExternalReference(ref, 2, 1); 1262 __ TailCallExternalReference(ref, 2, 1);
1260 } 1263 }
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1368 *(reinterpret_cast<Object**>(map_address)) = map; 1371 *(reinterpret_cast<Object**>(map_address)) = map;
1369 1372
1370 // Patch the offset in the store instruction. The offset is in the 1373 // Patch the offset in the store instruction. The offset is in the
1371 // last 4 bytes of a six byte register-to-memory move instruction. 1374 // last 4 bytes of a six byte register-to-memory move instruction.
1372 Address offset_address = 1375 Address offset_address =
1373 map_check_address + StoreIC::kOffsetToStoreInstruction + 2; 1376 map_check_address + StoreIC::kOffsetToStoreInstruction + 2;
1374 // The offset should have initial value (kMaxInt - 1), cleared value 1377 // The offset should have initial value (kMaxInt - 1), cleared value
1375 // (-1) or we should be clearing the inlined version. 1378 // (-1) or we should be clearing the inlined version.
1376 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt - 1 || 1379 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt - 1 ||
1377 *reinterpret_cast<int*>(offset_address) == -1 || 1380 *reinterpret_cast<int*>(offset_address) == -1 ||
1378 (offset == 0 && map == Heap::null_value())); 1381 (offset == 0 && map == HEAP->null_value()));
1379 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; 1382 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag;
1380 1383
1381 // Patch the offset in the write-barrier code. The offset is the 1384 // Patch the offset in the write-barrier code. The offset is the
1382 // last 4 bytes of a six byte lea instruction. 1385 // last 4 bytes of a six byte lea instruction.
1383 offset_address = map_check_address + delta_to_record_write + 2; 1386 offset_address = map_check_address + delta_to_record_write + 2;
1384 // The offset should have initial value (kMaxInt), cleared value 1387 // The offset should have initial value (kMaxInt), cleared value
1385 // (-1) or we should be clearing the inlined version. 1388 // (-1) or we should be clearing the inlined version.
1386 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt || 1389 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt ||
1387 *reinterpret_cast<int*>(offset_address) == -1 || 1390 *reinterpret_cast<int*>(offset_address) == -1 ||
1388 (offset == 0 && map == Heap::null_value())); 1391 (offset == 0 && map == HEAP->null_value()));
1389 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; 1392 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag;
1390 1393
1391 return true; 1394 return true;
1392 } 1395 }
1393 1396
1394 1397
1395 static bool PatchInlinedMapCheck(Address address, Object* map) { 1398 static bool PatchInlinedMapCheck(Address address, Object* map) {
1396 if (V8::UseCrankshaft()) return false; 1399 if (V8::UseCrankshaft()) return false;
1397 1400
1398 Address test_instruction_address = 1401 Address test_instruction_address =
(...skipping 27 matching lines...) Expand all
1426 } 1429 }
1427 1430
1428 1431
1429 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 1432 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
1430 // ----------- S t a t e ------------- 1433 // ----------- S t a t e -------------
1431 // -- eax : key 1434 // -- eax : key
1432 // -- edx : receiver 1435 // -- edx : receiver
1433 // -- esp[0] : return address 1436 // -- esp[0] : return address
1434 // ----------------------------------- 1437 // -----------------------------------
1435 1438
1436 __ IncrementCounter(&Counters::keyed_load_miss, 1); 1439 __ IncrementCounter(COUNTERS->keyed_load_miss(), 1);
1437 1440
1438 __ pop(ebx); 1441 __ pop(ebx);
1439 __ push(edx); // receiver 1442 __ push(edx); // receiver
1440 __ push(eax); // name 1443 __ push(eax); // name
1441 __ push(ebx); // return address 1444 __ push(ebx); // return address
1442 1445
1443 // Perform tail call to the entry. 1446 // Perform tail call to the entry.
1444 ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss)); 1447 ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss));
1445 __ TailCallExternalReference(ref, 2, 1); 1448 __ TailCallExternalReference(ref, 2, 1);
1446 } 1449 }
(...skipping 22 matching lines...) Expand all
1469 // -- eax : value 1472 // -- eax : value
1470 // -- ecx : name 1473 // -- ecx : name
1471 // -- edx : receiver 1474 // -- edx : receiver
1472 // -- esp[0] : return address 1475 // -- esp[0] : return address
1473 // ----------------------------------- 1476 // -----------------------------------
1474 1477
1475 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, 1478 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
1476 NOT_IN_LOOP, 1479 NOT_IN_LOOP,
1477 MONOMORPHIC, 1480 MONOMORPHIC,
1478 strict_mode); 1481 strict_mode);
1479 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); 1482 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx,
1483 no_reg);
1480 1484
1481 // Cache miss: Jump to runtime. 1485 // Cache miss: Jump to runtime.
1482 GenerateMiss(masm); 1486 GenerateMiss(masm);
1483 } 1487 }
1484 1488
1485 1489
1486 void StoreIC::GenerateMiss(MacroAssembler* masm) { 1490 void StoreIC::GenerateMiss(MacroAssembler* masm) {
1487 // ----------- S t a t e ------------- 1491 // ----------- S t a t e -------------
1488 // -- eax : value 1492 // -- eax : value
1489 // -- ecx : name 1493 // -- ecx : name
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1573 Label miss, restore_miss; 1577 Label miss, restore_miss;
1574 1578
1575 GenerateStringDictionaryReceiverCheck(masm, edx, ebx, edi, &miss); 1579 GenerateStringDictionaryReceiverCheck(masm, edx, ebx, edi, &miss);
1576 1580
1577 // A lot of registers are needed for storing to slow case 1581 // A lot of registers are needed for storing to slow case
1578 // objects. Push and restore receiver but rely on 1582 // objects. Push and restore receiver but rely on
1579 // GenerateDictionaryStore preserving the value and name. 1583 // GenerateDictionaryStore preserving the value and name.
1580 __ push(edx); 1584 __ push(edx);
1581 GenerateDictionaryStore(masm, &restore_miss, ebx, ecx, eax, edx, edi); 1585 GenerateDictionaryStore(masm, &restore_miss, ebx, ecx, eax, edx, edi);
1582 __ Drop(1); 1586 __ Drop(1);
1583 __ IncrementCounter(&Counters::store_normal_hit, 1); 1587 __ IncrementCounter(COUNTERS->store_normal_hit(), 1);
1584 __ ret(0); 1588 __ ret(0);
1585 1589
1586 __ bind(&restore_miss); 1590 __ bind(&restore_miss);
1587 __ pop(edx); 1591 __ pop(edx);
1588 1592
1589 __ bind(&miss); 1593 __ bind(&miss);
1590 __ IncrementCounter(&Counters::store_normal_miss, 1); 1594 __ IncrementCounter(COUNTERS->store_normal_miss(), 1);
1591 GenerateMiss(masm); 1595 GenerateMiss(masm);
1592 } 1596 }
1593 1597
1594 1598
1595 void StoreIC::GenerateGlobalProxy(MacroAssembler* masm, 1599 void StoreIC::GenerateGlobalProxy(MacroAssembler* masm,
1596 StrictModeFlag strict_mode) { 1600 StrictModeFlag strict_mode) {
1597 // ----------- S t a t e ------------- 1601 // ----------- S t a t e -------------
1598 // -- eax : value 1602 // -- eax : value
1599 // -- ecx : name 1603 // -- ecx : name
1600 // -- edx : receiver 1604 // -- edx : receiver
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1751 Condition cc = *jmp_address == Assembler::kJncShortOpcode 1755 Condition cc = *jmp_address == Assembler::kJncShortOpcode
1752 ? not_zero 1756 ? not_zero
1753 : zero; 1757 : zero;
1754 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); 1758 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
1755 } 1759 }
1756 1760
1757 1761
1758 } } // namespace v8::internal 1762 } } // namespace v8::internal
1759 1763
1760 #endif // V8_TARGET_ARCH_IA32 1764 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | src/ia32/lithium-gap-resolver-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698