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

Side by Side Diff: src/x64/stub-cache-x64.cc

Issue 2982001: Simplifying GenerateDictionaryNegativeLookup by making the 'extra' parameter ... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 5 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/stub-cache.h ('k') | no next file » | 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 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 // Helper function used to check that the dictionary doesn't contain 84 // Helper function used to check that the dictionary doesn't contain
85 // the property. This function may return false negatives, so miss_label 85 // the property. This function may return false negatives, so miss_label
86 // must always call a backup property check that is complete. 86 // must always call a backup property check that is complete.
87 // This function is safe to call if the receiver has fast properties. 87 // This function is safe to call if the receiver has fast properties.
88 // Name must be a symbol and receiver must be a heap object. 88 // Name must be a symbol and receiver must be a heap object.
89 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, 89 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
90 Label* miss_label, 90 Label* miss_label,
91 Register receiver, 91 Register receiver,
92 String* name, 92 String* name,
93 Register r0, 93 Register r0,
94 Register extra) { 94 Register r1) {
95 ASSERT(name->IsSymbol()); 95 ASSERT(name->IsSymbol());
96 __ IncrementCounter(&Counters::negative_lookups, 1); 96 __ IncrementCounter(&Counters::negative_lookups, 1);
97 __ IncrementCounter(&Counters::negative_lookups_miss, 1); 97 __ IncrementCounter(&Counters::negative_lookups_miss, 1);
98 98
99 Label done; 99 Label done;
100 __ movq(r0, FieldOperand(receiver, HeapObject::kMapOffset)); 100 __ movq(r0, FieldOperand(receiver, HeapObject::kMapOffset));
101 101
102 const int kInterceptorOrAccessCheckNeededMask = 102 const int kInterceptorOrAccessCheckNeededMask =
103 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 103 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
104 104
(...skipping 28 matching lines...) Expand all
133 StringDictionary::kElementsStartIndex * kPointerSize; 133 StringDictionary::kElementsStartIndex * kPointerSize;
134 134
135 // If names of slots in range from 1 to kProbes - 1 for the hash value are 135 // If names of slots in range from 1 to kProbes - 1 for the hash value are
136 // not equal to the name and kProbes-th slot is not used (its name is the 136 // not equal to the name and kProbes-th slot is not used (its name is the
137 // undefined value), it guarantees the hash table doesn't contain the 137 // undefined value), it guarantees the hash table doesn't contain the
138 // property. It's true even if some slots represent deleted properties 138 // property. It's true even if some slots represent deleted properties
139 // (their names are the null value). 139 // (their names are the null value).
140 for (int i = 0; i < kProbes; i++) { 140 for (int i = 0; i < kProbes; i++) {
141 // r0 points to properties hash. 141 // r0 points to properties hash.
142 // Compute the masked index: (hash + i + i * i) & mask. 142 // Compute the masked index: (hash + i + i * i) & mask.
143 if (extra.is(no_reg)) { 143 Register index = r1;
144 __ push(receiver);
145 }
146 Register index = extra.is(no_reg) ? receiver : extra;
147 // Capacity is smi 2^n. 144 // Capacity is smi 2^n.
148 __ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset)); 145 __ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset));
149 __ decl(index); 146 __ decl(index);
150 __ and_(index, 147 __ and_(index,
151 Immediate(name->Hash() + StringDictionary::GetProbeOffset(i))); 148 Immediate(name->Hash() + StringDictionary::GetProbeOffset(i)));
152 149
153 // Scale the index by multiplying by the entry size. 150 // Scale the index by multiplying by the entry size.
154 ASSERT(StringDictionary::kEntrySize == 3); 151 ASSERT(StringDictionary::kEntrySize == 3);
155 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3. 152 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3.
156 153
157 Register entity_name = extra.is(no_reg) ? properties : extra; 154 Register entity_name = r1;
158 // Having undefined at this place means the name is not contained. 155 // Having undefined at this place means the name is not contained.
159 ASSERT_EQ(kSmiTagSize, 1); 156 ASSERT_EQ(kSmiTagSize, 1);
160 __ movq(entity_name, Operand(properties, index, times_pointer_size, 157 __ movq(entity_name, Operand(properties, index, times_pointer_size,
161 kElementsStartOffset - kHeapObjectTag)); 158 kElementsStartOffset - kHeapObjectTag));
162 __ Cmp(entity_name, Factory::undefined_value()); 159 __ Cmp(entity_name, Factory::undefined_value());
163 if (extra.is(no_reg)) {
164 // 'receiver' shares a register with 'entity_name'.
165 __ pop(receiver);
166 }
167 // __ jmp(miss_label); 160 // __ jmp(miss_label);
168 if (i != kProbes - 1) { 161 if (i != kProbes - 1) {
169 __ j(equal, &done); 162 __ j(equal, &done);
170 163
171 // Stop if found the property. 164 // Stop if found the property.
172 __ Cmp(entity_name, Handle<String>(name)); 165 __ Cmp(entity_name, Handle<String>(name));
173 __ j(equal, miss_label); 166 __ j(equal, miss_label);
174
175 if (extra.is(no_reg)) {
176 // Restore the properties if their register was occupied by the name.
177 __ movq(properties,
178 FieldOperand(receiver, JSObject::kPropertiesOffset));
179 }
180 } else { 167 } else {
181 // Give up probing if still not found the undefined value. 168 // Give up probing if still not found the undefined value.
182 __ j(not_equal, miss_label); 169 __ j(not_equal, miss_label);
183 } 170 }
184 } 171 }
185 172
186 __ bind(&done); 173 __ bind(&done);
187 __ DecrementCounter(&Counters::negative_lookups_miss, 1); 174 __ DecrementCounter(&Counters::negative_lookups_miss, 1);
188 } 175 }
189 176
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 name_(name) {} 584 name_(name) {}
598 585
599 void Compile(MacroAssembler* masm, 586 void Compile(MacroAssembler* masm,
600 JSObject* object, 587 JSObject* object,
601 JSObject* holder, 588 JSObject* holder,
602 String* name, 589 String* name,
603 LookupResult* lookup, 590 LookupResult* lookup,
604 Register receiver, 591 Register receiver,
605 Register scratch1, 592 Register scratch1,
606 Register scratch2, 593 Register scratch2,
594 Register scratch3,
607 Label* miss) { 595 Label* miss) {
608 ASSERT(holder->HasNamedInterceptor()); 596 ASSERT(holder->HasNamedInterceptor());
609 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); 597 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
610 598
611 // Check that the receiver isn't a smi. 599 // Check that the receiver isn't a smi.
612 __ JumpIfSmi(receiver, miss); 600 __ JumpIfSmi(receiver, miss);
613 601
614 CallOptimization optimization(lookup); 602 CallOptimization optimization(lookup);
615 603
616 if (optimization.is_constant_call()) { 604 if (optimization.is_constant_call()) {
617 CompileCacheable(masm, 605 CompileCacheable(masm,
618 object, 606 object,
619 receiver, 607 receiver,
620 scratch1, 608 scratch1,
621 scratch2, 609 scratch2,
610 scratch3,
622 holder, 611 holder,
623 lookup, 612 lookup,
624 name, 613 name,
625 optimization, 614 optimization,
626 miss); 615 miss);
627 } else { 616 } else {
628 CompileRegular(masm, 617 CompileRegular(masm,
629 object, 618 object,
630 receiver, 619 receiver,
631 scratch1, 620 scratch1,
632 scratch2, 621 scratch2,
622 scratch3,
633 name, 623 name,
634 holder, 624 holder,
635 miss); 625 miss);
636 } 626 }
637 } 627 }
638 628
639 private: 629 private:
640 void CompileCacheable(MacroAssembler* masm, 630 void CompileCacheable(MacroAssembler* masm,
641 JSObject* object, 631 JSObject* object,
642 Register receiver, 632 Register receiver,
643 Register scratch1, 633 Register scratch1,
644 Register scratch2, 634 Register scratch2,
635 Register scratch3,
645 JSObject* interceptor_holder, 636 JSObject* interceptor_holder,
646 LookupResult* lookup, 637 LookupResult* lookup,
647 String* name, 638 String* name,
648 const CallOptimization& optimization, 639 const CallOptimization& optimization,
649 Label* miss_label) { 640 Label* miss_label) {
650 ASSERT(optimization.is_constant_call()); 641 ASSERT(optimization.is_constant_call());
651 ASSERT(!lookup->holder()->IsGlobalObject()); 642 ASSERT(!lookup->holder()->IsGlobalObject());
652 643
653 int depth1 = kInvalidProtoDepth; 644 int depth1 = kInvalidProtoDepth;
654 int depth2 = kInvalidProtoDepth; 645 int depth2 = kInvalidProtoDepth;
(...skipping 19 matching lines...) Expand all
674 ReserveSpaceForFastApiCall(masm, scratch1); 665 ReserveSpaceForFastApiCall(masm, scratch1);
675 } 666 }
676 667
677 // Check that the maps from receiver to interceptor's holder 668 // Check that the maps from receiver to interceptor's holder
678 // haven't changed and thus we can invoke interceptor. 669 // haven't changed and thus we can invoke interceptor.
679 Label miss_cleanup; 670 Label miss_cleanup;
680 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; 671 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
681 Register holder = 672 Register holder =
682 stub_compiler_->CheckPrototypes(object, receiver, 673 stub_compiler_->CheckPrototypes(object, receiver,
683 interceptor_holder, scratch1, 674 interceptor_holder, scratch1,
684 scratch2, name, depth1, miss); 675 scratch2, scratch3, name, depth1, miss);
685 676
686 // Invoke an interceptor and if it provides a value, 677 // Invoke an interceptor and if it provides a value,
687 // branch to |regular_invoke|. 678 // branch to |regular_invoke|.
688 Label regular_invoke; 679 Label regular_invoke;
689 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, 680 LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
690 &regular_invoke); 681 &regular_invoke);
691 682
692 // Interceptor returned nothing for this property. Try to use cached 683 // Interceptor returned nothing for this property. Try to use cached
693 // constant function. 684 // constant function.
694 685
695 // Check that the maps from interceptor's holder to constant function's 686 // Check that the maps from interceptor's holder to constant function's
696 // holder haven't changed and thus we can use cached constant function. 687 // holder haven't changed and thus we can use cached constant function.
697 if (interceptor_holder != lookup->holder()) { 688 if (interceptor_holder != lookup->holder()) {
698 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, 689 stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
699 lookup->holder(), scratch1, 690 lookup->holder(), scratch1,
700 scratch2, name, depth2, miss); 691 scratch2, scratch3, name, depth2, miss);
701 } else { 692 } else {
702 // CheckPrototypes has a side effect of fetching a 'holder' 693 // CheckPrototypes has a side effect of fetching a 'holder'
703 // for API (object which is instanceof for the signature). It's 694 // for API (object which is instanceof for the signature). It's
704 // safe to omit it here, as if present, it should be fetched 695 // safe to omit it here, as if present, it should be fetched
705 // by the previous CheckPrototypes. 696 // by the previous CheckPrototypes.
706 ASSERT(depth2 == kInvalidProtoDepth); 697 ASSERT(depth2 == kInvalidProtoDepth);
707 } 698 }
708 699
709 // Invoke function. 700 // Invoke function.
710 if (can_do_fast_api_call) { 701 if (can_do_fast_api_call) {
(...skipping 15 matching lines...) Expand all
726 if (can_do_fast_api_call) { 717 if (can_do_fast_api_call) {
727 FreeSpaceForFastApiCall(masm, scratch1); 718 FreeSpaceForFastApiCall(masm, scratch1);
728 } 719 }
729 } 720 }
730 721
731 void CompileRegular(MacroAssembler* masm, 722 void CompileRegular(MacroAssembler* masm,
732 JSObject* object, 723 JSObject* object,
733 Register receiver, 724 Register receiver,
734 Register scratch1, 725 Register scratch1,
735 Register scratch2, 726 Register scratch2,
727 Register scratch3,
736 String* name, 728 String* name,
737 JSObject* interceptor_holder, 729 JSObject* interceptor_holder,
738 Label* miss_label) { 730 Label* miss_label) {
739 Register holder = 731 Register holder =
740 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, 732 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
741 scratch1, scratch2, name, 733 scratch1, scratch2, scratch3, name,
742 miss_label); 734 miss_label);
743 735
744 __ EnterInternalFrame(); 736 __ EnterInternalFrame();
745 // Save the name_ register across the call. 737 // Save the name_ register across the call.
746 __ push(name_); 738 __ push(name_);
747 739
748 PushInterceptorArguments(masm, 740 PushInterceptorArguments(masm,
749 receiver, 741 receiver,
750 holder, 742 holder,
751 name_, 743 name_,
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 JSObject::cast(object), holder); 876 JSObject::cast(object), holder);
885 } 877 }
886 878
887 if (depth != kInvalidProtoDepth) { 879 if (depth != kInvalidProtoDepth) {
888 __ IncrementCounter(&Counters::call_const_fast_api, 1); 880 __ IncrementCounter(&Counters::call_const_fast_api, 1);
889 ReserveSpaceForFastApiCall(masm(), rax); 881 ReserveSpaceForFastApiCall(masm(), rax);
890 } 882 }
891 883
892 // Check that the maps haven't changed. 884 // Check that the maps haven't changed.
893 CheckPrototypes(JSObject::cast(object), rdx, holder, 885 CheckPrototypes(JSObject::cast(object), rdx, holder,
894 rbx, rax, name, depth, &miss, rdi); 886 rbx, rax, rdi, name, depth, &miss);
895 887
896 // Patch the receiver on the stack with the global proxy if 888 // Patch the receiver on the stack with the global proxy if
897 // necessary. 889 // necessary.
898 if (object->IsGlobalObject()) { 890 if (object->IsGlobalObject()) {
899 ASSERT(depth == kInvalidProtoDepth); 891 ASSERT(depth == kInvalidProtoDepth);
900 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 892 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
901 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 893 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
902 } 894 }
903 break; 895 break;
904 896
905 case STRING_CHECK: 897 case STRING_CHECK:
906 if (!function->IsBuiltin()) { 898 if (!function->IsBuiltin()) {
907 // Calling non-builtins with a value as receiver requires boxing. 899 // Calling non-builtins with a value as receiver requires boxing.
908 __ jmp(&miss); 900 __ jmp(&miss);
909 } else { 901 } else {
910 // Check that the object is a two-byte string or a symbol. 902 // Check that the object is a two-byte string or a symbol.
911 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax); 903 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax);
912 __ j(above_equal, &miss); 904 __ j(above_equal, &miss);
913 // Check that the maps starting from the prototype haven't changed. 905 // Check that the maps starting from the prototype haven't changed.
914 GenerateDirectLoadGlobalFunctionPrototype( 906 GenerateDirectLoadGlobalFunctionPrototype(
915 masm(), Context::STRING_FUNCTION_INDEX, rax); 907 masm(), Context::STRING_FUNCTION_INDEX, rax);
916 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, 908 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
917 rbx, rdx, name, &miss, rdi); 909 rbx, rdx, rdi, name, &miss);
918 } 910 }
919 break; 911 break;
920 912
921 case NUMBER_CHECK: { 913 case NUMBER_CHECK: {
922 if (!function->IsBuiltin()) { 914 if (!function->IsBuiltin()) {
923 // Calling non-builtins with a value as receiver requires boxing. 915 // Calling non-builtins with a value as receiver requires boxing.
924 __ jmp(&miss); 916 __ jmp(&miss);
925 } else { 917 } else {
926 Label fast; 918 Label fast;
927 // Check that the object is a smi or a heap number. 919 // Check that the object is a smi or a heap number.
928 __ JumpIfSmi(rdx, &fast); 920 __ JumpIfSmi(rdx, &fast);
929 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax); 921 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax);
930 __ j(not_equal, &miss); 922 __ j(not_equal, &miss);
931 __ bind(&fast); 923 __ bind(&fast);
932 // Check that the maps starting from the prototype haven't changed. 924 // Check that the maps starting from the prototype haven't changed.
933 GenerateDirectLoadGlobalFunctionPrototype( 925 GenerateDirectLoadGlobalFunctionPrototype(
934 masm(), Context::NUMBER_FUNCTION_INDEX, rax); 926 masm(), Context::NUMBER_FUNCTION_INDEX, rax);
935 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, 927 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
936 rbx, rdx, name, &miss, rdi); 928 rbx, rdx, rdi, name, &miss);
937 } 929 }
938 break; 930 break;
939 } 931 }
940 932
941 case BOOLEAN_CHECK: { 933 case BOOLEAN_CHECK: {
942 if (!function->IsBuiltin()) { 934 if (!function->IsBuiltin()) {
943 // Calling non-builtins with a value as receiver requires boxing. 935 // Calling non-builtins with a value as receiver requires boxing.
944 __ jmp(&miss); 936 __ jmp(&miss);
945 } else { 937 } else {
946 Label fast; 938 Label fast;
947 // Check that the object is a boolean. 939 // Check that the object is a boolean.
948 __ CompareRoot(rdx, Heap::kTrueValueRootIndex); 940 __ CompareRoot(rdx, Heap::kTrueValueRootIndex);
949 __ j(equal, &fast); 941 __ j(equal, &fast);
950 __ CompareRoot(rdx, Heap::kFalseValueRootIndex); 942 __ CompareRoot(rdx, Heap::kFalseValueRootIndex);
951 __ j(not_equal, &miss); 943 __ j(not_equal, &miss);
952 __ bind(&fast); 944 __ bind(&fast);
953 // Check that the maps starting from the prototype haven't changed. 945 // Check that the maps starting from the prototype haven't changed.
954 GenerateDirectLoadGlobalFunctionPrototype( 946 GenerateDirectLoadGlobalFunctionPrototype(
955 masm(), Context::BOOLEAN_FUNCTION_INDEX, rax); 947 masm(), Context::BOOLEAN_FUNCTION_INDEX, rax);
956 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, 948 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
957 rbx, rdx, name, &miss, rdi); 949 rbx, rdx, rdi, name, &miss);
958 } 950 }
959 break; 951 break;
960 } 952 }
961 953
962 default: 954 default:
963 UNREACHABLE(); 955 UNREACHABLE();
964 } 956 }
965 957
966 if (depth != kInvalidProtoDepth) { 958 if (depth != kInvalidProtoDepth) {
967 GenerateFastApiCall(masm(), optimization, argc); 959 GenerateFastApiCall(masm(), optimization, argc);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1002 GenerateNameCheck(name, &miss); 994 GenerateNameCheck(name, &miss);
1003 995
1004 // Get the receiver from the stack. 996 // Get the receiver from the stack.
1005 const int argc = arguments().immediate(); 997 const int argc = arguments().immediate();
1006 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 998 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1007 999
1008 // Check that the receiver isn't a smi. 1000 // Check that the receiver isn't a smi.
1009 __ JumpIfSmi(rdx, &miss); 1001 __ JumpIfSmi(rdx, &miss);
1010 1002
1011 // Do the right check and compute the holder register. 1003 // Do the right check and compute the holder register.
1012 Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, 1004 Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, rdi,
1013 name, &miss, rdi); 1005 name, &miss);
1014 1006
1015 GenerateFastPropertyLoad(masm(), rdi, reg, holder, index); 1007 GenerateFastPropertyLoad(masm(), rdi, reg, holder, index);
1016 1008
1017 // Check that the function really is a function. 1009 // Check that the function really is a function.
1018 __ JumpIfSmi(rdi, &miss); 1010 __ JumpIfSmi(rdi, &miss);
1019 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); 1011 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx);
1020 __ j(not_equal, &miss); 1012 __ j(not_equal, &miss);
1021 1013
1022 // Patch the receiver on the stack with the global proxy if 1014 // Patch the receiver on the stack with the global proxy if
1023 // necessary. 1015 // necessary.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1066 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1058 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1067 1059
1068 // Check that the receiver isn't a smi. 1060 // Check that the receiver isn't a smi.
1069 __ JumpIfSmi(rdx, &miss); 1061 __ JumpIfSmi(rdx, &miss);
1070 1062
1071 CheckPrototypes(JSObject::cast(object), 1063 CheckPrototypes(JSObject::cast(object),
1072 rdx, 1064 rdx,
1073 holder, 1065 holder,
1074 rbx, 1066 rbx,
1075 rax, 1067 rax,
1068 rdi,
1076 name, 1069 name,
1077 &miss, 1070 &miss);
1078 rdi);
1079 1071
1080 if (argc == 0) { 1072 if (argc == 0) {
1081 // Noop, return the length. 1073 // Noop, return the length.
1082 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); 1074 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset));
1083 __ ret((argc + 1) * kPointerSize); 1075 __ ret((argc + 1) * kPointerSize);
1084 } else { 1076 } else {
1085 // Get the elements array of the object. 1077 // Get the elements array of the object.
1086 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); 1078 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
1087 1079
1088 // Check that the elements are in fast mode (not dictionary). 1080 // Check that the elements are in fast mode (not dictionary).
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
1221 1213
1222 // Get the receiver from the stack. 1214 // Get the receiver from the stack.
1223 const int argc = arguments().immediate(); 1215 const int argc = arguments().immediate();
1224 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1216 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1225 1217
1226 // Check that the receiver isn't a smi. 1218 // Check that the receiver isn't a smi.
1227 __ JumpIfSmi(rdx, &miss); 1219 __ JumpIfSmi(rdx, &miss);
1228 1220
1229 CheckPrototypes(JSObject::cast(object), rdx, 1221 CheckPrototypes(JSObject::cast(object), rdx,
1230 holder, rbx, 1222 holder, rbx,
1231 rax, name, &miss, rdi); 1223 rax, rdi, name, &miss);
1232 1224
1233 // Get the elements array of the object. 1225 // Get the elements array of the object.
1234 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); 1226 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
1235 1227
1236 // Check that the elements are in fast mode (not dictionary). 1228 // Check that the elements are in fast mode (not dictionary).
1237 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), Factory::fixed_array_map()); 1229 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), Factory::fixed_array_map());
1238 __ j(not_equal, &miss); 1230 __ j(not_equal, &miss);
1239 1231
1240 // Get the array's length into rcx and calculate new length. 1232 // Get the array's length into rcx and calculate new length.
1241 __ SmiToInteger32(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); 1233 __ SmiToInteger32(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1328 1320
1329 CallInterceptorCompiler compiler(this, arguments(), rcx); 1321 CallInterceptorCompiler compiler(this, arguments(), rcx);
1330 compiler.Compile(masm(), 1322 compiler.Compile(masm(),
1331 object, 1323 object,
1332 holder, 1324 holder,
1333 name, 1325 name,
1334 &lookup, 1326 &lookup,
1335 rdx, 1327 rdx,
1336 rbx, 1328 rbx,
1337 rdi, 1329 rdi,
1330 rax,
1338 &miss); 1331 &miss);
1339 1332
1340 // Restore receiver. 1333 // Restore receiver.
1341 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1334 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1342 1335
1343 // Check that the function really is a function. 1336 // Check that the function really is a function.
1344 __ JumpIfSmi(rax, &miss); 1337 __ JumpIfSmi(rax, &miss);
1345 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 1338 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
1346 __ j(not_equal, &miss); 1339 __ j(not_equal, &miss);
1347 1340
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1390 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1383 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1391 1384
1392 // If the object is the holder then we know that it's a global 1385 // If the object is the holder then we know that it's a global
1393 // object which can only happen for contextual calls. In this case, 1386 // object which can only happen for contextual calls. In this case,
1394 // the receiver cannot be a smi. 1387 // the receiver cannot be a smi.
1395 if (object != holder) { 1388 if (object != holder) {
1396 __ JumpIfSmi(rdx, &miss); 1389 __ JumpIfSmi(rdx, &miss);
1397 } 1390 }
1398 1391
1399 // Check that the maps haven't changed. 1392 // Check that the maps haven't changed.
1400 CheckPrototypes(object, rdx, holder, rbx, rax, name, &miss, rdi); 1393 CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, &miss);
1401 1394
1402 // Get the value from the cell. 1395 // Get the value from the cell.
1403 __ Move(rdi, Handle<JSGlobalPropertyCell>(cell)); 1396 __ Move(rdi, Handle<JSGlobalPropertyCell>(cell));
1404 __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset)); 1397 __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset));
1405 1398
1406 // Check that the cell contains the same function. 1399 // Check that the cell contains the same function.
1407 if (Heap::InNewSpace(function)) { 1400 if (Heap::InNewSpace(function)) {
1408 // We can't embed a pointer to a function in new space so we have 1401 // We can't embed a pointer to a function in new space so we have
1409 // to verify that the shared function info is unchanged. This has 1402 // to verify that the shared function info is unchanged. This has
1410 // the nice side effect that multiple closures based on the same 1403 // the nice side effect that multiple closures based on the same
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1455 JSObject* holder, 1448 JSObject* holder,
1456 AccessorInfo* callback) { 1449 AccessorInfo* callback) {
1457 // ----------- S t a t e ------------- 1450 // ----------- S t a t e -------------
1458 // -- rax : receiver 1451 // -- rax : receiver
1459 // -- rcx : name 1452 // -- rcx : name
1460 // -- rsp[0] : return address 1453 // -- rsp[0] : return address
1461 // ----------------------------------- 1454 // -----------------------------------
1462 Label miss; 1455 Label miss;
1463 1456
1464 Failure* failure = Failure::InternalError(); 1457 Failure* failure = Failure::InternalError();
1465 bool success = GenerateLoadCallback(object, holder, rax, rcx, rbx, rdx, 1458 bool success = GenerateLoadCallback(object, holder, rax, rcx, rbx, rdx, rdi,
1466 callback, name, &miss, &failure); 1459 callback, name, &miss, &failure);
1467 if (!success) return failure; 1460 if (!success) return failure;
1468 1461
1469 __ bind(&miss); 1462 __ bind(&miss);
1470 GenerateLoadMiss(masm(), Code::LOAD_IC); 1463 GenerateLoadMiss(masm(), Code::LOAD_IC);
1471 1464
1472 // Return the generated code. 1465 // Return the generated code.
1473 return GetCode(CALLBACKS, name); 1466 return GetCode(CALLBACKS, name);
1474 } 1467 }
1475 1468
1476 1469
1477 Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, 1470 Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
1478 JSObject* holder, 1471 JSObject* holder,
1479 Object* value, 1472 Object* value,
1480 String* name) { 1473 String* name) {
1481 // ----------- S t a t e ------------- 1474 // ----------- S t a t e -------------
1482 // -- rax : receiver 1475 // -- rax : receiver
1483 // -- rcx : name 1476 // -- rcx : name
1484 // -- rsp[0] : return address 1477 // -- rsp[0] : return address
1485 // ----------------------------------- 1478 // -----------------------------------
1486 Label miss; 1479 Label miss;
1487 1480
1488 GenerateLoadConstant(object, holder, rax, rbx, rdx, value, name, &miss); 1481 GenerateLoadConstant(object, holder, rax, rbx, rdx, rdi, value, name, &miss);
1489 __ bind(&miss); 1482 __ bind(&miss);
1490 GenerateLoadMiss(masm(), Code::LOAD_IC); 1483 GenerateLoadMiss(masm(), Code::LOAD_IC);
1491 1484
1492 // Return the generated code. 1485 // Return the generated code.
1493 return GetCode(CONSTANT_FUNCTION, name); 1486 return GetCode(CONSTANT_FUNCTION, name);
1494 } 1487 }
1495 1488
1496 1489
1497 Object* LoadStubCompiler::CompileLoadNonexistent(String* name, 1490 Object* LoadStubCompiler::CompileLoadNonexistent(String* name,
1498 JSObject* object, 1491 JSObject* object,
1499 JSObject* last) { 1492 JSObject* last) {
1500 // ----------- S t a t e ------------- 1493 // ----------- S t a t e -------------
1501 // -- rax : receiver 1494 // -- rax : receiver
1502 // -- rcx : name 1495 // -- rcx : name
1503 // -- rsp[0] : return address 1496 // -- rsp[0] : return address
1504 // ----------------------------------- 1497 // -----------------------------------
1505 Label miss; 1498 Label miss;
1506 1499
1507 // Chech that receiver is not a smi. 1500 // Chech that receiver is not a smi.
1508 __ JumpIfSmi(rax, &miss); 1501 __ JumpIfSmi(rax, &miss);
1509 1502
1510 // Check the maps of the full prototype chain. Also check that 1503 // Check the maps of the full prototype chain. Also check that
1511 // global property cells up to (but not including) the last object 1504 // global property cells up to (but not including) the last object
1512 // in the prototype chain are empty. 1505 // in the prototype chain are empty.
1513 CheckPrototypes(object, rax, last, rbx, rdx, name, &miss, rdi); 1506 CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss);
1514 1507
1515 // If the last object in the prototype chain is a global object, 1508 // If the last object in the prototype chain is a global object,
1516 // check that the global property cell is empty. 1509 // check that the global property cell is empty.
1517 if (last->IsGlobalObject()) { 1510 if (last->IsGlobalObject()) {
1518 Object* cell = GenerateCheckPropertyCell(masm(), 1511 Object* cell = GenerateCheckPropertyCell(masm(),
1519 GlobalObject::cast(last), 1512 GlobalObject::cast(last),
1520 name, 1513 name,
1521 rdx, 1514 rdx,
1522 &miss); 1515 &miss);
1523 if (cell->IsFailure()) return cell; 1516 if (cell->IsFailure()) return cell;
(...skipping 16 matching lines...) Expand all
1540 JSObject* holder, 1533 JSObject* holder,
1541 int index, 1534 int index,
1542 String* name) { 1535 String* name) {
1543 // ----------- S t a t e ------------- 1536 // ----------- S t a t e -------------
1544 // -- rax : receiver 1537 // -- rax : receiver
1545 // -- rcx : name 1538 // -- rcx : name
1546 // -- rsp[0] : return address 1539 // -- rsp[0] : return address
1547 // ----------------------------------- 1540 // -----------------------------------
1548 Label miss; 1541 Label miss;
1549 1542
1550 GenerateLoadField(object, holder, rax, rbx, rdx, index, name, &miss); 1543 GenerateLoadField(object, holder, rax, rbx, rdx, rdi, index, name, &miss);
1551 __ bind(&miss); 1544 __ bind(&miss);
1552 GenerateLoadMiss(masm(), Code::LOAD_IC); 1545 GenerateLoadMiss(masm(), Code::LOAD_IC);
1553 1546
1554 // Return the generated code. 1547 // Return the generated code.
1555 return GetCode(FIELD, name); 1548 return GetCode(FIELD, name);
1556 } 1549 }
1557 1550
1558 1551
1559 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, 1552 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1560 JSObject* holder, 1553 JSObject* holder,
(...skipping 10 matching lines...) Expand all
1571 1564
1572 // TODO(368): Compile in the whole chain: all the interceptors in 1565 // TODO(368): Compile in the whole chain: all the interceptors in
1573 // prototypes and ultimate answer. 1566 // prototypes and ultimate answer.
1574 GenerateLoadInterceptor(receiver, 1567 GenerateLoadInterceptor(receiver,
1575 holder, 1568 holder,
1576 &lookup, 1569 &lookup,
1577 rax, 1570 rax,
1578 rcx, 1571 rcx,
1579 rdx, 1572 rdx,
1580 rbx, 1573 rbx,
1574 rdi,
1581 name, 1575 name,
1582 &miss); 1576 &miss);
1583 1577
1584 __ bind(&miss); 1578 __ bind(&miss);
1585 GenerateLoadMiss(masm(), Code::LOAD_IC); 1579 GenerateLoadMiss(masm(), Code::LOAD_IC);
1586 1580
1587 // Return the generated code. 1581 // Return the generated code.
1588 return GetCode(INTERCEPTOR, name); 1582 return GetCode(INTERCEPTOR, name);
1589 } 1583 }
1590 1584
(...skipping 11 matching lines...) Expand all
1602 Label miss; 1596 Label miss;
1603 1597
1604 // If the object is the holder then we know that it's a global 1598 // If the object is the holder then we know that it's a global
1605 // object which can only happen for contextual loads. In this case, 1599 // object which can only happen for contextual loads. In this case,
1606 // the receiver cannot be a smi. 1600 // the receiver cannot be a smi.
1607 if (object != holder) { 1601 if (object != holder) {
1608 __ JumpIfSmi(rax, &miss); 1602 __ JumpIfSmi(rax, &miss);
1609 } 1603 }
1610 1604
1611 // Check that the maps haven't changed. 1605 // Check that the maps haven't changed.
1612 CheckPrototypes(object, rax, holder, rbx, rdx, name, &miss, rdi); 1606 CheckPrototypes(object, rax, holder, rbx, rdx, rdi, name, &miss);
1613 1607
1614 // Get the value from the cell. 1608 // Get the value from the cell.
1615 __ Move(rbx, Handle<JSGlobalPropertyCell>(cell)); 1609 __ Move(rbx, Handle<JSGlobalPropertyCell>(cell));
1616 __ movq(rbx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset)); 1610 __ movq(rbx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset));
1617 1611
1618 // Check for deleted property if property can actually be deleted. 1612 // Check for deleted property if property can actually be deleted.
1619 if (!is_dont_delete) { 1613 if (!is_dont_delete) {
1620 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 1614 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
1621 __ j(equal, &miss); 1615 __ j(equal, &miss);
1622 } else if (FLAG_debug_code) { 1616 } else if (FLAG_debug_code) {
(...skipping 25 matching lines...) Expand all
1648 // ----------------------------------- 1642 // -----------------------------------
1649 Label miss; 1643 Label miss;
1650 1644
1651 __ IncrementCounter(&Counters::keyed_load_callback, 1); 1645 __ IncrementCounter(&Counters::keyed_load_callback, 1);
1652 1646
1653 // Check that the name has not changed. 1647 // Check that the name has not changed.
1654 __ Cmp(rax, Handle<String>(name)); 1648 __ Cmp(rax, Handle<String>(name));
1655 __ j(not_equal, &miss); 1649 __ j(not_equal, &miss);
1656 1650
1657 Failure* failure = Failure::InternalError(); 1651 Failure* failure = Failure::InternalError();
1658 bool success = GenerateLoadCallback(receiver, holder, rdx, rax, rbx, rcx, 1652 bool success = GenerateLoadCallback(receiver, holder, rdx, rax, rbx, rcx, rdi,
1659 callback, name, &miss, &failure); 1653 callback, name, &miss, &failure);
1660 if (!success) return failure; 1654 if (!success) return failure;
1661 1655
1662 __ bind(&miss); 1656 __ bind(&miss);
1663 __ DecrementCounter(&Counters::keyed_load_callback, 1); 1657 __ DecrementCounter(&Counters::keyed_load_callback, 1);
1664 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1658 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1665 1659
1666 // Return the generated code. 1660 // Return the generated code.
1667 return GetCode(CALLBACKS, name); 1661 return GetCode(CALLBACKS, name);
1668 } 1662 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1702 // -- rsp[0] : return address 1696 // -- rsp[0] : return address
1703 // ----------------------------------- 1697 // -----------------------------------
1704 Label miss; 1698 Label miss;
1705 1699
1706 __ IncrementCounter(&Counters::keyed_load_constant_function, 1); 1700 __ IncrementCounter(&Counters::keyed_load_constant_function, 1);
1707 1701
1708 // Check that the name has not changed. 1702 // Check that the name has not changed.
1709 __ Cmp(rax, Handle<String>(name)); 1703 __ Cmp(rax, Handle<String>(name));
1710 __ j(not_equal, &miss); 1704 __ j(not_equal, &miss);
1711 1705
1712 GenerateLoadConstant(receiver, holder, rdx, rbx, rcx, 1706 GenerateLoadConstant(receiver, holder, rdx, rbx, rcx, rdi,
1713 value, name, &miss); 1707 value, name, &miss);
1714 __ bind(&miss); 1708 __ bind(&miss);
1715 __ DecrementCounter(&Counters::keyed_load_constant_function, 1); 1709 __ DecrementCounter(&Counters::keyed_load_constant_function, 1);
1716 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1710 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1717 1711
1718 // Return the generated code. 1712 // Return the generated code.
1719 return GetCode(CONSTANT_FUNCTION, name); 1713 return GetCode(CONSTANT_FUNCTION, name);
1720 } 1714 }
1721 1715
1722 1716
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1762 1756
1763 LookupResult lookup; 1757 LookupResult lookup;
1764 LookupPostInterceptor(holder, name, &lookup); 1758 LookupPostInterceptor(holder, name, &lookup);
1765 GenerateLoadInterceptor(receiver, 1759 GenerateLoadInterceptor(receiver,
1766 holder, 1760 holder,
1767 &lookup, 1761 &lookup,
1768 rdx, 1762 rdx,
1769 rax, 1763 rax,
1770 rcx, 1764 rcx,
1771 rbx, 1765 rbx,
1766 rdi,
1772 name, 1767 name,
1773 &miss); 1768 &miss);
1774 __ bind(&miss); 1769 __ bind(&miss);
1775 __ DecrementCounter(&Counters::keyed_load_interceptor, 1); 1770 __ DecrementCounter(&Counters::keyed_load_interceptor, 1);
1776 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1771 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1777 1772
1778 // Return the generated code. 1773 // Return the generated code.
1779 return GetCode(INTERCEPTOR, name); 1774 return GetCode(INTERCEPTOR, name);
1780 } 1775 }
1781 1776
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
1977 // -- rsp[0] : return address 1972 // -- rsp[0] : return address
1978 // ----------------------------------- 1973 // -----------------------------------
1979 Label miss; 1974 Label miss;
1980 1975
1981 __ IncrementCounter(&Counters::keyed_load_field, 1); 1976 __ IncrementCounter(&Counters::keyed_load_field, 1);
1982 1977
1983 // Check that the name has not changed. 1978 // Check that the name has not changed.
1984 __ Cmp(rax, Handle<String>(name)); 1979 __ Cmp(rax, Handle<String>(name));
1985 __ j(not_equal, &miss); 1980 __ j(not_equal, &miss);
1986 1981
1987 GenerateLoadField(receiver, holder, rdx, rbx, rcx, index, name, &miss); 1982 GenerateLoadField(receiver, holder, rdx, rbx, rcx, rdi, index, name, &miss);
1988 1983
1989 __ bind(&miss); 1984 __ bind(&miss);
1990 __ DecrementCounter(&Counters::keyed_load_field, 1); 1985 __ DecrementCounter(&Counters::keyed_load_field, 1);
1991 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1986 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1992 1987
1993 // Return the generated code. 1988 // Return the generated code.
1994 return GetCode(FIELD, name); 1989 return GetCode(FIELD, name);
1995 } 1990 }
1996 1991
1997 1992
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
2056 } 2051 }
2057 2052
2058 2053
2059 void StubCompiler::GenerateLoadInterceptor(JSObject* object, 2054 void StubCompiler::GenerateLoadInterceptor(JSObject* object,
2060 JSObject* interceptor_holder, 2055 JSObject* interceptor_holder,
2061 LookupResult* lookup, 2056 LookupResult* lookup,
2062 Register receiver, 2057 Register receiver,
2063 Register name_reg, 2058 Register name_reg,
2064 Register scratch1, 2059 Register scratch1,
2065 Register scratch2, 2060 Register scratch2,
2061 Register scratch3,
2066 String* name, 2062 String* name,
2067 Label* miss) { 2063 Label* miss) {
2068 ASSERT(interceptor_holder->HasNamedInterceptor()); 2064 ASSERT(interceptor_holder->HasNamedInterceptor());
2069 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); 2065 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
2070 2066
2071 // Check that the receiver isn't a smi. 2067 // Check that the receiver isn't a smi.
2072 __ JumpIfSmi(receiver, miss); 2068 __ JumpIfSmi(receiver, miss);
2073 2069
2074 // So far the most popular follow ups for interceptor loads are FIELD 2070 // So far the most popular follow ups for interceptor loads are FIELD
2075 // and CALLBACKS, so inline only them, other cases may be added 2071 // and CALLBACKS, so inline only them, other cases may be added
2076 // later. 2072 // later.
2077 bool compile_followup_inline = false; 2073 bool compile_followup_inline = false;
2078 if (lookup->IsProperty() && lookup->IsCacheable()) { 2074 if (lookup->IsProperty() && lookup->IsCacheable()) {
2079 if (lookup->type() == FIELD) { 2075 if (lookup->type() == FIELD) {
2080 compile_followup_inline = true; 2076 compile_followup_inline = true;
2081 } else if (lookup->type() == CALLBACKS && 2077 } else if (lookup->type() == CALLBACKS &&
2082 lookup->GetCallbackObject()->IsAccessorInfo() && 2078 lookup->GetCallbackObject()->IsAccessorInfo() &&
2083 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) { 2079 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) {
2084 compile_followup_inline = true; 2080 compile_followup_inline = true;
2085 } 2081 }
2086 } 2082 }
2087 2083
2088 if (compile_followup_inline) { 2084 if (compile_followup_inline) {
2089 // Compile the interceptor call, followed by inline code to load the 2085 // Compile the interceptor call, followed by inline code to load the
2090 // property from further up the prototype chain if the call fails. 2086 // property from further up the prototype chain if the call fails.
2091 // Check that the maps haven't changed. 2087 // Check that the maps haven't changed.
2092 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 2088 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
2093 scratch1, scratch2, name, miss); 2089 scratch1, scratch2, scratch3,
2090 name, miss);
2094 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); 2091 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
2095 2092
2096 // Save necessary data before invoking an interceptor. 2093 // Save necessary data before invoking an interceptor.
2097 // Requires a frame to make GC aware of pushed pointers. 2094 // Requires a frame to make GC aware of pushed pointers.
2098 __ EnterInternalFrame(); 2095 __ EnterInternalFrame();
2099 2096
2100 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { 2097 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
2101 // CALLBACKS case needs a receiver to be passed into C++ callback. 2098 // CALLBACKS case needs a receiver to be passed into C++ callback.
2102 __ push(receiver); 2099 __ push(receiver);
2103 } 2100 }
(...skipping 27 matching lines...) Expand all
2131 __ LeaveInternalFrame(); 2128 __ LeaveInternalFrame();
2132 2129
2133 // Check that the maps from interceptor's holder to lookup's holder 2130 // Check that the maps from interceptor's holder to lookup's holder
2134 // haven't changed. And load lookup's holder into |holder| register. 2131 // haven't changed. And load lookup's holder into |holder| register.
2135 if (interceptor_holder != lookup->holder()) { 2132 if (interceptor_holder != lookup->holder()) {
2136 holder_reg = CheckPrototypes(interceptor_holder, 2133 holder_reg = CheckPrototypes(interceptor_holder,
2137 holder_reg, 2134 holder_reg,
2138 lookup->holder(), 2135 lookup->holder(),
2139 scratch1, 2136 scratch1,
2140 scratch2, 2137 scratch2,
2138 scratch3,
2141 name, 2139 name,
2142 miss); 2140 miss);
2143 } 2141 }
2144 2142
2145 if (lookup->type() == FIELD) { 2143 if (lookup->type() == FIELD) {
2146 // We found FIELD property in prototype chain of interceptor's holder. 2144 // We found FIELD property in prototype chain of interceptor's holder.
2147 // Retrieve a field from field's holder. 2145 // Retrieve a field from field's holder.
2148 GenerateFastPropertyLoad(masm(), rax, holder_reg, 2146 GenerateFastPropertyLoad(masm(), rax, holder_reg,
2149 lookup->holder(), lookup->GetFieldIndex()); 2147 lookup->holder(), lookup->GetFieldIndex());
2150 __ ret(0); 2148 __ ret(0);
(...skipping 19 matching lines...) Expand all
2170 __ push(scratch2); // restore return address 2168 __ push(scratch2); // restore return address
2171 2169
2172 ExternalReference ref = 2170 ExternalReference ref =
2173 ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); 2171 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
2174 __ TailCallExternalReference(ref, 5, 1); 2172 __ TailCallExternalReference(ref, 5, 1);
2175 } 2173 }
2176 } else { // !compile_followup_inline 2174 } else { // !compile_followup_inline
2177 // Call the runtime system to load the interceptor. 2175 // Call the runtime system to load the interceptor.
2178 // Check that the maps haven't changed. 2176 // Check that the maps haven't changed.
2179 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 2177 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
2180 scratch1, scratch2, name, miss); 2178 scratch1, scratch2, scratch3,
2179 name, miss);
2181 __ pop(scratch2); // save old return address 2180 __ pop(scratch2); // save old return address
2182 PushInterceptorArguments(masm(), receiver, holder_reg, 2181 PushInterceptorArguments(masm(), receiver, holder_reg,
2183 name_reg, interceptor_holder); 2182 name_reg, interceptor_holder);
2184 __ push(scratch2); // restore old return address 2183 __ push(scratch2); // restore old return address
2185 2184
2186 ExternalReference ref = ExternalReference( 2185 ExternalReference ref = ExternalReference(
2187 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); 2186 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
2188 __ TailCallExternalReference(ref, 5, 1); 2187 __ TailCallExternalReference(ref, 5, 1);
2189 } 2188 }
2190 } 2189 }
2191 2190
2192 2191
2193 bool StubCompiler::GenerateLoadCallback(JSObject* object, 2192 bool StubCompiler::GenerateLoadCallback(JSObject* object,
2194 JSObject* holder, 2193 JSObject* holder,
2195 Register receiver, 2194 Register receiver,
2196 Register name_reg, 2195 Register name_reg,
2197 Register scratch1, 2196 Register scratch1,
2198 Register scratch2, 2197 Register scratch2,
2198 Register scratch3,
2199 AccessorInfo* callback, 2199 AccessorInfo* callback,
2200 String* name, 2200 String* name,
2201 Label* miss, 2201 Label* miss,
2202 Failure** failure) { 2202 Failure** failure) {
2203 // Check that the receiver isn't a smi. 2203 // Check that the receiver isn't a smi.
2204 __ JumpIfSmi(receiver, miss); 2204 __ JumpIfSmi(receiver, miss);
2205 2205
2206 // Check that the maps haven't changed. 2206 // Check that the maps haven't changed.
2207 Register reg = 2207 Register reg =
2208 CheckPrototypes(object, receiver, holder, 2208 CheckPrototypes(object, receiver, holder,
2209 scratch1, scratch2, name, miss); 2209 scratch1, scratch2, scratch3, name, miss);
2210 2210
2211 // Push the arguments on the JS stack of the caller. 2211 // Push the arguments on the JS stack of the caller.
2212 __ pop(scratch2); // remove return address 2212 __ pop(scratch2); // remove return address
2213 __ push(receiver); // receiver 2213 __ push(receiver); // receiver
2214 __ push(reg); // holder 2214 __ push(reg); // holder
2215 __ Move(reg, Handle<AccessorInfo>(callback)); // callback data 2215 __ Move(reg, Handle<AccessorInfo>(callback)); // callback data
2216 __ push(reg); 2216 __ push(reg);
2217 __ push(FieldOperand(reg, AccessorInfo::kDataOffset)); 2217 __ push(FieldOperand(reg, AccessorInfo::kDataOffset));
2218 __ push(name_reg); // name 2218 __ push(name_reg); // name
2219 __ push(scratch2); // restore return address 2219 __ push(scratch2); // restore return address
2220 2220
2221 // Do tail-call to the runtime system. 2221 // Do tail-call to the runtime system.
2222 ExternalReference load_callback_property = 2222 ExternalReference load_callback_property =
2223 ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); 2223 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
2224 __ TailCallExternalReference(load_callback_property, 5, 1); 2224 __ TailCallExternalReference(load_callback_property, 5, 1);
2225 2225
2226 return true; 2226 return true;
2227 } 2227 }
2228 2228
2229 2229
2230 Register StubCompiler::CheckPrototypes(JSObject* object, 2230 Register StubCompiler::CheckPrototypes(JSObject* object,
2231 Register object_reg, 2231 Register object_reg,
2232 JSObject* holder, 2232 JSObject* holder,
2233 Register holder_reg, 2233 Register holder_reg,
2234 Register scratch, 2234 Register scratch1,
2235 Register scratch2,
2235 String* name, 2236 String* name,
2236 int save_at_depth, 2237 int save_at_depth,
2237 Label* miss, 2238 Label* miss) {
2238 Register extra) { 2239 // Make sure there's no overlap between holder and object registers.
2239 // Make sure there's no overlap between scratch and the other 2240 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
2240 // registers. 2241 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
2241 ASSERT(!scratch.is(object_reg) && !scratch.is(holder_reg)); 2242 && !scratch2.is(scratch1));
2242 2243
2243 // Keep track of the current object in register reg. On the first 2244 // Keep track of the current object in register reg. On the first
2244 // iteration, reg is an alias for object_reg, on later iterations, 2245 // iteration, reg is an alias for object_reg, on later iterations,
2245 // it is an alias for holder_reg. 2246 // it is an alias for holder_reg.
2246 Register reg = object_reg; 2247 Register reg = object_reg;
2247 int depth = 0; 2248 int depth = 0;
2248 2249
2249 if (save_at_depth == depth) { 2250 if (save_at_depth == depth) {
2250 __ movq(Operand(rsp, kPointerSize), object_reg); 2251 __ movq(Operand(rsp, kPointerSize), object_reg);
2251 } 2252 }
(...skipping 21 matching lines...) Expand all
2273 name = String::cast(lookup_result); 2274 name = String::cast(lookup_result);
2274 } 2275 }
2275 } 2276 }
2276 ASSERT(current->property_dictionary()->FindEntry(name) == 2277 ASSERT(current->property_dictionary()->FindEntry(name) ==
2277 StringDictionary::kNotFound); 2278 StringDictionary::kNotFound);
2278 2279
2279 GenerateDictionaryNegativeLookup(masm(), 2280 GenerateDictionaryNegativeLookup(masm(),
2280 miss, 2281 miss,
2281 reg, 2282 reg,
2282 name, 2283 name,
2283 scratch, 2284 scratch1,
2284 extra); 2285 scratch2);
2285 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); 2286 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
2286 reg = holder_reg; // from now the object is in holder_reg 2287 reg = holder_reg; // from now the object is in holder_reg
2287 __ movq(reg, FieldOperand(scratch, Map::kPrototypeOffset)); 2288 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
2288 } else if (Heap::InNewSpace(prototype)) { 2289 } else if (Heap::InNewSpace(prototype)) {
2289 // Get the map of the current object. 2290 // Get the map of the current object.
2290 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); 2291 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
2291 __ Cmp(scratch, Handle<Map>(current->map())); 2292 __ Cmp(scratch1, Handle<Map>(current->map()));
2292 // Branch on the result of the map check. 2293 // Branch on the result of the map check.
2293 __ j(not_equal, miss); 2294 __ j(not_equal, miss);
2294 // Check access rights to the global object. This has to happen 2295 // Check access rights to the global object. This has to happen
2295 // after the map check so that we know that the object is 2296 // after the map check so that we know that the object is
2296 // actually a global object. 2297 // actually a global object.
2297 if (current->IsJSGlobalProxy()) { 2298 if (current->IsJSGlobalProxy()) {
2298 __ CheckAccessGlobalProxy(reg, scratch, miss); 2299 __ CheckAccessGlobalProxy(reg, scratch1, miss);
2299 2300
2300 // Restore scratch register to be the map of the object. 2301 // Restore scratch register to be the map of the object.
2301 // We load the prototype from the map in the scratch register. 2302 // We load the prototype from the map in the scratch register.
2302 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); 2303 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
2303 } 2304 }
2304 // The prototype is in new space; we cannot store a reference 2305 // The prototype is in new space; we cannot store a reference
2305 // to it in the code. Load it from the map. 2306 // to it in the code. Load it from the map.
2306 reg = holder_reg; // from now the object is in holder_reg 2307 reg = holder_reg; // from now the object is in holder_reg
2307 __ movq(reg, FieldOperand(scratch, Map::kPrototypeOffset)); 2308 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
2308 2309
2309 } else { 2310 } else {
2310 // Check the map of the current object. 2311 // Check the map of the current object.
2311 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), 2312 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset),
2312 Handle<Map>(current->map())); 2313 Handle<Map>(current->map()));
2313 // Branch on the result of the map check. 2314 // Branch on the result of the map check.
2314 __ j(not_equal, miss); 2315 __ j(not_equal, miss);
2315 // Check access rights to the global object. This has to happen 2316 // Check access rights to the global object. This has to happen
2316 // after the map check so that we know that the object is 2317 // after the map check so that we know that the object is
2317 // actually a global object. 2318 // actually a global object.
2318 if (current->IsJSGlobalProxy()) { 2319 if (current->IsJSGlobalProxy()) {
2319 __ CheckAccessGlobalProxy(reg, scratch, miss); 2320 __ CheckAccessGlobalProxy(reg, scratch1, miss);
2320 } 2321 }
2321 // The prototype is in old space; load it directly. 2322 // The prototype is in old space; load it directly.
2322 reg = holder_reg; // from now the object is in holder_reg 2323 reg = holder_reg; // from now the object is in holder_reg
2323 __ Move(reg, Handle<JSObject>(prototype)); 2324 __ Move(reg, Handle<JSObject>(prototype));
2324 } 2325 }
2325 2326
2326 if (save_at_depth == depth) { 2327 if (save_at_depth == depth) {
2327 __ movq(Operand(rsp, kPointerSize), reg); 2328 __ movq(Operand(rsp, kPointerSize), reg);
2328 } 2329 }
2329 2330
2330 // Go to the next object in the prototype chain. 2331 // Go to the next object in the prototype chain.
2331 current = prototype; 2332 current = prototype;
2332 } 2333 }
2333 2334
2334 // Check the holder map. 2335 // Check the holder map.
2335 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), Handle<Map>(holder->map())); 2336 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), Handle<Map>(holder->map()));
2336 __ j(not_equal, miss); 2337 __ j(not_equal, miss);
2337 2338
2338 // Log the check depth. 2339 // Log the check depth.
2339 LOG(IntEvent("check-maps-depth", depth + 1)); 2340 LOG(IntEvent("check-maps-depth", depth + 1));
2340 2341
2341 // Perform security check for access to the global object and return 2342 // Perform security check for access to the global object and return
2342 // the holder register. 2343 // the holder register.
2343 ASSERT(current == holder); 2344 ASSERT(current == holder);
2344 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); 2345 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
2345 if (current->IsJSGlobalProxy()) { 2346 if (current->IsJSGlobalProxy()) {
2346 __ CheckAccessGlobalProxy(reg, scratch, miss); 2347 __ CheckAccessGlobalProxy(reg, scratch1, miss);
2347 } 2348 }
2348 2349
2349 // If we've skipped any global objects, it's not enough to verify 2350 // If we've skipped any global objects, it's not enough to verify
2350 // that their maps haven't changed. We also need to check that the 2351 // that their maps haven't changed. We also need to check that the
2351 // property cell for the property is still empty. 2352 // property cell for the property is still empty.
2352 current = object; 2353 current = object;
2353 while (current != holder) { 2354 while (current != holder) {
2354 if (current->IsGlobalObject()) { 2355 if (current->IsGlobalObject()) {
2355 Object* cell = GenerateCheckPropertyCell(masm(), 2356 Object* cell = GenerateCheckPropertyCell(masm(),
2356 GlobalObject::cast(current), 2357 GlobalObject::cast(current),
2357 name, 2358 name,
2358 scratch, 2359 scratch1,
2359 miss); 2360 miss);
2360 if (cell->IsFailure()) { 2361 if (cell->IsFailure()) {
2361 set_failure(Failure::cast(cell)); 2362 set_failure(Failure::cast(cell));
2362 return reg; 2363 return reg;
2363 } 2364 }
2364 } 2365 }
2365 current = JSObject::cast(current->GetPrototype()); 2366 current = JSObject::cast(current->GetPrototype());
2366 } 2367 }
2367 2368
2368 // Return the register containing the holder. 2369 // Return the register containing the holder.
2369 return reg; 2370 return reg;
2370 } 2371 }
2371 2372
2372 2373
2373 void StubCompiler::GenerateLoadField(JSObject* object, 2374 void StubCompiler::GenerateLoadField(JSObject* object,
2374 JSObject* holder, 2375 JSObject* holder,
2375 Register receiver, 2376 Register receiver,
2376 Register scratch1, 2377 Register scratch1,
2377 Register scratch2, 2378 Register scratch2,
2379 Register scratch3,
2378 int index, 2380 int index,
2379 String* name, 2381 String* name,
2380 Label* miss) { 2382 Label* miss) {
2381 // Check that the receiver isn't a smi. 2383 // Check that the receiver isn't a smi.
2382 __ JumpIfSmi(receiver, miss); 2384 __ JumpIfSmi(receiver, miss);
2383 2385
2384 // Check the prototype chain. 2386 // Check the prototype chain.
2385 Register reg = 2387 Register reg =
2386 CheckPrototypes(object, receiver, holder, 2388 CheckPrototypes(object, receiver, holder,
2387 scratch1, scratch2, name, miss); 2389 scratch1, scratch2, scratch3, name, miss);
2388 2390
2389 // Get the value from the properties. 2391 // Get the value from the properties.
2390 GenerateFastPropertyLoad(masm(), rax, reg, holder, index); 2392 GenerateFastPropertyLoad(masm(), rax, reg, holder, index);
2391 __ ret(0); 2393 __ ret(0);
2392 } 2394 }
2393 2395
2394 2396
2395 void StubCompiler::GenerateLoadConstant(JSObject* object, 2397 void StubCompiler::GenerateLoadConstant(JSObject* object,
2396 JSObject* holder, 2398 JSObject* holder,
2397 Register receiver, 2399 Register receiver,
2398 Register scratch1, 2400 Register scratch1,
2399 Register scratch2, 2401 Register scratch2,
2402 Register scratch3,
2400 Object* value, 2403 Object* value,
2401 String* name, 2404 String* name,
2402 Label* miss) { 2405 Label* miss) {
2403 // Check that the receiver isn't a smi. 2406 // Check that the receiver isn't a smi.
2404 __ JumpIfSmi(receiver, miss); 2407 __ JumpIfSmi(receiver, miss);
2405 2408
2406 // Check that the maps haven't changed. 2409 // Check that the maps haven't changed.
2407 Register reg = 2410 Register reg =
2408 CheckPrototypes(object, receiver, holder, 2411 CheckPrototypes(object, receiver, holder,
2409 scratch1, scratch2, name, miss); 2412 scratch1, scratch2, scratch3, name, miss);
2410 2413
2411 // Return the constant value. 2414 // Return the constant value.
2412 __ Move(rax, Handle<Object>(value)); 2415 __ Move(rax, Handle<Object>(value));
2413 __ ret(0); 2416 __ ret(0);
2414 } 2417 }
2415 2418
2416 2419
2417 // Specialized stub for constructing objects from functions which only have only 2420 // Specialized stub for constructing objects from functions which only have only
2418 // simple assignments of the form this.x = ...; in their body. 2421 // simple assignments of the form this.x = ...; in their body.
2419 Object* ConstructStubCompiler::CompileConstructStub( 2422 Object* ConstructStubCompiler::CompileConstructStub(
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
2542 // Return the generated code. 2545 // Return the generated code.
2543 return GetCode(); 2546 return GetCode();
2544 } 2547 }
2545 2548
2546 2549
2547 #undef __ 2550 #undef __
2548 2551
2549 } } // namespace v8::internal 2552 } } // namespace v8::internal
2550 2553
2551 #endif // V8_TARGET_ARCH_X64 2554 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/stub-cache.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698