OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 // Helper function used to check that the dictionary doesn't contain | 104 // Helper function used to check that the dictionary doesn't contain |
105 // the property. This function may return false negatives, so miss_label | 105 // the property. This function may return false negatives, so miss_label |
106 // must always call a backup property check that is complete. | 106 // must always call a backup property check that is complete. |
107 // This function is safe to call if the receiver has fast properties. | 107 // This function is safe to call if the receiver has fast properties. |
108 // Name must be a symbol and receiver must be a heap object. | 108 // Name must be a symbol and receiver must be a heap object. |
109 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 109 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, |
110 Label* miss_label, | 110 Label* miss_label, |
111 Register receiver, | 111 Register receiver, |
112 String* name, | 112 String* name, |
113 Register r0, | 113 Register r0, |
114 Register extra) { | 114 Register r1) { |
115 ASSERT(name->IsSymbol()); | 115 ASSERT(name->IsSymbol()); |
116 __ IncrementCounter(&Counters::negative_lookups, 1); | 116 __ IncrementCounter(&Counters::negative_lookups, 1); |
117 __ IncrementCounter(&Counters::negative_lookups_miss, 1); | 117 __ IncrementCounter(&Counters::negative_lookups_miss, 1); |
118 | 118 |
119 Label done; | 119 Label done; |
120 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); | 120 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); |
121 | 121 |
122 const int kInterceptorOrAccessCheckNeededMask = | 122 const int kInterceptorOrAccessCheckNeededMask = |
123 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 123 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
124 | 124 |
(...skipping 28 matching lines...) Expand all Loading... |
153 StringDictionary::kElementsStartIndex * kPointerSize; | 153 StringDictionary::kElementsStartIndex * kPointerSize; |
154 | 154 |
155 // If names of slots in range from 1 to kProbes - 1 for the hash value are | 155 // If names of slots in range from 1 to kProbes - 1 for the hash value are |
156 // not equal to the name and kProbes-th slot is not used (its name is the | 156 // not equal to the name and kProbes-th slot is not used (its name is the |
157 // undefined value), it guarantees the hash table doesn't contain the | 157 // undefined value), it guarantees the hash table doesn't contain the |
158 // property. It's true even if some slots represent deleted properties | 158 // property. It's true even if some slots represent deleted properties |
159 // (their names are the null value). | 159 // (their names are the null value). |
160 for (int i = 0; i < kProbes; i++) { | 160 for (int i = 0; i < kProbes; i++) { |
161 // r0 points to properties hash. | 161 // r0 points to properties hash. |
162 // Compute the masked index: (hash + i + i * i) & mask. | 162 // Compute the masked index: (hash + i + i * i) & mask. |
163 if (extra.is(no_reg)) { | 163 Register index = r1; |
164 __ push(receiver); | |
165 } | |
166 Register index = extra.is(no_reg) ? receiver : extra; | |
167 // Capacity is smi 2^n. | 164 // Capacity is smi 2^n. |
168 __ mov(index, FieldOperand(properties, kCapacityOffset)); | 165 __ mov(index, FieldOperand(properties, kCapacityOffset)); |
169 __ dec(index); | 166 __ dec(index); |
170 __ and_(Operand(index), | 167 __ and_(Operand(index), |
171 Immediate(Smi::FromInt(name->Hash() + | 168 Immediate(Smi::FromInt(name->Hash() + |
172 StringDictionary::GetProbeOffset(i)))); | 169 StringDictionary::GetProbeOffset(i)))); |
173 | 170 |
174 // Scale the index by multiplying by the entry size. | 171 // Scale the index by multiplying by the entry size. |
175 ASSERT(StringDictionary::kEntrySize == 3); | 172 ASSERT(StringDictionary::kEntrySize == 3); |
176 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3. | 173 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3. |
177 | 174 |
178 Register entity_name = extra.is(no_reg) ? properties : extra; | 175 Register entity_name = r1; |
179 // Having undefined at this place means the name is not contained. | 176 // Having undefined at this place means the name is not contained. |
180 ASSERT_EQ(kSmiTagSize, 1); | 177 ASSERT_EQ(kSmiTagSize, 1); |
181 __ mov(entity_name, Operand(properties, index, times_half_pointer_size, | 178 __ mov(entity_name, Operand(properties, index, times_half_pointer_size, |
182 kElementsStartOffset - kHeapObjectTag)); | 179 kElementsStartOffset - kHeapObjectTag)); |
183 __ cmp(entity_name, Factory::undefined_value()); | 180 __ cmp(entity_name, Factory::undefined_value()); |
184 if (extra.is(no_reg)) { | |
185 // 'receiver' shares a register with 'entity_name'. | |
186 __ pop(receiver); | |
187 } | |
188 if (i != kProbes - 1) { | 181 if (i != kProbes - 1) { |
189 __ j(equal, &done, taken); | 182 __ j(equal, &done, taken); |
190 | 183 |
191 // Stop if found the property. | 184 // Stop if found the property. |
192 __ cmp(entity_name, Handle<String>(name)); | 185 __ cmp(entity_name, Handle<String>(name)); |
193 __ j(equal, miss_label, not_taken); | 186 __ j(equal, miss_label, not_taken); |
194 | |
195 if (extra.is(no_reg)) { | |
196 // Restore the properties if their register was occupied by the name. | |
197 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); | |
198 } | |
199 } else { | 187 } else { |
200 // Give up probing if still not found the undefined value. | 188 // Give up probing if still not found the undefined value. |
201 __ j(not_equal, miss_label, not_taken); | 189 __ j(not_equal, miss_label, not_taken); |
202 } | 190 } |
203 } | 191 } |
204 | 192 |
205 __ bind(&done); | 193 __ bind(&done); |
206 __ DecrementCounter(&Counters::negative_lookups_miss, 1); | 194 __ DecrementCounter(&Counters::negative_lookups_miss, 1); |
207 } | 195 } |
208 | 196 |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 name_(name) {} | 508 name_(name) {} |
521 | 509 |
522 void Compile(MacroAssembler* masm, | 510 void Compile(MacroAssembler* masm, |
523 JSObject* object, | 511 JSObject* object, |
524 JSObject* holder, | 512 JSObject* holder, |
525 String* name, | 513 String* name, |
526 LookupResult* lookup, | 514 LookupResult* lookup, |
527 Register receiver, | 515 Register receiver, |
528 Register scratch1, | 516 Register scratch1, |
529 Register scratch2, | 517 Register scratch2, |
| 518 Register scratch3, |
530 Label* miss) { | 519 Label* miss) { |
531 ASSERT(holder->HasNamedInterceptor()); | 520 ASSERT(holder->HasNamedInterceptor()); |
532 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 521 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
533 | 522 |
534 // Check that the receiver isn't a smi. | 523 // Check that the receiver isn't a smi. |
535 __ test(receiver, Immediate(kSmiTagMask)); | 524 __ test(receiver, Immediate(kSmiTagMask)); |
536 __ j(zero, miss, not_taken); | 525 __ j(zero, miss, not_taken); |
537 | 526 |
538 CallOptimization optimization(lookup); | 527 CallOptimization optimization(lookup); |
539 | 528 |
540 if (optimization.is_constant_call()) { | 529 if (optimization.is_constant_call()) { |
541 CompileCacheable(masm, | 530 CompileCacheable(masm, |
542 object, | 531 object, |
543 receiver, | 532 receiver, |
544 scratch1, | 533 scratch1, |
545 scratch2, | 534 scratch2, |
| 535 scratch3, |
546 holder, | 536 holder, |
547 lookup, | 537 lookup, |
548 name, | 538 name, |
549 optimization, | 539 optimization, |
550 miss); | 540 miss); |
551 } else { | 541 } else { |
552 CompileRegular(masm, | 542 CompileRegular(masm, |
553 object, | 543 object, |
554 receiver, | 544 receiver, |
555 scratch1, | 545 scratch1, |
556 scratch2, | 546 scratch2, |
| 547 scratch3, |
557 name, | 548 name, |
558 holder, | 549 holder, |
559 miss); | 550 miss); |
560 } | 551 } |
561 } | 552 } |
562 | 553 |
563 private: | 554 private: |
564 void CompileCacheable(MacroAssembler* masm, | 555 void CompileCacheable(MacroAssembler* masm, |
565 JSObject* object, | 556 JSObject* object, |
566 Register receiver, | 557 Register receiver, |
567 Register scratch1, | 558 Register scratch1, |
568 Register scratch2, | 559 Register scratch2, |
| 560 Register scratch3, |
569 JSObject* interceptor_holder, | 561 JSObject* interceptor_holder, |
570 LookupResult* lookup, | 562 LookupResult* lookup, |
571 String* name, | 563 String* name, |
572 const CallOptimization& optimization, | 564 const CallOptimization& optimization, |
573 Label* miss_label) { | 565 Label* miss_label) { |
574 ASSERT(optimization.is_constant_call()); | 566 ASSERT(optimization.is_constant_call()); |
575 ASSERT(!lookup->holder()->IsGlobalObject()); | 567 ASSERT(!lookup->holder()->IsGlobalObject()); |
576 | 568 |
577 int depth1 = kInvalidProtoDepth; | 569 int depth1 = kInvalidProtoDepth; |
578 int depth2 = kInvalidProtoDepth; | 570 int depth2 = kInvalidProtoDepth; |
(...skipping 19 matching lines...) Expand all Loading... |
598 ReserveSpaceForFastApiCall(masm, scratch1); | 590 ReserveSpaceForFastApiCall(masm, scratch1); |
599 } | 591 } |
600 | 592 |
601 // Check that the maps from receiver to interceptor's holder | 593 // Check that the maps from receiver to interceptor's holder |
602 // haven't changed and thus we can invoke interceptor. | 594 // haven't changed and thus we can invoke interceptor. |
603 Label miss_cleanup; | 595 Label miss_cleanup; |
604 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | 596 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
605 Register holder = | 597 Register holder = |
606 stub_compiler_->CheckPrototypes(object, receiver, | 598 stub_compiler_->CheckPrototypes(object, receiver, |
607 interceptor_holder, scratch1, | 599 interceptor_holder, scratch1, |
608 scratch2, name, depth1, miss); | 600 scratch2, scratch3, name, depth1, miss); |
609 | 601 |
610 // Invoke an interceptor and if it provides a value, | 602 // Invoke an interceptor and if it provides a value, |
611 // branch to |regular_invoke|. | 603 // branch to |regular_invoke|. |
612 Label regular_invoke; | 604 Label regular_invoke; |
613 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, | 605 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, |
614 ®ular_invoke); | 606 ®ular_invoke); |
615 | 607 |
616 // Interceptor returned nothing for this property. Try to use cached | 608 // Interceptor returned nothing for this property. Try to use cached |
617 // constant function. | 609 // constant function. |
618 | 610 |
619 // Check that the maps from interceptor's holder to constant function's | 611 // Check that the maps from interceptor's holder to constant function's |
620 // holder haven't changed and thus we can use cached constant function. | 612 // holder haven't changed and thus we can use cached constant function. |
621 if (interceptor_holder != lookup->holder()) { | 613 if (interceptor_holder != lookup->holder()) { |
622 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, | 614 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, |
623 lookup->holder(), scratch1, | 615 lookup->holder(), scratch1, |
624 scratch2, name, depth2, miss); | 616 scratch2, scratch3, name, depth2, miss); |
625 } else { | 617 } else { |
626 // CheckPrototypes has a side effect of fetching a 'holder' | 618 // CheckPrototypes has a side effect of fetching a 'holder' |
627 // for API (object which is instanceof for the signature). It's | 619 // for API (object which is instanceof for the signature). It's |
628 // safe to omit it here, as if present, it should be fetched | 620 // safe to omit it here, as if present, it should be fetched |
629 // by the previous CheckPrototypes. | 621 // by the previous CheckPrototypes. |
630 ASSERT(depth2 == kInvalidProtoDepth); | 622 ASSERT(depth2 == kInvalidProtoDepth); |
631 } | 623 } |
632 | 624 |
633 // Invoke function. | 625 // Invoke function. |
634 if (can_do_fast_api_call) { | 626 if (can_do_fast_api_call) { |
(...skipping 15 matching lines...) Expand all Loading... |
650 if (can_do_fast_api_call) { | 642 if (can_do_fast_api_call) { |
651 FreeSpaceForFastApiCall(masm, scratch1); | 643 FreeSpaceForFastApiCall(masm, scratch1); |
652 } | 644 } |
653 } | 645 } |
654 | 646 |
655 void CompileRegular(MacroAssembler* masm, | 647 void CompileRegular(MacroAssembler* masm, |
656 JSObject* object, | 648 JSObject* object, |
657 Register receiver, | 649 Register receiver, |
658 Register scratch1, | 650 Register scratch1, |
659 Register scratch2, | 651 Register scratch2, |
| 652 Register scratch3, |
660 String* name, | 653 String* name, |
661 JSObject* interceptor_holder, | 654 JSObject* interceptor_holder, |
662 Label* miss_label) { | 655 Label* miss_label) { |
663 Register holder = | 656 Register holder = |
664 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 657 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, |
665 scratch1, scratch2, name, | 658 scratch1, scratch2, scratch3, name, |
666 miss_label); | 659 miss_label); |
667 | 660 |
668 __ EnterInternalFrame(); | 661 __ EnterInternalFrame(); |
669 // Save the name_ register across the call. | 662 // Save the name_ register across the call. |
670 __ push(name_); | 663 __ push(name_); |
671 | 664 |
672 PushInterceptorArguments(masm, | 665 PushInterceptorArguments(masm, |
673 receiver, | 666 receiver, |
674 holder, | 667 holder, |
675 name_, | 668 name_, |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 | 850 |
858 | 851 |
859 #undef __ | 852 #undef __ |
860 #define __ ACCESS_MASM(masm()) | 853 #define __ ACCESS_MASM(masm()) |
861 | 854 |
862 | 855 |
863 Register StubCompiler::CheckPrototypes(JSObject* object, | 856 Register StubCompiler::CheckPrototypes(JSObject* object, |
864 Register object_reg, | 857 Register object_reg, |
865 JSObject* holder, | 858 JSObject* holder, |
866 Register holder_reg, | 859 Register holder_reg, |
867 Register scratch, | 860 Register scratch1, |
| 861 Register scratch2, |
868 String* name, | 862 String* name, |
869 int save_at_depth, | 863 int save_at_depth, |
870 Label* miss, | 864 Label* miss) { |
871 Register extra) { | |
872 // Make sure there's no overlap between holder and object registers. | 865 // Make sure there's no overlap between holder and object registers. |
873 ASSERT(!scratch.is(object_reg) && !scratch.is(holder_reg)); | 866 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
874 ASSERT(!extra.is(object_reg) && !extra.is(holder_reg) && !extra.is(scratch)); | 867 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 868 && !scratch2.is(scratch1)); |
875 // Keep track of the current object in register reg. | 869 // Keep track of the current object in register reg. |
876 Register reg = object_reg; | 870 Register reg = object_reg; |
877 JSObject* current = object; | 871 JSObject* current = object; |
878 int depth = 0; | 872 int depth = 0; |
879 | 873 |
880 if (save_at_depth == depth) { | 874 if (save_at_depth == depth) { |
881 __ mov(Operand(esp, kPointerSize), reg); | 875 __ mov(Operand(esp, kPointerSize), reg); |
882 } | 876 } |
883 | 877 |
884 // Traverse the prototype chain and check the maps in the prototype chain for | 878 // Traverse the prototype chain and check the maps in the prototype chain for |
(...skipping 19 matching lines...) Expand all Loading... |
904 name = String::cast(lookup_result); | 898 name = String::cast(lookup_result); |
905 } | 899 } |
906 } | 900 } |
907 ASSERT(current->property_dictionary()->FindEntry(name) == | 901 ASSERT(current->property_dictionary()->FindEntry(name) == |
908 StringDictionary::kNotFound); | 902 StringDictionary::kNotFound); |
909 | 903 |
910 GenerateDictionaryNegativeLookup(masm(), | 904 GenerateDictionaryNegativeLookup(masm(), |
911 miss, | 905 miss, |
912 reg, | 906 reg, |
913 name, | 907 name, |
914 scratch, | 908 scratch1, |
915 extra); | 909 scratch2); |
916 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 910 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
917 reg = holder_reg; // from now the object is in holder_reg | 911 reg = holder_reg; // from now the object is in holder_reg |
918 __ mov(reg, FieldOperand(scratch, Map::kPrototypeOffset)); | 912 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
919 } else if (Heap::InNewSpace(prototype)) { | 913 } else if (Heap::InNewSpace(prototype)) { |
920 // Get the map of the current object. | 914 // Get the map of the current object. |
921 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 915 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
922 __ cmp(Operand(scratch), Immediate(Handle<Map>(current->map()))); | 916 __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map()))); |
923 // Branch on the result of the map check. | 917 // Branch on the result of the map check. |
924 __ j(not_equal, miss, not_taken); | 918 __ j(not_equal, miss, not_taken); |
925 // Check access rights to the global object. This has to happen | 919 // Check access rights to the global object. This has to happen |
926 // after the map check so that we know that the object is | 920 // after the map check so that we know that the object is |
927 // actually a global object. | 921 // actually a global object. |
928 if (current->IsJSGlobalProxy()) { | 922 if (current->IsJSGlobalProxy()) { |
929 __ CheckAccessGlobalProxy(reg, scratch, miss); | 923 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
930 | 924 |
931 // Restore scratch register to be the map of the object. | 925 // Restore scratch register to be the map of the object. |
932 // We load the prototype from the map in the scratch register. | 926 // We load the prototype from the map in the scratch register. |
933 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 927 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
934 } | 928 } |
935 // The prototype is in new space; we cannot store a reference | 929 // The prototype is in new space; we cannot store a reference |
936 // to it in the code. Load it from the map. | 930 // to it in the code. Load it from the map. |
937 reg = holder_reg; // from now the object is in holder_reg | 931 reg = holder_reg; // from now the object is in holder_reg |
938 __ mov(reg, FieldOperand(scratch, Map::kPrototypeOffset)); | 932 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
939 } else { | 933 } else { |
940 // Check the map of the current object. | 934 // Check the map of the current object. |
941 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 935 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
942 Immediate(Handle<Map>(current->map()))); | 936 Immediate(Handle<Map>(current->map()))); |
943 // Branch on the result of the map check. | 937 // Branch on the result of the map check. |
944 __ j(not_equal, miss, not_taken); | 938 __ j(not_equal, miss, not_taken); |
945 // Check access rights to the global object. This has to happen | 939 // Check access rights to the global object. This has to happen |
946 // after the map check so that we know that the object is | 940 // after the map check so that we know that the object is |
947 // actually a global object. | 941 // actually a global object. |
948 if (current->IsJSGlobalProxy()) { | 942 if (current->IsJSGlobalProxy()) { |
949 __ CheckAccessGlobalProxy(reg, scratch, miss); | 943 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
950 } | 944 } |
951 // The prototype is in old space; load it directly. | 945 // The prototype is in old space; load it directly. |
952 reg = holder_reg; // from now the object is in holder_reg | 946 reg = holder_reg; // from now the object is in holder_reg |
953 __ mov(reg, Handle<JSObject>(prototype)); | 947 __ mov(reg, Handle<JSObject>(prototype)); |
954 } | 948 } |
955 | 949 |
956 if (save_at_depth == depth) { | 950 if (save_at_depth == depth) { |
957 __ mov(Operand(esp, kPointerSize), reg); | 951 __ mov(Operand(esp, kPointerSize), reg); |
958 } | 952 } |
959 | 953 |
960 // Go to the next object in the prototype chain. | 954 // Go to the next object in the prototype chain. |
961 current = prototype; | 955 current = prototype; |
962 } | 956 } |
963 ASSERT(current == holder); | 957 ASSERT(current == holder); |
964 | 958 |
965 // Log the check depth. | 959 // Log the check depth. |
966 LOG(IntEvent("check-maps-depth", depth + 1)); | 960 LOG(IntEvent("check-maps-depth", depth + 1)); |
967 | 961 |
968 // Check the holder map. | 962 // Check the holder map. |
969 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 963 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
970 Immediate(Handle<Map>(holder->map()))); | 964 Immediate(Handle<Map>(holder->map()))); |
971 __ j(not_equal, miss, not_taken); | 965 __ j(not_equal, miss, not_taken); |
972 | 966 |
973 // Perform security check for access to the global object. | 967 // Perform security check for access to the global object. |
974 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 968 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
975 if (holder->IsJSGlobalProxy()) { | 969 if (holder->IsJSGlobalProxy()) { |
976 __ CheckAccessGlobalProxy(reg, scratch, miss); | 970 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
977 }; | 971 }; |
978 | 972 |
979 // If we've skipped any global objects, it's not enough to verify | 973 // If we've skipped any global objects, it's not enough to verify |
980 // that their maps haven't changed. We also need to check that the | 974 // that their maps haven't changed. We also need to check that the |
981 // property cell for the property is still empty. | 975 // property cell for the property is still empty. |
982 Object* result = GenerateCheckPropertyCells(masm(), | 976 Object* result = GenerateCheckPropertyCells(masm(), |
983 object, | 977 object, |
984 holder, | 978 holder, |
985 name, | 979 name, |
986 scratch, | 980 scratch1, |
987 miss); | 981 miss); |
988 if (result->IsFailure()) set_failure(Failure::cast(result)); | 982 if (result->IsFailure()) set_failure(Failure::cast(result)); |
989 | 983 |
990 // Return the register containing the holder. | 984 // Return the register containing the holder. |
991 return reg; | 985 return reg; |
992 } | 986 } |
993 | 987 |
994 | 988 |
995 void StubCompiler::GenerateLoadField(JSObject* object, | 989 void StubCompiler::GenerateLoadField(JSObject* object, |
996 JSObject* holder, | 990 JSObject* holder, |
997 Register receiver, | 991 Register receiver, |
998 Register scratch1, | 992 Register scratch1, |
999 Register scratch2, | 993 Register scratch2, |
| 994 Register scratch3, |
1000 int index, | 995 int index, |
1001 String* name, | 996 String* name, |
1002 Label* miss) { | 997 Label* miss) { |
1003 // Check that the receiver isn't a smi. | 998 // Check that the receiver isn't a smi. |
1004 __ test(receiver, Immediate(kSmiTagMask)); | 999 __ test(receiver, Immediate(kSmiTagMask)); |
1005 __ j(zero, miss, not_taken); | 1000 __ j(zero, miss, not_taken); |
1006 | 1001 |
1007 // Check the prototype chain. | 1002 // Check the prototype chain. |
1008 Register reg = | 1003 Register reg = |
1009 CheckPrototypes(object, receiver, holder, | 1004 CheckPrototypes(object, receiver, holder, |
1010 scratch1, scratch2, name, miss); | 1005 scratch1, scratch2, scratch3, name, miss); |
1011 | 1006 |
1012 // Get the value from the properties. | 1007 // Get the value from the properties. |
1013 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); | 1008 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); |
1014 __ ret(0); | 1009 __ ret(0); |
1015 } | 1010 } |
1016 | 1011 |
1017 | 1012 |
1018 bool StubCompiler::GenerateLoadCallback(JSObject* object, | 1013 bool StubCompiler::GenerateLoadCallback(JSObject* object, |
1019 JSObject* holder, | 1014 JSObject* holder, |
1020 Register receiver, | 1015 Register receiver, |
1021 Register name_reg, | 1016 Register name_reg, |
1022 Register scratch1, | 1017 Register scratch1, |
1023 Register scratch2, | 1018 Register scratch2, |
| 1019 Register scratch3, |
1024 AccessorInfo* callback, | 1020 AccessorInfo* callback, |
1025 String* name, | 1021 String* name, |
1026 Label* miss, | 1022 Label* miss, |
1027 Failure** failure) { | 1023 Failure** failure) { |
1028 // Check that the receiver isn't a smi. | 1024 // Check that the receiver isn't a smi. |
1029 __ test(receiver, Immediate(kSmiTagMask)); | 1025 __ test(receiver, Immediate(kSmiTagMask)); |
1030 __ j(zero, miss, not_taken); | 1026 __ j(zero, miss, not_taken); |
1031 | 1027 |
1032 // Check that the maps haven't changed. | 1028 // Check that the maps haven't changed. |
1033 Register reg = | 1029 Register reg = |
1034 CheckPrototypes(object, receiver, holder, | 1030 CheckPrototypes(object, receiver, holder, |
1035 scratch1, scratch2, name, miss); | 1031 scratch1, scratch2, scratch3, name, miss); |
1036 | 1032 |
1037 Handle<AccessorInfo> callback_handle(callback); | 1033 Handle<AccessorInfo> callback_handle(callback); |
1038 | 1034 |
1039 Register other = reg.is(scratch1) ? scratch2 : scratch1; | 1035 Register other = reg.is(scratch1) ? scratch2 : scratch1; |
1040 __ EnterInternalFrame(); | 1036 __ EnterInternalFrame(); |
1041 __ PushHandleScope(other); | 1037 __ PushHandleScope(other); |
1042 // Push the stack address where the list of arguments ends | 1038 // Push the stack address where the list of arguments ends |
1043 __ mov(other, esp); | 1039 __ mov(other, esp); |
1044 __ sub(Operand(other), Immediate(2 * kPointerSize)); | 1040 __ sub(Operand(other), Immediate(2 * kPointerSize)); |
1045 __ push(other); | 1041 __ push(other); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1089 __ ret(0); | 1085 __ ret(0); |
1090 return true; | 1086 return true; |
1091 } | 1087 } |
1092 | 1088 |
1093 | 1089 |
1094 void StubCompiler::GenerateLoadConstant(JSObject* object, | 1090 void StubCompiler::GenerateLoadConstant(JSObject* object, |
1095 JSObject* holder, | 1091 JSObject* holder, |
1096 Register receiver, | 1092 Register receiver, |
1097 Register scratch1, | 1093 Register scratch1, |
1098 Register scratch2, | 1094 Register scratch2, |
| 1095 Register scratch3, |
1099 Object* value, | 1096 Object* value, |
1100 String* name, | 1097 String* name, |
1101 Label* miss) { | 1098 Label* miss) { |
1102 // Check that the receiver isn't a smi. | 1099 // Check that the receiver isn't a smi. |
1103 __ test(receiver, Immediate(kSmiTagMask)); | 1100 __ test(receiver, Immediate(kSmiTagMask)); |
1104 __ j(zero, miss, not_taken); | 1101 __ j(zero, miss, not_taken); |
1105 | 1102 |
1106 // Check that the maps haven't changed. | 1103 // Check that the maps haven't changed. |
1107 Register reg = | 1104 Register reg = |
1108 CheckPrototypes(object, receiver, holder, | 1105 CheckPrototypes(object, receiver, holder, |
1109 scratch1, scratch2, name, miss); | 1106 scratch1, scratch2, scratch3, name, miss); |
1110 | 1107 |
1111 // Return the constant value. | 1108 // Return the constant value. |
1112 __ mov(eax, Handle<Object>(value)); | 1109 __ mov(eax, Handle<Object>(value)); |
1113 __ ret(0); | 1110 __ ret(0); |
1114 } | 1111 } |
1115 | 1112 |
1116 | 1113 |
1117 void StubCompiler::GenerateLoadInterceptor(JSObject* object, | 1114 void StubCompiler::GenerateLoadInterceptor(JSObject* object, |
1118 JSObject* interceptor_holder, | 1115 JSObject* interceptor_holder, |
1119 LookupResult* lookup, | 1116 LookupResult* lookup, |
1120 Register receiver, | 1117 Register receiver, |
1121 Register name_reg, | 1118 Register name_reg, |
1122 Register scratch1, | 1119 Register scratch1, |
1123 Register scratch2, | 1120 Register scratch2, |
| 1121 Register scratch3, |
1124 String* name, | 1122 String* name, |
1125 Label* miss) { | 1123 Label* miss) { |
1126 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1124 ASSERT(interceptor_holder->HasNamedInterceptor()); |
1127 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1125 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
1128 | 1126 |
1129 // Check that the receiver isn't a smi. | 1127 // Check that the receiver isn't a smi. |
1130 __ test(receiver, Immediate(kSmiTagMask)); | 1128 __ test(receiver, Immediate(kSmiTagMask)); |
1131 __ j(zero, miss, not_taken); | 1129 __ j(zero, miss, not_taken); |
1132 | 1130 |
1133 // So far the most popular follow ups for interceptor loads are FIELD | 1131 // So far the most popular follow ups for interceptor loads are FIELD |
1134 // and CALLBACKS, so inline only them, other cases may be added | 1132 // and CALLBACKS, so inline only them, other cases may be added |
1135 // later. | 1133 // later. |
1136 bool compile_followup_inline = false; | 1134 bool compile_followup_inline = false; |
1137 if (lookup->IsProperty() && lookup->IsCacheable()) { | 1135 if (lookup->IsProperty() && lookup->IsCacheable()) { |
1138 if (lookup->type() == FIELD) { | 1136 if (lookup->type() == FIELD) { |
1139 compile_followup_inline = true; | 1137 compile_followup_inline = true; |
1140 } else if (lookup->type() == CALLBACKS && | 1138 } else if (lookup->type() == CALLBACKS && |
1141 lookup->GetCallbackObject()->IsAccessorInfo() && | 1139 lookup->GetCallbackObject()->IsAccessorInfo() && |
1142 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) { | 1140 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) { |
1143 compile_followup_inline = true; | 1141 compile_followup_inline = true; |
1144 } | 1142 } |
1145 } | 1143 } |
1146 | 1144 |
1147 if (compile_followup_inline) { | 1145 if (compile_followup_inline) { |
1148 // Compile the interceptor call, followed by inline code to load the | 1146 // Compile the interceptor call, followed by inline code to load the |
1149 // property from further up the prototype chain if the call fails. | 1147 // property from further up the prototype chain if the call fails. |
1150 // Check that the maps haven't changed. | 1148 // Check that the maps haven't changed. |
1151 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, | 1149 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, |
1152 scratch1, scratch2, name, miss); | 1150 scratch1, scratch2, scratch3, |
| 1151 name, miss); |
1153 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); | 1152 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); |
1154 | 1153 |
1155 // Save necessary data before invoking an interceptor. | 1154 // Save necessary data before invoking an interceptor. |
1156 // Requires a frame to make GC aware of pushed pointers. | 1155 // Requires a frame to make GC aware of pushed pointers. |
1157 __ EnterInternalFrame(); | 1156 __ EnterInternalFrame(); |
1158 | 1157 |
1159 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { | 1158 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { |
1160 // CALLBACKS case needs a receiver to be passed into C++ callback. | 1159 // CALLBACKS case needs a receiver to be passed into C++ callback. |
1161 __ push(receiver); | 1160 __ push(receiver); |
1162 } | 1161 } |
(...skipping 27 matching lines...) Expand all Loading... |
1190 __ LeaveInternalFrame(); | 1189 __ LeaveInternalFrame(); |
1191 | 1190 |
1192 // Check that the maps from interceptor's holder to lookup's holder | 1191 // Check that the maps from interceptor's holder to lookup's holder |
1193 // haven't changed. And load lookup's holder into holder_reg. | 1192 // haven't changed. And load lookup's holder into holder_reg. |
1194 if (interceptor_holder != lookup->holder()) { | 1193 if (interceptor_holder != lookup->holder()) { |
1195 holder_reg = CheckPrototypes(interceptor_holder, | 1194 holder_reg = CheckPrototypes(interceptor_holder, |
1196 holder_reg, | 1195 holder_reg, |
1197 lookup->holder(), | 1196 lookup->holder(), |
1198 scratch1, | 1197 scratch1, |
1199 scratch2, | 1198 scratch2, |
| 1199 scratch3, |
1200 name, | 1200 name, |
1201 miss); | 1201 miss); |
1202 } | 1202 } |
1203 | 1203 |
1204 if (lookup->type() == FIELD) { | 1204 if (lookup->type() == FIELD) { |
1205 // We found FIELD property in prototype chain of interceptor's holder. | 1205 // We found FIELD property in prototype chain of interceptor's holder. |
1206 // Retrieve a field from field's holder. | 1206 // Retrieve a field from field's holder. |
1207 GenerateFastPropertyLoad(masm(), eax, holder_reg, | 1207 GenerateFastPropertyLoad(masm(), eax, holder_reg, |
1208 lookup->holder(), lookup->GetFieldIndex()); | 1208 lookup->holder(), lookup->GetFieldIndex()); |
1209 __ ret(0); | 1209 __ ret(0); |
(...skipping 20 matching lines...) Expand all Loading... |
1230 | 1230 |
1231 ExternalReference ref = | 1231 ExternalReference ref = |
1232 ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); | 1232 ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); |
1233 __ TailCallExternalReference(ref, 5, 1); | 1233 __ TailCallExternalReference(ref, 5, 1); |
1234 } | 1234 } |
1235 } else { // !compile_followup_inline | 1235 } else { // !compile_followup_inline |
1236 // Call the runtime system to load the interceptor. | 1236 // Call the runtime system to load the interceptor. |
1237 // Check that the maps haven't changed. | 1237 // Check that the maps haven't changed. |
1238 Register holder_reg = | 1238 Register holder_reg = |
1239 CheckPrototypes(object, receiver, interceptor_holder, | 1239 CheckPrototypes(object, receiver, interceptor_holder, |
1240 scratch1, scratch2, name, miss); | 1240 scratch1, scratch2, scratch3, name, miss); |
1241 __ pop(scratch2); // save old return address | 1241 __ pop(scratch2); // save old return address |
1242 PushInterceptorArguments(masm(), receiver, holder_reg, | 1242 PushInterceptorArguments(masm(), receiver, holder_reg, |
1243 name_reg, interceptor_holder); | 1243 name_reg, interceptor_holder); |
1244 __ push(scratch2); // restore old return address | 1244 __ push(scratch2); // restore old return address |
1245 | 1245 |
1246 ExternalReference ref = ExternalReference( | 1246 ExternalReference ref = ExternalReference( |
1247 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); | 1247 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); |
1248 __ TailCallExternalReference(ref, 5, 1); | 1248 __ TailCallExternalReference(ref, 5, 1); |
1249 } | 1249 } |
1250 } | 1250 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1305 | 1305 |
1306 // Get the receiver from the stack. | 1306 // Get the receiver from the stack. |
1307 const int argc = arguments().immediate(); | 1307 const int argc = arguments().immediate(); |
1308 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1308 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1309 | 1309 |
1310 // Check that the receiver isn't a smi. | 1310 // Check that the receiver isn't a smi. |
1311 __ test(edx, Immediate(kSmiTagMask)); | 1311 __ test(edx, Immediate(kSmiTagMask)); |
1312 __ j(zero, &miss, not_taken); | 1312 __ j(zero, &miss, not_taken); |
1313 | 1313 |
1314 // Do the right check and compute the holder register. | 1314 // Do the right check and compute the holder register. |
1315 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, | 1315 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi, |
1316 name, &miss, edi); | 1316 name, &miss); |
1317 | 1317 |
1318 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); | 1318 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); |
1319 | 1319 |
1320 // Check that the function really is a function. | 1320 // Check that the function really is a function. |
1321 __ test(edi, Immediate(kSmiTagMask)); | 1321 __ test(edi, Immediate(kSmiTagMask)); |
1322 __ j(zero, &miss, not_taken); | 1322 __ j(zero, &miss, not_taken); |
1323 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1323 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
1324 __ j(not_equal, &miss, not_taken); | 1324 __ j(not_equal, &miss, not_taken); |
1325 | 1325 |
1326 // Patch the receiver on the stack with the global proxy if | 1326 // Patch the receiver on the stack with the global proxy if |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1368 // Get the receiver from the stack. | 1368 // Get the receiver from the stack. |
1369 const int argc = arguments().immediate(); | 1369 const int argc = arguments().immediate(); |
1370 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1370 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1371 | 1371 |
1372 // Check that the receiver isn't a smi. | 1372 // Check that the receiver isn't a smi. |
1373 __ test(edx, Immediate(kSmiTagMask)); | 1373 __ test(edx, Immediate(kSmiTagMask)); |
1374 __ j(zero, &miss); | 1374 __ j(zero, &miss); |
1375 | 1375 |
1376 CheckPrototypes(JSObject::cast(object), edx, | 1376 CheckPrototypes(JSObject::cast(object), edx, |
1377 holder, ebx, | 1377 holder, ebx, |
1378 eax, name, &miss, edi); | 1378 eax, edi, name, &miss); |
1379 | 1379 |
1380 if (argc == 0) { | 1380 if (argc == 0) { |
1381 // Noop, return the length. | 1381 // Noop, return the length. |
1382 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); | 1382 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); |
1383 __ ret((argc + 1) * kPointerSize); | 1383 __ ret((argc + 1) * kPointerSize); |
1384 } else { | 1384 } else { |
1385 // Get the elements array of the object. | 1385 // Get the elements array of the object. |
1386 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); | 1386 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); |
1387 | 1387 |
1388 // Check that the elements are in fast mode (not dictionary). | 1388 // Check that the elements are in fast mode (not dictionary). |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1514 | 1514 |
1515 // Get the receiver from the stack. | 1515 // Get the receiver from the stack. |
1516 const int argc = arguments().immediate(); | 1516 const int argc = arguments().immediate(); |
1517 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1517 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1518 | 1518 |
1519 // Check that the receiver isn't a smi. | 1519 // Check that the receiver isn't a smi. |
1520 __ test(edx, Immediate(kSmiTagMask)); | 1520 __ test(edx, Immediate(kSmiTagMask)); |
1521 __ j(zero, &miss); | 1521 __ j(zero, &miss); |
1522 CheckPrototypes(JSObject::cast(object), edx, | 1522 CheckPrototypes(JSObject::cast(object), edx, |
1523 holder, ebx, | 1523 holder, ebx, |
1524 eax, name, &miss, edi); | 1524 eax, edi, name, &miss); |
1525 | 1525 |
1526 // Get the elements array of the object. | 1526 // Get the elements array of the object. |
1527 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); | 1527 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); |
1528 | 1528 |
1529 // Check that the elements are in fast mode (not dictionary). | 1529 // Check that the elements are in fast mode (not dictionary). |
1530 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 1530 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
1531 Immediate(Factory::fixed_array_map())); | 1531 Immediate(Factory::fixed_array_map())); |
1532 __ j(not_equal, &miss); | 1532 __ j(not_equal, &miss); |
1533 | 1533 |
1534 // Get the array's length into ecx and calculate new length. | 1534 // Get the array's length into ecx and calculate new length. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1589 | 1589 |
1590 Label miss; | 1590 Label miss; |
1591 Label index_out_of_range; | 1591 Label index_out_of_range; |
1592 GenerateNameCheck(name, &miss); | 1592 GenerateNameCheck(name, &miss); |
1593 | 1593 |
1594 // Check that the maps starting from the prototype haven't changed. | 1594 // Check that the maps starting from the prototype haven't changed. |
1595 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1595 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
1596 Context::STRING_FUNCTION_INDEX, | 1596 Context::STRING_FUNCTION_INDEX, |
1597 eax); | 1597 eax); |
1598 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 1598 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
1599 ebx, edx, name, &miss, edi); | 1599 ebx, edx, edi, name, &miss); |
1600 | 1600 |
1601 Register receiver = ebx; | 1601 Register receiver = ebx; |
1602 Register index = edi; | 1602 Register index = edi; |
1603 Register scratch = edx; | 1603 Register scratch = edx; |
1604 Register result = eax; | 1604 Register result = eax; |
1605 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); | 1605 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); |
1606 if (argc > 0) { | 1606 if (argc > 0) { |
1607 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); | 1607 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); |
1608 } else { | 1608 } else { |
1609 __ Set(index, Immediate(Factory::undefined_value())); | 1609 __ Set(index, Immediate(Factory::undefined_value())); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1654 Label miss; | 1654 Label miss; |
1655 Label index_out_of_range; | 1655 Label index_out_of_range; |
1656 | 1656 |
1657 GenerateNameCheck(name, &miss); | 1657 GenerateNameCheck(name, &miss); |
1658 | 1658 |
1659 // Check that the maps starting from the prototype haven't changed. | 1659 // Check that the maps starting from the prototype haven't changed. |
1660 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1660 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
1661 Context::STRING_FUNCTION_INDEX, | 1661 Context::STRING_FUNCTION_INDEX, |
1662 eax); | 1662 eax); |
1663 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 1663 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
1664 ebx, edx, name, &miss, edi); | 1664 ebx, edx, edi, name, &miss); |
1665 | 1665 |
1666 Register receiver = eax; | 1666 Register receiver = eax; |
1667 Register index = edi; | 1667 Register index = edi; |
1668 Register scratch1 = ebx; | 1668 Register scratch1 = ebx; |
1669 Register scratch2 = edx; | 1669 Register scratch2 = edx; |
1670 Register result = eax; | 1670 Register result = eax; |
1671 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); | 1671 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); |
1672 if (argc > 0) { | 1672 if (argc > 0) { |
1673 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); | 1673 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); |
1674 } else { | 1674 } else { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1759 JSObject::cast(object), holder); | 1759 JSObject::cast(object), holder); |
1760 } | 1760 } |
1761 | 1761 |
1762 if (depth != kInvalidProtoDepth) { | 1762 if (depth != kInvalidProtoDepth) { |
1763 __ IncrementCounter(&Counters::call_const_fast_api, 1); | 1763 __ IncrementCounter(&Counters::call_const_fast_api, 1); |
1764 ReserveSpaceForFastApiCall(masm(), eax); | 1764 ReserveSpaceForFastApiCall(masm(), eax); |
1765 } | 1765 } |
1766 | 1766 |
1767 // Check that the maps haven't changed. | 1767 // Check that the maps haven't changed. |
1768 CheckPrototypes(JSObject::cast(object), edx, holder, | 1768 CheckPrototypes(JSObject::cast(object), edx, holder, |
1769 ebx, eax, name, depth, &miss, edi); | 1769 ebx, eax, edi, name, depth, &miss); |
1770 | 1770 |
1771 // Patch the receiver on the stack with the global proxy if | 1771 // Patch the receiver on the stack with the global proxy if |
1772 // necessary. | 1772 // necessary. |
1773 if (object->IsGlobalObject()) { | 1773 if (object->IsGlobalObject()) { |
1774 ASSERT(depth == kInvalidProtoDepth); | 1774 ASSERT(depth == kInvalidProtoDepth); |
1775 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 1775 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
1776 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 1776 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
1777 } | 1777 } |
1778 break; | 1778 break; |
1779 | 1779 |
1780 case STRING_CHECK: | 1780 case STRING_CHECK: |
1781 if (!function->IsBuiltin()) { | 1781 if (!function->IsBuiltin()) { |
1782 // Calling non-builtins with a value as receiver requires boxing. | 1782 // Calling non-builtins with a value as receiver requires boxing. |
1783 __ jmp(&miss); | 1783 __ jmp(&miss); |
1784 } else { | 1784 } else { |
1785 // Check that the object is a string or a symbol. | 1785 // Check that the object is a string or a symbol. |
1786 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); | 1786 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); |
1787 __ j(above_equal, &miss, not_taken); | 1787 __ j(above_equal, &miss, not_taken); |
1788 // Check that the maps starting from the prototype haven't changed. | 1788 // Check that the maps starting from the prototype haven't changed. |
1789 GenerateDirectLoadGlobalFunctionPrototype( | 1789 GenerateDirectLoadGlobalFunctionPrototype( |
1790 masm(), Context::STRING_FUNCTION_INDEX, eax); | 1790 masm(), Context::STRING_FUNCTION_INDEX, eax); |
1791 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 1791 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
1792 ebx, edx, name, &miss, edi); | 1792 ebx, edx, edi, name, &miss); |
1793 } | 1793 } |
1794 break; | 1794 break; |
1795 | 1795 |
1796 case NUMBER_CHECK: { | 1796 case NUMBER_CHECK: { |
1797 if (!function->IsBuiltin()) { | 1797 if (!function->IsBuiltin()) { |
1798 // Calling non-builtins with a value as receiver requires boxing. | 1798 // Calling non-builtins with a value as receiver requires boxing. |
1799 __ jmp(&miss); | 1799 __ jmp(&miss); |
1800 } else { | 1800 } else { |
1801 Label fast; | 1801 Label fast; |
1802 // Check that the object is a smi or a heap number. | 1802 // Check that the object is a smi or a heap number. |
1803 __ test(edx, Immediate(kSmiTagMask)); | 1803 __ test(edx, Immediate(kSmiTagMask)); |
1804 __ j(zero, &fast, taken); | 1804 __ j(zero, &fast, taken); |
1805 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); | 1805 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); |
1806 __ j(not_equal, &miss, not_taken); | 1806 __ j(not_equal, &miss, not_taken); |
1807 __ bind(&fast); | 1807 __ bind(&fast); |
1808 // Check that the maps starting from the prototype haven't changed. | 1808 // Check that the maps starting from the prototype haven't changed. |
1809 GenerateDirectLoadGlobalFunctionPrototype( | 1809 GenerateDirectLoadGlobalFunctionPrototype( |
1810 masm(), Context::NUMBER_FUNCTION_INDEX, eax); | 1810 masm(), Context::NUMBER_FUNCTION_INDEX, eax); |
1811 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 1811 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
1812 ebx, edx, name, &miss, edi); | 1812 ebx, edx, edi, name, &miss); |
1813 } | 1813 } |
1814 break; | 1814 break; |
1815 } | 1815 } |
1816 | 1816 |
1817 case BOOLEAN_CHECK: { | 1817 case BOOLEAN_CHECK: { |
1818 if (!function->IsBuiltin()) { | 1818 if (!function->IsBuiltin()) { |
1819 // Calling non-builtins with a value as receiver requires boxing. | 1819 // Calling non-builtins with a value as receiver requires boxing. |
1820 __ jmp(&miss); | 1820 __ jmp(&miss); |
1821 } else { | 1821 } else { |
1822 Label fast; | 1822 Label fast; |
1823 // Check that the object is a boolean. | 1823 // Check that the object is a boolean. |
1824 __ cmp(edx, Factory::true_value()); | 1824 __ cmp(edx, Factory::true_value()); |
1825 __ j(equal, &fast, taken); | 1825 __ j(equal, &fast, taken); |
1826 __ cmp(edx, Factory::false_value()); | 1826 __ cmp(edx, Factory::false_value()); |
1827 __ j(not_equal, &miss, not_taken); | 1827 __ j(not_equal, &miss, not_taken); |
1828 __ bind(&fast); | 1828 __ bind(&fast); |
1829 // Check that the maps starting from the prototype haven't changed. | 1829 // Check that the maps starting from the prototype haven't changed. |
1830 GenerateDirectLoadGlobalFunctionPrototype( | 1830 GenerateDirectLoadGlobalFunctionPrototype( |
1831 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax); | 1831 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax); |
1832 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 1832 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
1833 ebx, edx, name, &miss, edi); | 1833 ebx, edx, edi, name, &miss); |
1834 } | 1834 } |
1835 break; | 1835 break; |
1836 } | 1836 } |
1837 | 1837 |
1838 default: | 1838 default: |
1839 UNREACHABLE(); | 1839 UNREACHABLE(); |
1840 } | 1840 } |
1841 | 1841 |
1842 if (depth != kInvalidProtoDepth) { | 1842 if (depth != kInvalidProtoDepth) { |
1843 GenerateFastApiCall(masm(), optimization, argc); | 1843 GenerateFastApiCall(masm(), optimization, argc); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1883 | 1883 |
1884 CallInterceptorCompiler compiler(this, arguments(), ecx); | 1884 CallInterceptorCompiler compiler(this, arguments(), ecx); |
1885 compiler.Compile(masm(), | 1885 compiler.Compile(masm(), |
1886 object, | 1886 object, |
1887 holder, | 1887 holder, |
1888 name, | 1888 name, |
1889 &lookup, | 1889 &lookup, |
1890 edx, | 1890 edx, |
1891 ebx, | 1891 ebx, |
1892 edi, | 1892 edi, |
| 1893 eax, |
1893 &miss); | 1894 &miss); |
1894 | 1895 |
1895 // Restore receiver. | 1896 // Restore receiver. |
1896 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1897 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1897 | 1898 |
1898 // Check that the function really is a function. | 1899 // Check that the function really is a function. |
1899 __ test(eax, Immediate(kSmiTagMask)); | 1900 __ test(eax, Immediate(kSmiTagMask)); |
1900 __ j(zero, &miss, not_taken); | 1901 __ j(zero, &miss, not_taken); |
1901 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); | 1902 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
1902 __ j(not_equal, &miss, not_taken); | 1903 __ j(not_equal, &miss, not_taken); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1945 | 1946 |
1946 // If the object is the holder then we know that it's a global | 1947 // If the object is the holder then we know that it's a global |
1947 // object which can only happen for contextual calls. In this case, | 1948 // object which can only happen for contextual calls. In this case, |
1948 // the receiver cannot be a smi. | 1949 // the receiver cannot be a smi. |
1949 if (object != holder) { | 1950 if (object != holder) { |
1950 __ test(edx, Immediate(kSmiTagMask)); | 1951 __ test(edx, Immediate(kSmiTagMask)); |
1951 __ j(zero, &miss, not_taken); | 1952 __ j(zero, &miss, not_taken); |
1952 } | 1953 } |
1953 | 1954 |
1954 // Check that the maps haven't changed. | 1955 // Check that the maps haven't changed. |
1955 CheckPrototypes(object, edx, holder, ebx, eax, name, &miss, edi); | 1956 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, &miss); |
1956 | 1957 |
1957 // Get the value from the cell. | 1958 // Get the value from the cell. |
1958 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 1959 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
1959 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); | 1960 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); |
1960 | 1961 |
1961 // Check that the cell contains the same function. | 1962 // Check that the cell contains the same function. |
1962 if (Heap::InNewSpace(function)) { | 1963 if (Heap::InNewSpace(function)) { |
1963 // We can't embed a pointer to a function in new space so we have | 1964 // We can't embed a pointer to a function in new space so we have |
1964 // to verify that the shared function info is unchanged. This has | 1965 // to verify that the shared function info is unchanged. This has |
1965 // the nice side effect that multiple closures based on the same | 1966 // the nice side effect that multiple closures based on the same |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2221 | 2222 |
2222 // Check that the receiver isn't a smi. | 2223 // Check that the receiver isn't a smi. |
2223 __ test(eax, Immediate(kSmiTagMask)); | 2224 __ test(eax, Immediate(kSmiTagMask)); |
2224 __ j(zero, &miss, not_taken); | 2225 __ j(zero, &miss, not_taken); |
2225 | 2226 |
2226 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); | 2227 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); |
2227 | 2228 |
2228 // Check the maps of the full prototype chain. Also check that | 2229 // Check the maps of the full prototype chain. Also check that |
2229 // global property cells up to (but not including) the last object | 2230 // global property cells up to (but not including) the last object |
2230 // in the prototype chain are empty. | 2231 // in the prototype chain are empty. |
2231 CheckPrototypes(object, eax, last, ebx, edx, name, &miss); | 2232 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); |
2232 | 2233 |
2233 // If the last object in the prototype chain is a global object, | 2234 // If the last object in the prototype chain is a global object, |
2234 // check that the global property cell is empty. | 2235 // check that the global property cell is empty. |
2235 if (last->IsGlobalObject()) { | 2236 if (last->IsGlobalObject()) { |
2236 Object* cell = GenerateCheckPropertyCell(masm(), | 2237 Object* cell = GenerateCheckPropertyCell(masm(), |
2237 GlobalObject::cast(last), | 2238 GlobalObject::cast(last), |
2238 name, | 2239 name, |
2239 edx, | 2240 edx, |
2240 &miss); | 2241 &miss); |
2241 if (cell->IsFailure()) return cell; | 2242 if (cell->IsFailure()) return cell; |
(...skipping 16 matching lines...) Expand all Loading... |
2258 JSObject* holder, | 2259 JSObject* holder, |
2259 int index, | 2260 int index, |
2260 String* name) { | 2261 String* name) { |
2261 // ----------- S t a t e ------------- | 2262 // ----------- S t a t e ------------- |
2262 // -- eax : receiver | 2263 // -- eax : receiver |
2263 // -- ecx : name | 2264 // -- ecx : name |
2264 // -- esp[0] : return address | 2265 // -- esp[0] : return address |
2265 // ----------------------------------- | 2266 // ----------------------------------- |
2266 Label miss; | 2267 Label miss; |
2267 | 2268 |
2268 GenerateLoadField(object, holder, eax, ebx, edx, index, name, &miss); | 2269 GenerateLoadField(object, holder, eax, ebx, edx, edi, index, name, &miss); |
2269 __ bind(&miss); | 2270 __ bind(&miss); |
2270 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2271 GenerateLoadMiss(masm(), Code::LOAD_IC); |
2271 | 2272 |
2272 // Return the generated code. | 2273 // Return the generated code. |
2273 return GetCode(FIELD, name); | 2274 return GetCode(FIELD, name); |
2274 } | 2275 } |
2275 | 2276 |
2276 | 2277 |
2277 Object* LoadStubCompiler::CompileLoadCallback(String* name, | 2278 Object* LoadStubCompiler::CompileLoadCallback(String* name, |
2278 JSObject* object, | 2279 JSObject* object, |
2279 JSObject* holder, | 2280 JSObject* holder, |
2280 AccessorInfo* callback) { | 2281 AccessorInfo* callback) { |
2281 // ----------- S t a t e ------------- | 2282 // ----------- S t a t e ------------- |
2282 // -- eax : receiver | 2283 // -- eax : receiver |
2283 // -- ecx : name | 2284 // -- ecx : name |
2284 // -- esp[0] : return address | 2285 // -- esp[0] : return address |
2285 // ----------------------------------- | 2286 // ----------------------------------- |
2286 Label miss; | 2287 Label miss; |
2287 | 2288 |
2288 Failure* failure = Failure::InternalError(); | 2289 Failure* failure = Failure::InternalError(); |
2289 bool success = GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, | 2290 bool success = GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, edi, |
2290 callback, name, &miss, &failure); | 2291 callback, name, &miss, &failure); |
2291 if (!success) return failure; | 2292 if (!success) return failure; |
2292 | 2293 |
2293 __ bind(&miss); | 2294 __ bind(&miss); |
2294 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2295 GenerateLoadMiss(masm(), Code::LOAD_IC); |
2295 | 2296 |
2296 // Return the generated code. | 2297 // Return the generated code. |
2297 return GetCode(CALLBACKS, name); | 2298 return GetCode(CALLBACKS, name); |
2298 } | 2299 } |
2299 | 2300 |
2300 | 2301 |
2301 Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, | 2302 Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, |
2302 JSObject* holder, | 2303 JSObject* holder, |
2303 Object* value, | 2304 Object* value, |
2304 String* name) { | 2305 String* name) { |
2305 // ----------- S t a t e ------------- | 2306 // ----------- S t a t e ------------- |
2306 // -- eax : receiver | 2307 // -- eax : receiver |
2307 // -- ecx : name | 2308 // -- ecx : name |
2308 // -- esp[0] : return address | 2309 // -- esp[0] : return address |
2309 // ----------------------------------- | 2310 // ----------------------------------- |
2310 Label miss; | 2311 Label miss; |
2311 | 2312 |
2312 GenerateLoadConstant(object, holder, eax, ebx, edx, value, name, &miss); | 2313 GenerateLoadConstant(object, holder, eax, ebx, edx, edi, value, name, &miss); |
2313 __ bind(&miss); | 2314 __ bind(&miss); |
2314 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2315 GenerateLoadMiss(masm(), Code::LOAD_IC); |
2315 | 2316 |
2316 // Return the generated code. | 2317 // Return the generated code. |
2317 return GetCode(CONSTANT_FUNCTION, name); | 2318 return GetCode(CONSTANT_FUNCTION, name); |
2318 } | 2319 } |
2319 | 2320 |
2320 | 2321 |
2321 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 2322 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
2322 JSObject* holder, | 2323 JSObject* holder, |
(...skipping 10 matching lines...) Expand all Loading... |
2333 | 2334 |
2334 // TODO(368): Compile in the whole chain: all the interceptors in | 2335 // TODO(368): Compile in the whole chain: all the interceptors in |
2335 // prototypes and ultimate answer. | 2336 // prototypes and ultimate answer. |
2336 GenerateLoadInterceptor(receiver, | 2337 GenerateLoadInterceptor(receiver, |
2337 holder, | 2338 holder, |
2338 &lookup, | 2339 &lookup, |
2339 eax, | 2340 eax, |
2340 ecx, | 2341 ecx, |
2341 edx, | 2342 edx, |
2342 ebx, | 2343 ebx, |
| 2344 edi, |
2343 name, | 2345 name, |
2344 &miss); | 2346 &miss); |
2345 | 2347 |
2346 __ bind(&miss); | 2348 __ bind(&miss); |
2347 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2349 GenerateLoadMiss(masm(), Code::LOAD_IC); |
2348 | 2350 |
2349 // Return the generated code. | 2351 // Return the generated code. |
2350 return GetCode(INTERCEPTOR, name); | 2352 return GetCode(INTERCEPTOR, name); |
2351 } | 2353 } |
2352 | 2354 |
(...skipping 12 matching lines...) Expand all Loading... |
2365 | 2367 |
2366 // If the object is the holder then we know that it's a global | 2368 // If the object is the holder then we know that it's a global |
2367 // object which can only happen for contextual loads. In this case, | 2369 // object which can only happen for contextual loads. In this case, |
2368 // the receiver cannot be a smi. | 2370 // the receiver cannot be a smi. |
2369 if (object != holder) { | 2371 if (object != holder) { |
2370 __ test(eax, Immediate(kSmiTagMask)); | 2372 __ test(eax, Immediate(kSmiTagMask)); |
2371 __ j(zero, &miss, not_taken); | 2373 __ j(zero, &miss, not_taken); |
2372 } | 2374 } |
2373 | 2375 |
2374 // Check that the maps haven't changed. | 2376 // Check that the maps haven't changed. |
2375 CheckPrototypes(object, eax, holder, ebx, edx, name, &miss, edi); | 2377 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); |
2376 | 2378 |
2377 // Get the value from the cell. | 2379 // Get the value from the cell. |
2378 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 2380 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
2379 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); | 2381 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); |
2380 | 2382 |
2381 // Check for deleted property if property can actually be deleted. | 2383 // Check for deleted property if property can actually be deleted. |
2382 if (!is_dont_delete) { | 2384 if (!is_dont_delete) { |
2383 __ cmp(ebx, Factory::the_hole_value()); | 2385 __ cmp(ebx, Factory::the_hole_value()); |
2384 __ j(equal, &miss, not_taken); | 2386 __ j(equal, &miss, not_taken); |
2385 } else if (FLAG_debug_code) { | 2387 } else if (FLAG_debug_code) { |
(...skipping 24 matching lines...) Expand all Loading... |
2410 // -- esp[0] : return address | 2412 // -- esp[0] : return address |
2411 // ----------------------------------- | 2413 // ----------------------------------- |
2412 Label miss; | 2414 Label miss; |
2413 | 2415 |
2414 __ IncrementCounter(&Counters::keyed_load_field, 1); | 2416 __ IncrementCounter(&Counters::keyed_load_field, 1); |
2415 | 2417 |
2416 // Check that the name has not changed. | 2418 // Check that the name has not changed. |
2417 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2419 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
2418 __ j(not_equal, &miss, not_taken); | 2420 __ j(not_equal, &miss, not_taken); |
2419 | 2421 |
2420 GenerateLoadField(receiver, holder, edx, ebx, ecx, index, name, &miss); | 2422 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); |
2421 | 2423 |
2422 __ bind(&miss); | 2424 __ bind(&miss); |
2423 __ DecrementCounter(&Counters::keyed_load_field, 1); | 2425 __ DecrementCounter(&Counters::keyed_load_field, 1); |
2424 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2426 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
2425 | 2427 |
2426 // Return the generated code. | 2428 // Return the generated code. |
2427 return GetCode(FIELD, name); | 2429 return GetCode(FIELD, name); |
2428 } | 2430 } |
2429 | 2431 |
2430 | 2432 |
2431 Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, | 2433 Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, |
2432 JSObject* receiver, | 2434 JSObject* receiver, |
2433 JSObject* holder, | 2435 JSObject* holder, |
2434 AccessorInfo* callback) { | 2436 AccessorInfo* callback) { |
2435 // ----------- S t a t e ------------- | 2437 // ----------- S t a t e ------------- |
2436 // -- eax : key | 2438 // -- eax : key |
2437 // -- edx : receiver | 2439 // -- edx : receiver |
2438 // -- esp[0] : return address | 2440 // -- esp[0] : return address |
2439 // ----------------------------------- | 2441 // ----------------------------------- |
2440 Label miss; | 2442 Label miss; |
2441 | 2443 |
2442 __ IncrementCounter(&Counters::keyed_load_callback, 1); | 2444 __ IncrementCounter(&Counters::keyed_load_callback, 1); |
2443 | 2445 |
2444 // Check that the name has not changed. | 2446 // Check that the name has not changed. |
2445 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2447 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
2446 __ j(not_equal, &miss, not_taken); | 2448 __ j(not_equal, &miss, not_taken); |
2447 | 2449 |
2448 Failure* failure = Failure::InternalError(); | 2450 Failure* failure = Failure::InternalError(); |
2449 bool success = GenerateLoadCallback(receiver, holder, edx, eax, ebx, ecx, | 2451 bool success = GenerateLoadCallback(receiver, holder, edx, eax, ebx, ecx, edi, |
2450 callback, name, &miss, &failure); | 2452 callback, name, &miss, &failure); |
2451 if (!success) return failure; | 2453 if (!success) return failure; |
2452 | 2454 |
2453 __ bind(&miss); | 2455 __ bind(&miss); |
2454 __ DecrementCounter(&Counters::keyed_load_callback, 1); | 2456 __ DecrementCounter(&Counters::keyed_load_callback, 1); |
2455 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2457 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
2456 | 2458 |
2457 // Return the generated code. | 2459 // Return the generated code. |
2458 return GetCode(CALLBACKS, name); | 2460 return GetCode(CALLBACKS, name); |
2459 } | 2461 } |
2460 | 2462 |
2461 | 2463 |
2462 Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, | 2464 Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, |
2463 JSObject* receiver, | 2465 JSObject* receiver, |
2464 JSObject* holder, | 2466 JSObject* holder, |
2465 Object* value) { | 2467 Object* value) { |
2466 // ----------- S t a t e ------------- | 2468 // ----------- S t a t e ------------- |
2467 // -- eax : key | 2469 // -- eax : key |
2468 // -- edx : receiver | 2470 // -- edx : receiver |
2469 // -- esp[0] : return address | 2471 // -- esp[0] : return address |
2470 // ----------------------------------- | 2472 // ----------------------------------- |
2471 Label miss; | 2473 Label miss; |
2472 | 2474 |
2473 __ IncrementCounter(&Counters::keyed_load_constant_function, 1); | 2475 __ IncrementCounter(&Counters::keyed_load_constant_function, 1); |
2474 | 2476 |
2475 // Check that the name has not changed. | 2477 // Check that the name has not changed. |
2476 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2478 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
2477 __ j(not_equal, &miss, not_taken); | 2479 __ j(not_equal, &miss, not_taken); |
2478 | 2480 |
2479 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, | 2481 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, |
2480 value, name, &miss); | 2482 value, name, &miss); |
2481 __ bind(&miss); | 2483 __ bind(&miss); |
2482 __ DecrementCounter(&Counters::keyed_load_constant_function, 1); | 2484 __ DecrementCounter(&Counters::keyed_load_constant_function, 1); |
2483 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2485 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
2484 | 2486 |
2485 // Return the generated code. | 2487 // Return the generated code. |
2486 return GetCode(CONSTANT_FUNCTION, name); | 2488 return GetCode(CONSTANT_FUNCTION, name); |
2487 } | 2489 } |
2488 | 2490 |
2489 | 2491 |
(...skipping 15 matching lines...) Expand all Loading... |
2505 | 2507 |
2506 LookupResult lookup; | 2508 LookupResult lookup; |
2507 LookupPostInterceptor(holder, name, &lookup); | 2509 LookupPostInterceptor(holder, name, &lookup); |
2508 GenerateLoadInterceptor(receiver, | 2510 GenerateLoadInterceptor(receiver, |
2509 holder, | 2511 holder, |
2510 &lookup, | 2512 &lookup, |
2511 edx, | 2513 edx, |
2512 eax, | 2514 eax, |
2513 ecx, | 2515 ecx, |
2514 ebx, | 2516 ebx, |
| 2517 edi, |
2515 name, | 2518 name, |
2516 &miss); | 2519 &miss); |
2517 __ bind(&miss); | 2520 __ bind(&miss); |
2518 __ DecrementCounter(&Counters::keyed_load_interceptor, 1); | 2521 __ DecrementCounter(&Counters::keyed_load_interceptor, 1); |
2519 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2522 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
2520 | 2523 |
2521 // Return the generated code. | 2524 // Return the generated code. |
2522 return GetCode(INTERCEPTOR, name); | 2525 return GetCode(INTERCEPTOR, name); |
2523 } | 2526 } |
2524 | 2527 |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2732 // Return the generated code. | 2735 // Return the generated code. |
2733 return GetCode(); | 2736 return GetCode(); |
2734 } | 2737 } |
2735 | 2738 |
2736 | 2739 |
2737 #undef __ | 2740 #undef __ |
2738 | 2741 |
2739 } } // namespace v8::internal | 2742 } } // namespace v8::internal |
2740 | 2743 |
2741 #endif // V8_TARGET_ARCH_IA32 | 2744 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |