| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 | 75 |
| 76 __ bind(&miss); | 76 __ bind(&miss); |
| 77 } | 77 } |
| 78 | 78 |
| 79 | 79 |
| 80 // Helper function used to check that the dictionary doesn't contain | 80 // Helper function used to check that the dictionary doesn't contain |
| 81 // the property. This function may return false negatives, so miss_label | 81 // the property. This function may return false negatives, so miss_label |
| 82 // must always call a backup property check that is complete. | 82 // must always call a backup property check that is complete. |
| 83 // This function is safe to call if the receiver has fast properties. | 83 // This function is safe to call if the receiver has fast properties. |
| 84 // Name must be a symbol and receiver must be a heap object. | 84 // Name must be a symbol and receiver must be a heap object. |
| 85 MUST_USE_RESULT static MaybeObject* GenerateDictionaryNegativeLookup( | 85 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, |
| 86 Label* miss_label, |
| 87 Register receiver, |
| 88 Handle<String> name, |
| 89 Register r0, |
| 90 Register r1) { |
| 91 ASSERT(name->IsSymbol()); |
| 92 Counters* counters = masm->isolate()->counters(); |
| 93 __ IncrementCounter(counters->negative_lookups(), 1); |
| 94 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
| 95 |
| 96 __ movq(r0, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 97 |
| 98 const int kInterceptorOrAccessCheckNeededMask = |
| 99 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
| 100 |
| 101 // Bail out if the receiver has a named interceptor or requires access checks. |
| 102 __ testb(FieldOperand(r0, Map::kBitFieldOffset), |
| 103 Immediate(kInterceptorOrAccessCheckNeededMask)); |
| 104 __ j(not_zero, miss_label); |
| 105 |
| 106 // Check that receiver is a JSObject. |
| 107 __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); |
| 108 __ j(below, miss_label); |
| 109 |
| 110 // Load properties array. |
| 111 Register properties = r0; |
| 112 __ movq(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 113 |
| 114 // Check that the properties array is a dictionary. |
| 115 __ CompareRoot(FieldOperand(properties, HeapObject::kMapOffset), |
| 116 Heap::kHashTableMapRootIndex); |
| 117 __ j(not_equal, miss_label); |
| 118 |
| 119 Label done; |
| 120 StringDictionaryLookupStub::GenerateNegativeLookup(masm, |
| 121 miss_label, |
| 122 &done, |
| 123 properties, |
| 124 name, |
| 125 r1); |
| 126 __ bind(&done); |
| 127 __ DecrementCounter(counters->negative_lookups_miss(), 1); |
| 128 } |
| 129 |
| 130 |
| 131 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 132 // handlified. |
| 133 MUST_USE_RESULT static MaybeObject* TryGenerateDictionaryNegativeLookup( |
| 86 MacroAssembler* masm, | 134 MacroAssembler* masm, |
| 87 Label* miss_label, | 135 Label* miss_label, |
| 88 Register receiver, | 136 Register receiver, |
| 89 String* name, | 137 String* name, |
| 90 Register r0, | 138 Register r0, |
| 91 Register r1) { | 139 Register r1) { |
| 92 ASSERT(name->IsSymbol()); | 140 ASSERT(name->IsSymbol()); |
| 93 Counters* counters = masm->isolate()->counters(); | 141 Counters* counters = masm->isolate()->counters(); |
| 94 __ IncrementCounter(counters->negative_lookups(), 1); | 142 __ IncrementCounter(counters->negative_lookups(), 1); |
| 95 __ IncrementCounter(counters->negative_lookups_miss(), 1); | 143 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 111 // Load properties array. | 159 // Load properties array. |
| 112 Register properties = r0; | 160 Register properties = r0; |
| 113 __ movq(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 161 __ movq(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 114 | 162 |
| 115 // Check that the properties array is a dictionary. | 163 // Check that the properties array is a dictionary. |
| 116 __ CompareRoot(FieldOperand(properties, HeapObject::kMapOffset), | 164 __ CompareRoot(FieldOperand(properties, HeapObject::kMapOffset), |
| 117 Heap::kHashTableMapRootIndex); | 165 Heap::kHashTableMapRootIndex); |
| 118 __ j(not_equal, miss_label); | 166 __ j(not_equal, miss_label); |
| 119 | 167 |
| 120 Label done; | 168 Label done; |
| 121 MaybeObject* result = StringDictionaryLookupStub::GenerateNegativeLookup( | 169 MaybeObject* result = StringDictionaryLookupStub::TryGenerateNegativeLookup( |
| 122 masm, | 170 masm, |
| 123 miss_label, | 171 miss_label, |
| 124 &done, | 172 &done, |
| 125 properties, | 173 properties, |
| 126 name, | 174 name, |
| 127 r1); | 175 r1); |
| 128 if (result->IsFailure()) return result; | 176 if (result->IsFailure()) return result; |
| 129 | 177 |
| 130 __ bind(&done); | 178 __ bind(&done); |
| 131 __ DecrementCounter(counters->negative_lookups_miss(), 1); | 179 __ DecrementCounter(counters->negative_lookups_miss(), 1); |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 __ TryGetFunctionPrototype(receiver, result, miss_label); | 353 __ TryGetFunctionPrototype(receiver, result, miss_label); |
| 306 if (!result.is(rax)) __ movq(rax, result); | 354 if (!result.is(rax)) __ movq(rax, result); |
| 307 __ ret(0); | 355 __ ret(0); |
| 308 } | 356 } |
| 309 | 357 |
| 310 | 358 |
| 311 // Load a fast property out of a holder object (src). In-object properties | 359 // Load a fast property out of a holder object (src). In-object properties |
| 312 // are loaded directly otherwise the property is loaded from the properties | 360 // are loaded directly otherwise the property is loaded from the properties |
| 313 // fixed array. | 361 // fixed array. |
| 314 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | 362 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, |
| 315 Register dst, Register src, | 363 Register dst, |
| 316 JSObject* holder, int index) { | 364 Register src, |
| 365 Handle<JSObject> holder, |
| 366 int index) { |
| 317 // Adjust for the number of properties stored in the holder. | 367 // Adjust for the number of properties stored in the holder. |
| 318 index -= holder->map()->inobject_properties(); | 368 index -= holder->map()->inobject_properties(); |
| 319 if (index < 0) { | 369 if (index < 0) { |
| 320 // Get the property straight out of the holder. | 370 // Get the property straight out of the holder. |
| 321 int offset = holder->map()->instance_size() + (index * kPointerSize); | 371 int offset = holder->map()->instance_size() + (index * kPointerSize); |
| 322 __ movq(dst, FieldOperand(src, offset)); | 372 __ movq(dst, FieldOperand(src, offset)); |
| 323 } else { | 373 } else { |
| 324 // Calculate the offset into the properties array. | 374 // Calculate the offset into the properties array. |
| 325 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 375 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
| 326 __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | 376 __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset)); |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 | 743 |
| 694 StubCompiler* stub_compiler_; | 744 StubCompiler* stub_compiler_; |
| 695 const ParameterCount& arguments_; | 745 const ParameterCount& arguments_; |
| 696 Register name_; | 746 Register name_; |
| 697 Code::ExtraICState extra_ic_state_; | 747 Code::ExtraICState extra_ic_state_; |
| 698 }; | 748 }; |
| 699 | 749 |
| 700 | 750 |
| 701 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { | 751 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { |
| 702 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); | 752 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); |
| 703 Code* code = NULL; | 753 Handle<Code> code = (kind == Code::LOAD_IC) |
| 704 if (kind == Code::LOAD_IC) { | 754 ? masm->isolate()->builtins()->LoadIC_Miss() |
| 705 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss); | 755 : masm->isolate()->builtins()->KeyedLoadIC_Miss(); |
| 706 } else { | 756 __ Jump(code, RelocInfo::CODE_TARGET); |
| 707 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss); | |
| 708 } | |
| 709 | |
| 710 Handle<Code> ic(code); | |
| 711 __ Jump(ic, RelocInfo::CODE_TARGET); | |
| 712 } | 757 } |
| 713 | 758 |
| 714 | 759 |
| 715 void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) { | 760 void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) { |
| 716 Code* code = masm->isolate()->builtins()->builtin( | 761 Code* code = masm->isolate()->builtins()->builtin( |
| 717 Builtins::kKeyedLoadIC_MissForceGeneric); | 762 Builtins::kKeyedLoadIC_MissForceGeneric); |
| 718 Handle<Code> ic(code); | 763 Handle<Code> ic(code); |
| 719 __ Jump(ic, RelocInfo::CODE_TARGET); | 764 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 720 } | 765 } |
| 721 | 766 |
| 722 | 767 |
| 723 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 768 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
| 724 // but may be destroyed if store is successful. | 769 // but may be destroyed if store is successful. |
| 725 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 770 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
| 726 JSObject* object, | 771 Handle<JSObject> object, |
| 727 int index, | 772 int index, |
| 728 Map* transition, | 773 Handle<Map> transition, |
| 729 Register receiver_reg, | 774 Register receiver_reg, |
| 730 Register name_reg, | 775 Register name_reg, |
| 731 Register scratch, | 776 Register scratch, |
| 732 Label* miss_label) { | 777 Label* miss_label) { |
| 733 // Check that the object isn't a smi. | 778 // Check that the object isn't a smi. |
| 734 __ JumpIfSmi(receiver_reg, miss_label); | 779 __ JumpIfSmi(receiver_reg, miss_label); |
| 735 | 780 |
| 736 // Check that the map of the object hasn't changed. | 781 // Check that the map of the object hasn't changed. |
| 737 __ Cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), | 782 __ Cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), |
| 738 Handle<Map>(object->map())); | 783 Handle<Map>(object->map())); |
| 739 __ j(not_equal, miss_label); | 784 __ j(not_equal, miss_label); |
| 740 | 785 |
| 741 // Perform global security token check if needed. | 786 // Perform global security token check if needed. |
| 742 if (object->IsJSGlobalProxy()) { | 787 if (object->IsJSGlobalProxy()) { |
| 743 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); | 788 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); |
| 744 } | 789 } |
| 745 | 790 |
| 746 // Stub never generated for non-global objects that require access | 791 // Stub never generated for non-global objects that require access |
| 747 // checks. | 792 // checks. |
| 748 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 793 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 749 | 794 |
| 750 // Perform map transition for the receiver if necessary. | 795 // Perform map transition for the receiver if necessary. |
| 751 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) { | 796 if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { |
| 752 // The properties must be extended before we can store the value. | 797 // The properties must be extended before we can store the value. |
| 753 // We jump to a runtime call that extends the properties array. | 798 // We jump to a runtime call that extends the properties array. |
| 754 __ pop(scratch); // Return address. | 799 __ pop(scratch); // Return address. |
| 755 __ push(receiver_reg); | 800 __ push(receiver_reg); |
| 756 __ Push(Handle<Map>(transition)); | 801 __ Push(transition); |
| 757 __ push(rax); | 802 __ push(rax); |
| 758 __ push(scratch); | 803 __ push(scratch); |
| 759 __ TailCallExternalReference( | 804 __ TailCallExternalReference( |
| 760 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 805 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
| 761 masm->isolate()), | 806 masm->isolate()), |
| 762 3, | 807 3, |
| 763 1); | 808 1); |
| 764 return; | 809 return; |
| 765 } | 810 } |
| 766 | 811 |
| 767 if (transition != NULL) { | 812 if (!transition.is_null()) { |
| 768 // Update the map of the object; no write barrier updating is | 813 // Update the map of the object; no write barrier updating is |
| 769 // needed because the map is never in new space. | 814 // needed because the map is never in new space. |
| 770 __ Move(FieldOperand(receiver_reg, HeapObject::kMapOffset), | 815 __ Move(FieldOperand(receiver_reg, HeapObject::kMapOffset), transition); |
| 771 Handle<Map>(transition)); | |
| 772 } | 816 } |
| 773 | 817 |
| 774 // Adjust for the number of properties stored in the object. Even in the | 818 // Adjust for the number of properties stored in the object. Even in the |
| 775 // face of a transition we can use the old map here because the size of the | 819 // face of a transition we can use the old map here because the size of the |
| 776 // object and the number of in-object properties is not going to change. | 820 // object and the number of in-object properties is not going to change. |
| 777 index -= object->map()->inobject_properties(); | 821 index -= object->map()->inobject_properties(); |
| 778 | 822 |
| 779 if (index < 0) { | 823 if (index < 0) { |
| 780 // Set the property straight into the object. | 824 // Set the property straight into the object. |
| 781 int offset = object->map()->instance_size() + (index * kPointerSize); | 825 int offset = object->map()->instance_size() + (index * kPointerSize); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 801 } | 845 } |
| 802 | 846 |
| 803 // Return the value (register rax). | 847 // Return the value (register rax). |
| 804 __ ret(0); | 848 __ ret(0); |
| 805 } | 849 } |
| 806 | 850 |
| 807 | 851 |
| 808 // Generate code to check that a global property cell is empty. Create | 852 // Generate code to check that a global property cell is empty. Create |
| 809 // the property cell at compilation time if no cell exists for the | 853 // the property cell at compilation time if no cell exists for the |
| 810 // property. | 854 // property. |
| 811 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell( | 855 static void GenerateCheckPropertyCell(MacroAssembler* masm, |
| 856 Handle<GlobalObject> global, |
| 857 Handle<String> name, |
| 858 Register scratch, |
| 859 Label* miss) { |
| 860 Handle<JSGlobalPropertyCell> cell = |
| 861 GlobalObject::EnsurePropertyCell(global, name); |
| 862 ASSERT(cell->value()->IsTheHole()); |
| 863 __ Move(scratch, cell); |
| 864 __ Cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
| 865 masm->isolate()->factory()->the_hole_value()); |
| 866 __ j(not_equal, miss); |
| 867 } |
| 868 |
| 869 |
| 870 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 871 // handlified. |
| 872 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell( |
| 812 MacroAssembler* masm, | 873 MacroAssembler* masm, |
| 813 GlobalObject* global, | 874 GlobalObject* global, |
| 814 String* name, | 875 String* name, |
| 815 Register scratch, | 876 Register scratch, |
| 816 Label* miss) { | 877 Label* miss) { |
| 817 Object* probe; | 878 Object* probe; |
| 818 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); | 879 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); |
| 819 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 880 if (!maybe_probe->ToObject(&probe)) return maybe_probe; |
| 820 } | 881 } |
| 821 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); | 882 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); |
| 822 ASSERT(cell->value()->IsTheHole()); | 883 ASSERT(cell->value()->IsTheHole()); |
| 823 __ Move(scratch, Handle<Object>(cell)); | 884 __ Move(scratch, Handle<Object>(cell)); |
| 824 __ Cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), | 885 __ Cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
| 825 masm->isolate()->factory()->the_hole_value()); | 886 masm->isolate()->factory()->the_hole_value()); |
| 826 __ j(not_equal, miss); | 887 __ j(not_equal, miss); |
| 827 return cell; | 888 return cell; |
| 828 } | 889 } |
| 829 | 890 |
| 830 | 891 |
| 892 // Calls GenerateCheckPropertyCell for each global object in the prototype chain |
| 893 // from object to (but not including) holder. |
| 894 static void GenerateCheckPropertyCells(MacroAssembler* masm, |
| 895 Handle<JSObject> object, |
| 896 Handle<JSObject> holder, |
| 897 Handle<String> name, |
| 898 Register scratch, |
| 899 Label* miss) { |
| 900 Handle<JSObject> current = object; |
| 901 while (!current.is_identical_to(holder)) { |
| 902 if (current->IsGlobalObject()) { |
| 903 GenerateCheckPropertyCell(masm, |
| 904 Handle<GlobalObject>::cast(current), |
| 905 name, |
| 906 scratch, |
| 907 miss); |
| 908 } |
| 909 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); |
| 910 } |
| 911 } |
| 912 |
| 913 |
| 914 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 915 // handlified. |
| 916 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCells( |
| 917 MacroAssembler* masm, |
| 918 JSObject* object, |
| 919 JSObject* holder, |
| 920 String* name, |
| 921 Register scratch, |
| 922 Label* miss) { |
| 923 JSObject* current = object; |
| 924 while (current != holder) { |
| 925 if (current->IsGlobalObject()) { |
| 926 // Returns a cell or a failure. |
| 927 MaybeObject* result = TryGenerateCheckPropertyCell( |
| 928 masm, |
| 929 GlobalObject::cast(current), |
| 930 name, |
| 931 scratch, |
| 932 miss); |
| 933 if (result->IsFailure()) return result; |
| 934 } |
| 935 ASSERT(current->IsJSObject()); |
| 936 current = JSObject::cast(current->GetPrototype()); |
| 937 } |
| 938 return NULL; |
| 939 } |
| 940 |
| 941 |
| 831 #undef __ | 942 #undef __ |
| 832 #define __ ACCESS_MASM((masm())) | 943 #define __ ACCESS_MASM((masm())) |
| 833 | 944 |
| 834 | 945 |
| 946 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
| 947 Register object_reg, |
| 948 Handle<JSObject> holder, |
| 949 Register holder_reg, |
| 950 Register scratch1, |
| 951 Register scratch2, |
| 952 Handle<String> name, |
| 953 int save_at_depth, |
| 954 Label* miss) { |
| 955 // Make sure there's no overlap between holder and object registers. |
| 956 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 957 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 958 && !scratch2.is(scratch1)); |
| 959 |
| 960 // Keep track of the current object in register reg. On the first |
| 961 // iteration, reg is an alias for object_reg, on later iterations, |
| 962 // it is an alias for holder_reg. |
| 963 Register reg = object_reg; |
| 964 int depth = 0; |
| 965 |
| 966 if (save_at_depth == depth) { |
| 967 __ movq(Operand(rsp, kPointerSize), object_reg); |
| 968 } |
| 969 |
| 970 // Check the maps in the prototype chain. |
| 971 // Traverse the prototype chain from the object and do map checks. |
| 972 Handle<JSObject> current = object; |
| 973 while (!current.is_identical_to(holder)) { |
| 974 ++depth; |
| 975 |
| 976 // Only global objects and objects that do not require access |
| 977 // checks are allowed in stubs. |
| 978 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); |
| 979 |
| 980 Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); |
| 981 if (!current->HasFastProperties() && |
| 982 !current->IsJSGlobalObject() && |
| 983 !current->IsJSGlobalProxy()) { |
| 984 if (!name->IsSymbol()) { |
| 985 name = factory()->LookupSymbol(name); |
| 986 } |
| 987 ASSERT(current->property_dictionary()->FindEntry(*name) == |
| 988 StringDictionary::kNotFound); |
| 989 |
| 990 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
| 991 scratch1, scratch2); |
| 992 |
| 993 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 994 reg = holder_reg; // From now on the object will be in holder_reg. |
| 995 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 996 } else { |
| 997 bool in_new_space = heap()->InNewSpace(*prototype); |
| 998 Handle<Map> current_map(current->map()); |
| 999 if (in_new_space) { |
| 1000 // Save the map in scratch1 for later. |
| 1001 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1002 __ Cmp(scratch1, current_map); |
| 1003 } else { |
| 1004 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), current_map); |
| 1005 } |
| 1006 // Branch on the result of the map check. |
| 1007 __ j(not_equal, miss); |
| 1008 // Check access rights to the global object. This has to happen after |
| 1009 // the map check so that we know that the object is actually a global |
| 1010 // object. |
| 1011 if (current->IsJSGlobalProxy()) { |
| 1012 __ CheckAccessGlobalProxy(reg, scratch2, miss); |
| 1013 } |
| 1014 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1015 |
| 1016 if (in_new_space) { |
| 1017 // The prototype is in new space; we cannot store a reference to it |
| 1018 // in the code. Load it from the map. |
| 1019 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1020 } else { |
| 1021 // The prototype is in old space; load it directly. |
| 1022 __ Move(reg, prototype); |
| 1023 } |
| 1024 } |
| 1025 |
| 1026 if (save_at_depth == depth) { |
| 1027 __ movq(Operand(rsp, kPointerSize), reg); |
| 1028 } |
| 1029 |
| 1030 // Go to the next object in the prototype chain. |
| 1031 current = prototype; |
| 1032 } |
| 1033 ASSERT(current.is_identical_to(holder)); |
| 1034 |
| 1035 // Log the check depth. |
| 1036 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 1037 |
| 1038 // Check the holder map. |
| 1039 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), Handle<Map>(holder->map())); |
| 1040 __ j(not_equal, miss); |
| 1041 |
| 1042 // Perform security check for access to the global object. |
| 1043 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); |
| 1044 if (current->IsJSGlobalProxy()) { |
| 1045 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 1046 } |
| 1047 |
| 1048 // If we've skipped any global objects, it's not enough to verify that |
| 1049 // their maps haven't changed. We also need to check that the property |
| 1050 // cell for the property is still empty. |
| 1051 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
| 1052 |
| 1053 // Return the register containing the holder. |
| 1054 return reg; |
| 1055 } |
| 1056 |
| 1057 |
| 835 Register StubCompiler::CheckPrototypes(JSObject* object, | 1058 Register StubCompiler::CheckPrototypes(JSObject* object, |
| 836 Register object_reg, | 1059 Register object_reg, |
| 837 JSObject* holder, | 1060 JSObject* holder, |
| 838 Register holder_reg, | 1061 Register holder_reg, |
| 839 Register scratch1, | 1062 Register scratch1, |
| 840 Register scratch2, | 1063 Register scratch2, |
| 841 String* name, | 1064 String* name, |
| 842 int save_at_depth, | 1065 int save_at_depth, |
| 843 Label* miss) { | 1066 Label* miss) { |
| 844 // Make sure there's no overlap between holder and object registers. | 1067 // Make sure there's no overlap between holder and object registers. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 875 if (lookup_result->IsFailure()) { | 1098 if (lookup_result->IsFailure()) { |
| 876 set_failure(Failure::cast(lookup_result)); | 1099 set_failure(Failure::cast(lookup_result)); |
| 877 return reg; | 1100 return reg; |
| 878 } else { | 1101 } else { |
| 879 name = String::cast(lookup_result->ToObjectUnchecked()); | 1102 name = String::cast(lookup_result->ToObjectUnchecked()); |
| 880 } | 1103 } |
| 881 } | 1104 } |
| 882 ASSERT(current->property_dictionary()->FindEntry(name) == | 1105 ASSERT(current->property_dictionary()->FindEntry(name) == |
| 883 StringDictionary::kNotFound); | 1106 StringDictionary::kNotFound); |
| 884 | 1107 |
| 885 MaybeObject* negative_lookup = GenerateDictionaryNegativeLookup(masm(), | 1108 MaybeObject* negative_lookup = |
| 886 miss, | 1109 TryGenerateDictionaryNegativeLookup(masm(), |
| 887 reg, | 1110 miss, |
| 888 name, | 1111 reg, |
| 889 scratch1, | 1112 name, |
| 890 scratch2); | 1113 scratch1, |
| 1114 scratch2); |
| 891 if (negative_lookup->IsFailure()) { | 1115 if (negative_lookup->IsFailure()) { |
| 892 set_failure(Failure::cast(negative_lookup)); | 1116 set_failure(Failure::cast(negative_lookup)); |
| 893 return reg; | 1117 return reg; |
| 894 } | 1118 } |
| 895 | 1119 |
| 896 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 1120 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 897 reg = holder_reg; // from now the object is in holder_reg | 1121 reg = holder_reg; // from now the object is in holder_reg |
| 898 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1122 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 899 } else if (heap()->InNewSpace(prototype)) { | 1123 } else if (heap()->InNewSpace(prototype)) { |
| 900 // Get the map of the current object. | 1124 // Get the map of the current object. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 953 // the holder register. | 1177 // the holder register. |
| 954 ASSERT(current == holder); | 1178 ASSERT(current == holder); |
| 955 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 1179 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); |
| 956 if (current->IsJSGlobalProxy()) { | 1180 if (current->IsJSGlobalProxy()) { |
| 957 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1181 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 958 } | 1182 } |
| 959 | 1183 |
| 960 // If we've skipped any global objects, it's not enough to verify | 1184 // If we've skipped any global objects, it's not enough to verify |
| 961 // that their maps haven't changed. We also need to check that the | 1185 // that their maps haven't changed. We also need to check that the |
| 962 // property cell for the property is still empty. | 1186 // property cell for the property is still empty. |
| 963 current = object; | 1187 MaybeObject* result = TryGenerateCheckPropertyCells(masm(), |
| 964 while (current != holder) { | 1188 object, |
| 965 if (current->IsGlobalObject()) { | 1189 holder, |
| 966 MaybeObject* cell = GenerateCheckPropertyCell(masm(), | 1190 name, |
| 967 GlobalObject::cast(current), | 1191 scratch1, |
| 968 name, | 1192 miss); |
| 969 scratch1, | 1193 if (result->IsFailure()) set_failure(Failure::cast(result)); |
| 970 miss); | |
| 971 if (cell->IsFailure()) { | |
| 972 set_failure(Failure::cast(cell)); | |
| 973 return reg; | |
| 974 } | |
| 975 } | |
| 976 current = JSObject::cast(current->GetPrototype()); | |
| 977 } | |
| 978 | 1194 |
| 979 // Return the register containing the holder. | 1195 // Return the register containing the holder. |
| 980 return reg; | 1196 return reg; |
| 981 } | 1197 } |
| 982 | 1198 |
| 983 | 1199 |
| 984 void StubCompiler::GenerateLoadField(JSObject* object, | 1200 void StubCompiler::GenerateLoadField(Handle<JSObject> object, |
| 985 JSObject* holder, | 1201 Handle<JSObject> holder, |
| 986 Register receiver, | 1202 Register receiver, |
| 987 Register scratch1, | 1203 Register scratch1, |
| 988 Register scratch2, | 1204 Register scratch2, |
| 989 Register scratch3, | 1205 Register scratch3, |
| 990 int index, | 1206 int index, |
| 991 String* name, | 1207 Handle<String> name, |
| 992 Label* miss) { | 1208 Label* miss) { |
| 993 // Check that the receiver isn't a smi. | 1209 // Check that the receiver isn't a smi. |
| 994 __ JumpIfSmi(receiver, miss); | 1210 __ JumpIfSmi(receiver, miss); |
| 995 | 1211 |
| 996 // Check the prototype chain. | 1212 // Check the prototype chain. |
| 997 Register reg = | 1213 Register reg = CheckPrototypes( |
| 998 CheckPrototypes(object, receiver, holder, | 1214 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); |
| 999 scratch1, scratch2, scratch3, name, miss); | |
| 1000 | 1215 |
| 1001 // Get the value from the properties. | 1216 // Get the value from the properties. |
| 1002 GenerateFastPropertyLoad(masm(), rax, reg, holder, index); | 1217 GenerateFastPropertyLoad(masm(), rax, reg, holder, index); |
| 1003 __ ret(0); | 1218 __ ret(0); |
| 1004 } | 1219 } |
| 1005 | 1220 |
| 1006 | 1221 |
| 1007 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, | 1222 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, |
| 1008 JSObject* holder, | 1223 JSObject* holder, |
| 1009 Register receiver, | 1224 Register receiver, |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1074 __ lea(accessor_info_arg, StackSpaceOperand(0)); | 1289 __ lea(accessor_info_arg, StackSpaceOperand(0)); |
| 1075 | 1290 |
| 1076 // Emitting a stub call may try to allocate (if the code is not | 1291 // Emitting a stub call may try to allocate (if the code is not |
| 1077 // already generated). Do not allow the assembler to perform a | 1292 // already generated). Do not allow the assembler to perform a |
| 1078 // garbage collection but instead return the allocation failure | 1293 // garbage collection but instead return the allocation failure |
| 1079 // object. | 1294 // object. |
| 1080 return masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace); | 1295 return masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace); |
| 1081 } | 1296 } |
| 1082 | 1297 |
| 1083 | 1298 |
| 1084 void StubCompiler::GenerateLoadConstant(JSObject* object, | 1299 void StubCompiler::GenerateLoadConstant(Handle<JSObject> object, |
| 1085 JSObject* holder, | 1300 Handle<JSObject> holder, |
| 1086 Register receiver, | 1301 Register receiver, |
| 1087 Register scratch1, | 1302 Register scratch1, |
| 1088 Register scratch2, | 1303 Register scratch2, |
| 1089 Register scratch3, | 1304 Register scratch3, |
| 1090 Object* value, | 1305 Handle<Object> value, |
| 1091 String* name, | 1306 Handle<String> name, |
| 1092 Label* miss) { | 1307 Label* miss) { |
| 1093 // Check that the receiver isn't a smi. | 1308 // Check that the receiver isn't a smi. |
| 1094 __ JumpIfSmi(receiver, miss); | 1309 __ JumpIfSmi(receiver, miss); |
| 1095 | 1310 |
| 1096 // Check that the maps haven't changed. | 1311 // Check that the maps haven't changed. |
| 1097 CheckPrototypes(object, receiver, holder, | 1312 CheckPrototypes( |
| 1098 scratch1, scratch2, scratch3, name, miss); | 1313 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); |
| 1099 | 1314 |
| 1100 // Return the constant value. | 1315 // Return the constant value. |
| 1101 __ Move(rax, Handle<Object>(value)); | 1316 __ Move(rax, value); |
| 1102 __ ret(0); | 1317 __ ret(0); |
| 1103 } | 1318 } |
| 1104 | 1319 |
| 1105 | 1320 |
| 1106 void StubCompiler::GenerateLoadInterceptor(JSObject* object, | 1321 void StubCompiler::GenerateLoadInterceptor(JSObject* object, |
| 1107 JSObject* interceptor_holder, | 1322 JSObject* interceptor_holder, |
| 1108 LookupResult* lookup, | 1323 LookupResult* lookup, |
| 1109 Register receiver, | 1324 Register receiver, |
| 1110 Register name_reg, | 1325 Register name_reg, |
| 1111 Register scratch1, | 1326 Register scratch1, |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1191 scratch2, | 1406 scratch2, |
| 1192 scratch3, | 1407 scratch3, |
| 1193 name, | 1408 name, |
| 1194 miss); | 1409 miss); |
| 1195 } | 1410 } |
| 1196 | 1411 |
| 1197 if (lookup->type() == FIELD) { | 1412 if (lookup->type() == FIELD) { |
| 1198 // We found FIELD property in prototype chain of interceptor's holder. | 1413 // We found FIELD property in prototype chain of interceptor's holder. |
| 1199 // Retrieve a field from field's holder. | 1414 // Retrieve a field from field's holder. |
| 1200 GenerateFastPropertyLoad(masm(), rax, holder_reg, | 1415 GenerateFastPropertyLoad(masm(), rax, holder_reg, |
| 1201 lookup->holder(), lookup->GetFieldIndex()); | 1416 Handle<JSObject>(lookup->holder()), |
| 1417 lookup->GetFieldIndex()); |
| 1202 __ ret(0); | 1418 __ ret(0); |
| 1203 } else { | 1419 } else { |
| 1204 // We found CALLBACKS property in prototype chain of interceptor's | 1420 // We found CALLBACKS property in prototype chain of interceptor's |
| 1205 // holder. | 1421 // holder. |
| 1206 ASSERT(lookup->type() == CALLBACKS); | 1422 ASSERT(lookup->type() == CALLBACKS); |
| 1207 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); | 1423 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); |
| 1208 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 1424 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); |
| 1209 ASSERT(callback != NULL); | 1425 ASSERT(callback != NULL); |
| 1210 ASSERT(callback->getter() != NULL); | 1426 ASSERT(callback->getter() != NULL); |
| 1211 | 1427 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1237 name_reg, interceptor_holder); | 1453 name_reg, interceptor_holder); |
| 1238 __ push(scratch2); // restore old return address | 1454 __ push(scratch2); // restore old return address |
| 1239 | 1455 |
| 1240 ExternalReference ref = ExternalReference( | 1456 ExternalReference ref = ExternalReference( |
| 1241 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate()); | 1457 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate()); |
| 1242 __ TailCallExternalReference(ref, 5, 1); | 1458 __ TailCallExternalReference(ref, 5, 1); |
| 1243 } | 1459 } |
| 1244 } | 1460 } |
| 1245 | 1461 |
| 1246 | 1462 |
| 1247 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { | 1463 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { |
| 1248 if (kind_ == Code::KEYED_CALL_IC) { | 1464 if (kind_ == Code::KEYED_CALL_IC) { |
| 1249 __ Cmp(rcx, Handle<String>(name)); | 1465 __ Cmp(rcx, name); |
| 1250 __ j(not_equal, miss); | 1466 __ j(not_equal, miss); |
| 1251 } | 1467 } |
| 1252 } | 1468 } |
| 1253 | 1469 |
| 1254 | 1470 |
| 1255 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, | 1471 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, |
| 1256 JSObject* holder, | 1472 JSObject* holder, |
| 1257 String* name, | 1473 String* name, |
| 1258 Label* miss) { | 1474 Label* miss) { |
| 1259 ASSERT(holder->IsGlobalObject()); | 1475 ASSERT(holder->IsGlobalObject()); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1298 __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); | 1514 __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); |
| 1299 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); | 1515 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); |
| 1300 __ j(not_equal, miss); | 1516 __ j(not_equal, miss); |
| 1301 } else { | 1517 } else { |
| 1302 __ Cmp(rdi, Handle<JSFunction>(function)); | 1518 __ Cmp(rdi, Handle<JSFunction>(function)); |
| 1303 __ j(not_equal, miss); | 1519 __ j(not_equal, miss); |
| 1304 } | 1520 } |
| 1305 } | 1521 } |
| 1306 | 1522 |
| 1307 | 1523 |
| 1308 MaybeObject* CallStubCompiler::GenerateMissBranch() { | 1524 void CallStubCompiler::GenerateMissBranch() { |
| 1309 MaybeObject* maybe_obj = | 1525 Handle<Code> code = |
| 1310 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1526 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
| 1311 kind_, | 1527 kind_, |
| 1312 extra_ic_state_); | 1528 extra_state_); |
| 1529 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1530 } |
| 1531 |
| 1532 |
| 1533 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 1534 // handlified. |
| 1535 MaybeObject* CallStubCompiler::TryGenerateMissBranch() { |
| 1536 MaybeObject* maybe_obj = |
| 1537 isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(), |
| 1538 kind_, |
| 1539 extra_state_); |
| 1313 Object* obj; | 1540 Object* obj; |
| 1314 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1541 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 1315 __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | 1542 __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); |
| 1316 return obj; | 1543 return obj; |
| 1317 } | 1544 } |
| 1318 | 1545 |
| 1319 | 1546 |
| 1320 MaybeObject* CallStubCompiler::CompileCallField(JSObject* object, | 1547 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| 1321 JSObject* holder, | 1548 Handle<JSObject> holder, |
| 1322 int index, | 1549 int index, |
| 1323 String* name) { | 1550 Handle<String> name) { |
| 1324 // ----------- S t a t e ------------- | 1551 // ----------- S t a t e ------------- |
| 1325 // rcx : function name | 1552 // rcx : function name |
| 1326 // rsp[0] : return address | 1553 // rsp[0] : return address |
| 1327 // rsp[8] : argument argc | 1554 // rsp[8] : argument argc |
| 1328 // rsp[16] : argument argc - 1 | 1555 // rsp[16] : argument argc - 1 |
| 1329 // ... | 1556 // ... |
| 1330 // rsp[argc * 8] : argument 1 | 1557 // rsp[argc * 8] : argument 1 |
| 1331 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1558 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1332 // ----------------------------------- | 1559 // ----------------------------------- |
| 1333 Label miss; | 1560 Label miss; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1353 __ j(not_equal, &miss); | 1580 __ j(not_equal, &miss); |
| 1354 | 1581 |
| 1355 // Patch the receiver on the stack with the global proxy if | 1582 // Patch the receiver on the stack with the global proxy if |
| 1356 // necessary. | 1583 // necessary. |
| 1357 if (object->IsGlobalObject()) { | 1584 if (object->IsGlobalObject()) { |
| 1358 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 1585 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 1359 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 1586 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 1360 } | 1587 } |
| 1361 | 1588 |
| 1362 // Invoke the function. | 1589 // Invoke the function. |
| 1363 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 1590 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 1364 ? CALL_AS_FUNCTION | 1591 ? CALL_AS_FUNCTION |
| 1365 : CALL_AS_METHOD; | 1592 : CALL_AS_METHOD; |
| 1366 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, | 1593 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, |
| 1367 NullCallWrapper(), call_kind); | 1594 NullCallWrapper(), call_kind); |
| 1368 | 1595 |
| 1369 // Handle call cache miss. | 1596 // Handle call cache miss. |
| 1370 __ bind(&miss); | 1597 __ bind(&miss); |
| 1371 MaybeObject* maybe_result = GenerateMissBranch(); | 1598 GenerateMissBranch(); |
| 1372 if (maybe_result->IsFailure()) return maybe_result; | |
| 1373 | 1599 |
| 1374 // Return the generated code. | 1600 // Return the generated code. |
| 1375 return GetCode(FIELD, name); | 1601 return GetCode(FIELD, name); |
| 1376 } | 1602 } |
| 1377 | 1603 |
| 1378 | 1604 |
| 1379 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, | 1605 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, |
| 1380 JSObject* holder, | 1606 JSObject* holder, |
| 1381 JSGlobalPropertyCell* cell, | 1607 JSGlobalPropertyCell* cell, |
| 1382 JSFunction* function, | 1608 JSFunction* function, |
| 1383 String* name) { | 1609 String* name) { |
| 1384 // ----------- S t a t e ------------- | 1610 // ----------- S t a t e ------------- |
| 1385 // -- rcx : name | 1611 // -- rcx : name |
| 1386 // -- rsp[0] : return address | 1612 // -- rsp[0] : return address |
| 1387 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1613 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1388 // -- ... | 1614 // -- ... |
| 1389 // -- rsp[(argc + 1) * 8] : receiver | 1615 // -- rsp[(argc + 1) * 8] : receiver |
| 1390 // ----------------------------------- | 1616 // ----------------------------------- |
| 1391 | 1617 |
| 1392 // If object is not an array, bail out to regular call. | 1618 // If object is not an array, bail out to regular call. |
| 1393 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); | 1619 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); |
| 1394 | 1620 |
| 1395 Label miss; | 1621 Label miss; |
| 1396 | 1622 |
| 1397 GenerateNameCheck(name, &miss); | 1623 GenerateNameCheck(Handle<String>(name), &miss); |
| 1398 | 1624 |
| 1399 // Get the receiver from the stack. | 1625 // Get the receiver from the stack. |
| 1400 const int argc = arguments().immediate(); | 1626 const int argc = arguments().immediate(); |
| 1401 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1627 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1402 | 1628 |
| 1403 // Check that the receiver isn't a smi. | 1629 // Check that the receiver isn't a smi. |
| 1404 __ JumpIfSmi(rdx, &miss); | 1630 __ JumpIfSmi(rdx, &miss); |
| 1405 | 1631 |
| 1406 CheckPrototypes(JSObject::cast(object), | 1632 CheckPrototypes(JSObject::cast(object), |
| 1407 rdx, | 1633 rdx, |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1481 __ bind(&attempt_to_grow_elements); | 1707 __ bind(&attempt_to_grow_elements); |
| 1482 if (!FLAG_inline_new) { | 1708 if (!FLAG_inline_new) { |
| 1483 __ jmp(&call_builtin); | 1709 __ jmp(&call_builtin); |
| 1484 } | 1710 } |
| 1485 | 1711 |
| 1486 __ movq(rdi, Operand(rsp, argc * kPointerSize)); | 1712 __ movq(rdi, Operand(rsp, argc * kPointerSize)); |
| 1487 // Growing elements that are SMI-only requires special handling in case | 1713 // Growing elements that are SMI-only requires special handling in case |
| 1488 // the new element is non-Smi. For now, delegate to the builtin. | 1714 // the new element is non-Smi. For now, delegate to the builtin. |
| 1489 Label no_fast_elements_check; | 1715 Label no_fast_elements_check; |
| 1490 __ JumpIfSmi(rdi, &no_fast_elements_check); | 1716 __ JumpIfSmi(rdi, &no_fast_elements_check); |
| 1491 __ movq(rsi, FieldOperand(rdx, HeapObject::kMapOffset)); | 1717 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); |
| 1492 __ CheckFastObjectElements(rsi, &call_builtin, Label::kFar); | 1718 __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar); |
| 1493 __ bind(&no_fast_elements_check); | 1719 __ bind(&no_fast_elements_check); |
| 1494 | 1720 |
| 1495 ExternalReference new_space_allocation_top = | 1721 ExternalReference new_space_allocation_top = |
| 1496 ExternalReference::new_space_allocation_top_address(isolate()); | 1722 ExternalReference::new_space_allocation_top_address(isolate()); |
| 1497 ExternalReference new_space_allocation_limit = | 1723 ExternalReference new_space_allocation_limit = |
| 1498 ExternalReference::new_space_allocation_limit_address(isolate()); | 1724 ExternalReference::new_space_allocation_limit_address(isolate()); |
| 1499 | 1725 |
| 1500 const int kAllocationDelta = 4; | 1726 const int kAllocationDelta = 4; |
| 1501 // Load top. | 1727 // Load top. |
| 1502 __ Load(rcx, new_space_allocation_top); | 1728 __ Load(rcx, new_space_allocation_top); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1546 } | 1772 } |
| 1547 | 1773 |
| 1548 __ bind(&call_builtin); | 1774 __ bind(&call_builtin); |
| 1549 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, | 1775 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, |
| 1550 isolate()), | 1776 isolate()), |
| 1551 argc + 1, | 1777 argc + 1, |
| 1552 1); | 1778 1); |
| 1553 } | 1779 } |
| 1554 | 1780 |
| 1555 __ bind(&miss); | 1781 __ bind(&miss); |
| 1556 MaybeObject* maybe_result = GenerateMissBranch(); | 1782 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1557 if (maybe_result->IsFailure()) return maybe_result; | 1783 if (maybe_result->IsFailure()) return maybe_result; |
| 1558 | 1784 |
| 1559 // Return the generated code. | 1785 // Return the generated code. |
| 1560 return GetCode(function); | 1786 return TryGetCode(function); |
| 1561 } | 1787 } |
| 1562 | 1788 |
| 1563 | 1789 |
| 1564 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, | 1790 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, |
| 1565 JSObject* holder, | 1791 JSObject* holder, |
| 1566 JSGlobalPropertyCell* cell, | 1792 JSGlobalPropertyCell* cell, |
| 1567 JSFunction* function, | 1793 JSFunction* function, |
| 1568 String* name) { | 1794 String* name) { |
| 1569 // ----------- S t a t e ------------- | 1795 // ----------- S t a t e ------------- |
| 1570 // -- rcx : name | 1796 // -- rcx : name |
| 1571 // -- rsp[0] : return address | 1797 // -- rsp[0] : return address |
| 1572 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1798 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1573 // -- ... | 1799 // -- ... |
| 1574 // -- rsp[(argc + 1) * 8] : receiver | 1800 // -- rsp[(argc + 1) * 8] : receiver |
| 1575 // ----------------------------------- | 1801 // ----------------------------------- |
| 1576 | 1802 |
| 1577 // If object is not an array, bail out to regular call. | 1803 // If object is not an array, bail out to regular call. |
| 1578 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); | 1804 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); |
| 1579 | 1805 |
| 1580 Label miss, return_undefined, call_builtin; | 1806 Label miss, return_undefined, call_builtin; |
| 1581 | 1807 |
| 1582 GenerateNameCheck(name, &miss); | 1808 GenerateNameCheck(Handle<String>(name), &miss); |
| 1583 | 1809 |
| 1584 // Get the receiver from the stack. | 1810 // Get the receiver from the stack. |
| 1585 const int argc = arguments().immediate(); | 1811 const int argc = arguments().immediate(); |
| 1586 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1812 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1587 | 1813 |
| 1588 // Check that the receiver isn't a smi. | 1814 // Check that the receiver isn't a smi. |
| 1589 __ JumpIfSmi(rdx, &miss); | 1815 __ JumpIfSmi(rdx, &miss); |
| 1590 | 1816 |
| 1591 CheckPrototypes(JSObject::cast(object), rdx, | 1817 CheckPrototypes(JSObject::cast(object), rdx, |
| 1592 holder, rbx, | 1818 holder, rbx, |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1629 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 1855 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 1630 __ ret((argc + 1) * kPointerSize); | 1856 __ ret((argc + 1) * kPointerSize); |
| 1631 | 1857 |
| 1632 __ bind(&call_builtin); | 1858 __ bind(&call_builtin); |
| 1633 __ TailCallExternalReference( | 1859 __ TailCallExternalReference( |
| 1634 ExternalReference(Builtins::c_ArrayPop, isolate()), | 1860 ExternalReference(Builtins::c_ArrayPop, isolate()), |
| 1635 argc + 1, | 1861 argc + 1, |
| 1636 1); | 1862 1); |
| 1637 | 1863 |
| 1638 __ bind(&miss); | 1864 __ bind(&miss); |
| 1639 MaybeObject* maybe_result = GenerateMissBranch(); | 1865 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1640 if (maybe_result->IsFailure()) return maybe_result; | 1866 if (maybe_result->IsFailure()) return maybe_result; |
| 1641 | 1867 |
| 1642 // Return the generated code. | 1868 // Return the generated code. |
| 1643 return GetCode(function); | 1869 return TryGetCode(function); |
| 1644 } | 1870 } |
| 1645 | 1871 |
| 1646 | 1872 |
| 1647 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( | 1873 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( |
| 1648 Object* object, | 1874 Object* object, |
| 1649 JSObject* holder, | 1875 JSObject* holder, |
| 1650 JSGlobalPropertyCell* cell, | 1876 JSGlobalPropertyCell* cell, |
| 1651 JSFunction* function, | 1877 JSFunction* function, |
| 1652 String* name) { | 1878 String* name) { |
| 1653 // ----------- S t a t e ------------- | 1879 // ----------- S t a t e ------------- |
| 1654 // -- rcx : function name | 1880 // -- rcx : function name |
| 1655 // -- rsp[0] : return address | 1881 // -- rsp[0] : return address |
| 1656 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1882 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1657 // -- ... | 1883 // -- ... |
| 1658 // -- rsp[(argc + 1) * 8] : receiver | 1884 // -- rsp[(argc + 1) * 8] : receiver |
| 1659 // ----------------------------------- | 1885 // ----------------------------------- |
| 1660 | 1886 |
| 1661 // If object is not a string, bail out to regular call. | 1887 // If object is not a string, bail out to regular call. |
| 1662 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); | 1888 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); |
| 1663 | 1889 |
| 1664 const int argc = arguments().immediate(); | 1890 const int argc = arguments().immediate(); |
| 1665 | 1891 |
| 1666 Label miss; | 1892 Label miss; |
| 1667 Label name_miss; | 1893 Label name_miss; |
| 1668 Label index_out_of_range; | 1894 Label index_out_of_range; |
| 1669 Label* index_out_of_range_label = &index_out_of_range; | 1895 Label* index_out_of_range_label = &index_out_of_range; |
| 1670 | 1896 |
| 1671 if (kind_ == Code::CALL_IC && | 1897 if (kind_ == Code::CALL_IC && |
| 1672 (CallICBase::StringStubState::decode(extra_ic_state_) == | 1898 (CallICBase::StringStubState::decode(extra_state_) == |
| 1673 DEFAULT_STRING_STUB)) { | 1899 DEFAULT_STRING_STUB)) { |
| 1674 index_out_of_range_label = &miss; | 1900 index_out_of_range_label = &miss; |
| 1675 } | 1901 } |
| 1676 | 1902 |
| 1677 GenerateNameCheck(name, &name_miss); | 1903 GenerateNameCheck(Handle<String>(name), &name_miss); |
| 1678 | 1904 |
| 1679 // Check that the maps starting from the prototype haven't changed. | 1905 // Check that the maps starting from the prototype haven't changed. |
| 1680 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1906 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 1681 Context::STRING_FUNCTION_INDEX, | 1907 Context::STRING_FUNCTION_INDEX, |
| 1682 rax, | 1908 rax, |
| 1683 &miss); | 1909 &miss); |
| 1684 ASSERT(object != holder); | 1910 ASSERT(object != holder); |
| 1685 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, | 1911 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
| 1686 rbx, rdx, rdi, name, &miss); | 1912 rbx, rdx, rdi, name, &miss); |
| 1687 | 1913 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1713 if (index_out_of_range.is_linked()) { | 1939 if (index_out_of_range.is_linked()) { |
| 1714 __ bind(&index_out_of_range); | 1940 __ bind(&index_out_of_range); |
| 1715 __ LoadRoot(rax, Heap::kNanValueRootIndex); | 1941 __ LoadRoot(rax, Heap::kNanValueRootIndex); |
| 1716 __ ret((argc + 1) * kPointerSize); | 1942 __ ret((argc + 1) * kPointerSize); |
| 1717 } | 1943 } |
| 1718 | 1944 |
| 1719 __ bind(&miss); | 1945 __ bind(&miss); |
| 1720 // Restore function name in rcx. | 1946 // Restore function name in rcx. |
| 1721 __ Move(rcx, Handle<String>(name)); | 1947 __ Move(rcx, Handle<String>(name)); |
| 1722 __ bind(&name_miss); | 1948 __ bind(&name_miss); |
| 1723 MaybeObject* maybe_result = GenerateMissBranch(); | 1949 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1724 if (maybe_result->IsFailure()) return maybe_result; | 1950 if (maybe_result->IsFailure()) return maybe_result; |
| 1725 | 1951 |
| 1726 // Return the generated code. | 1952 // Return the generated code. |
| 1727 return GetCode(function); | 1953 return TryGetCode(function); |
| 1728 } | 1954 } |
| 1729 | 1955 |
| 1730 | 1956 |
| 1731 MaybeObject* CallStubCompiler::CompileStringCharAtCall( | 1957 MaybeObject* CallStubCompiler::CompileStringCharAtCall( |
| 1732 Object* object, | 1958 Object* object, |
| 1733 JSObject* holder, | 1959 JSObject* holder, |
| 1734 JSGlobalPropertyCell* cell, | 1960 JSGlobalPropertyCell* cell, |
| 1735 JSFunction* function, | 1961 JSFunction* function, |
| 1736 String* name) { | 1962 String* name) { |
| 1737 // ----------- S t a t e ------------- | 1963 // ----------- S t a t e ------------- |
| 1738 // -- rcx : function name | 1964 // -- rcx : function name |
| 1739 // -- rsp[0] : return address | 1965 // -- rsp[0] : return address |
| 1740 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1966 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1741 // -- ... | 1967 // -- ... |
| 1742 // -- rsp[(argc + 1) * 8] : receiver | 1968 // -- rsp[(argc + 1) * 8] : receiver |
| 1743 // ----------------------------------- | 1969 // ----------------------------------- |
| 1744 | 1970 |
| 1745 // If object is not a string, bail out to regular call. | 1971 // If object is not a string, bail out to regular call. |
| 1746 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); | 1972 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); |
| 1747 | 1973 |
| 1748 const int argc = arguments().immediate(); | 1974 const int argc = arguments().immediate(); |
| 1749 | 1975 |
| 1750 Label miss; | 1976 Label miss; |
| 1751 Label name_miss; | 1977 Label name_miss; |
| 1752 Label index_out_of_range; | 1978 Label index_out_of_range; |
| 1753 Label* index_out_of_range_label = &index_out_of_range; | 1979 Label* index_out_of_range_label = &index_out_of_range; |
| 1754 | 1980 |
| 1755 if (kind_ == Code::CALL_IC && | 1981 if (kind_ == Code::CALL_IC && |
| 1756 (CallICBase::StringStubState::decode(extra_ic_state_) == | 1982 (CallICBase::StringStubState::decode(extra_state_) == |
| 1757 DEFAULT_STRING_STUB)) { | 1983 DEFAULT_STRING_STUB)) { |
| 1758 index_out_of_range_label = &miss; | 1984 index_out_of_range_label = &miss; |
| 1759 } | 1985 } |
| 1760 | 1986 |
| 1761 GenerateNameCheck(name, &name_miss); | 1987 GenerateNameCheck(Handle<String>(name), &name_miss); |
| 1762 | 1988 |
| 1763 // Check that the maps starting from the prototype haven't changed. | 1989 // Check that the maps starting from the prototype haven't changed. |
| 1764 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1990 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 1765 Context::STRING_FUNCTION_INDEX, | 1991 Context::STRING_FUNCTION_INDEX, |
| 1766 rax, | 1992 rax, |
| 1767 &miss); | 1993 &miss); |
| 1768 ASSERT(object != holder); | 1994 ASSERT(object != holder); |
| 1769 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, | 1995 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
| 1770 rbx, rdx, rdi, name, &miss); | 1996 rbx, rdx, rdi, name, &miss); |
| 1771 | 1997 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1799 if (index_out_of_range.is_linked()) { | 2025 if (index_out_of_range.is_linked()) { |
| 1800 __ bind(&index_out_of_range); | 2026 __ bind(&index_out_of_range); |
| 1801 __ LoadRoot(rax, Heap::kEmptyStringRootIndex); | 2027 __ LoadRoot(rax, Heap::kEmptyStringRootIndex); |
| 1802 __ ret((argc + 1) * kPointerSize); | 2028 __ ret((argc + 1) * kPointerSize); |
| 1803 } | 2029 } |
| 1804 | 2030 |
| 1805 __ bind(&miss); | 2031 __ bind(&miss); |
| 1806 // Restore function name in rcx. | 2032 // Restore function name in rcx. |
| 1807 __ Move(rcx, Handle<String>(name)); | 2033 __ Move(rcx, Handle<String>(name)); |
| 1808 __ bind(&name_miss); | 2034 __ bind(&name_miss); |
| 1809 MaybeObject* maybe_result = GenerateMissBranch(); | 2035 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1810 if (maybe_result->IsFailure()) return maybe_result; | 2036 if (maybe_result->IsFailure()) return maybe_result; |
| 1811 | 2037 |
| 1812 // Return the generated code. | 2038 // Return the generated code. |
| 1813 return GetCode(function); | 2039 return TryGetCode(function); |
| 1814 } | 2040 } |
| 1815 | 2041 |
| 1816 | 2042 |
| 1817 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( | 2043 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( |
| 1818 Object* object, | 2044 Object* object, |
| 1819 JSObject* holder, | 2045 JSObject* holder, |
| 1820 JSGlobalPropertyCell* cell, | 2046 JSGlobalPropertyCell* cell, |
| 1821 JSFunction* function, | 2047 JSFunction* function, |
| 1822 String* name) { | 2048 String* name) { |
| 1823 // ----------- S t a t e ------------- | 2049 // ----------- S t a t e ------------- |
| 1824 // -- rcx : function name | 2050 // -- rcx : function name |
| 1825 // -- rsp[0] : return address | 2051 // -- rsp[0] : return address |
| 1826 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 2052 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1827 // -- ... | 2053 // -- ... |
| 1828 // -- rsp[(argc + 1) * 8] : receiver | 2054 // -- rsp[(argc + 1) * 8] : receiver |
| 1829 // ----------------------------------- | 2055 // ----------------------------------- |
| 1830 | 2056 |
| 1831 const int argc = arguments().immediate(); | 2057 const int argc = arguments().immediate(); |
| 1832 | 2058 |
| 1833 // If the object is not a JSObject or we got an unexpected number of | 2059 // If the object is not a JSObject or we got an unexpected number of |
| 1834 // arguments, bail out to the regular call. | 2060 // arguments, bail out to the regular call. |
| 1835 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 2061 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); |
| 1836 | 2062 |
| 1837 Label miss; | 2063 Label miss; |
| 1838 GenerateNameCheck(name, &miss); | 2064 GenerateNameCheck(Handle<String>(name), &miss); |
| 1839 | 2065 |
| 1840 if (cell == NULL) { | 2066 if (cell == NULL) { |
| 1841 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); | 2067 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); |
| 1842 | 2068 |
| 1843 __ JumpIfSmi(rdx, &miss); | 2069 __ JumpIfSmi(rdx, &miss); |
| 1844 | 2070 |
| 1845 CheckPrototypes(JSObject::cast(object), rdx, holder, rbx, rax, rdi, name, | 2071 CheckPrototypes(JSObject::cast(object), rdx, holder, rbx, rax, rdi, name, |
| 1846 &miss); | 2072 &miss); |
| 1847 } else { | 2073 } else { |
| 1848 ASSERT(cell->value() == function); | 2074 ASSERT(cell->value() == function); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1864 StringCharFromCodeGenerator char_from_code_generator(code, rax); | 2090 StringCharFromCodeGenerator char_from_code_generator(code, rax); |
| 1865 char_from_code_generator.GenerateFast(masm()); | 2091 char_from_code_generator.GenerateFast(masm()); |
| 1866 __ ret(2 * kPointerSize); | 2092 __ ret(2 * kPointerSize); |
| 1867 | 2093 |
| 1868 StubRuntimeCallHelper call_helper; | 2094 StubRuntimeCallHelper call_helper; |
| 1869 char_from_code_generator.GenerateSlow(masm(), call_helper); | 2095 char_from_code_generator.GenerateSlow(masm(), call_helper); |
| 1870 | 2096 |
| 1871 // Tail call the full function. We do not have to patch the receiver | 2097 // Tail call the full function. We do not have to patch the receiver |
| 1872 // because the function makes no use of it. | 2098 // because the function makes no use of it. |
| 1873 __ bind(&slow); | 2099 __ bind(&slow); |
| 1874 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 2100 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 1875 ? CALL_AS_FUNCTION | 2101 ? CALL_AS_FUNCTION |
| 1876 : CALL_AS_METHOD; | 2102 : CALL_AS_METHOD; |
| 1877 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2103 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 1878 NullCallWrapper(), call_kind); | 2104 NullCallWrapper(), call_kind); |
| 1879 | 2105 |
| 1880 __ bind(&miss); | 2106 __ bind(&miss); |
| 1881 // rcx: function name. | 2107 // rcx: function name. |
| 1882 MaybeObject* maybe_result = GenerateMissBranch(); | 2108 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1883 if (maybe_result->IsFailure()) return maybe_result; | 2109 if (maybe_result->IsFailure()) return maybe_result; |
| 1884 | 2110 |
| 1885 // Return the generated code. | 2111 // Return the generated code. |
| 1886 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2112 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
| 1887 } | 2113 } |
| 1888 | 2114 |
| 1889 | 2115 |
| 1890 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, | 2116 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, |
| 1891 JSObject* holder, | 2117 JSObject* holder, |
| 1892 JSGlobalPropertyCell* cell, | 2118 JSGlobalPropertyCell* cell, |
| 1893 JSFunction* function, | 2119 JSFunction* function, |
| 1894 String* name) { | 2120 String* name) { |
| 1895 // TODO(872): implement this. | 2121 // TODO(872): implement this. |
| 1896 return heap()->undefined_value(); | 2122 return heap()->undefined_value(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1910 // -- rsp[(argc + 1) * 8] : receiver | 2136 // -- rsp[(argc + 1) * 8] : receiver |
| 1911 // ----------------------------------- | 2137 // ----------------------------------- |
| 1912 | 2138 |
| 1913 const int argc = arguments().immediate(); | 2139 const int argc = arguments().immediate(); |
| 1914 | 2140 |
| 1915 // If the object is not a JSObject or we got an unexpected number of | 2141 // If the object is not a JSObject or we got an unexpected number of |
| 1916 // arguments, bail out to the regular call. | 2142 // arguments, bail out to the regular call. |
| 1917 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 2143 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); |
| 1918 | 2144 |
| 1919 Label miss; | 2145 Label miss; |
| 1920 GenerateNameCheck(name, &miss); | 2146 GenerateNameCheck(Handle<String>(name), &miss); |
| 1921 | 2147 |
| 1922 if (cell == NULL) { | 2148 if (cell == NULL) { |
| 1923 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); | 2149 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); |
| 1924 | 2150 |
| 1925 __ JumpIfSmi(rdx, &miss); | 2151 __ JumpIfSmi(rdx, &miss); |
| 1926 | 2152 |
| 1927 CheckPrototypes(JSObject::cast(object), rdx, holder, rbx, rax, rdi, name, | 2153 CheckPrototypes(JSObject::cast(object), rdx, holder, rbx, rax, rdi, name, |
| 1928 &miss); | 2154 &miss); |
| 1929 } else { | 2155 } else { |
| 1930 ASSERT(cell->value() == function); | 2156 ASSERT(cell->value() == function); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1981 // number. We still have the sign mask in rdi. | 2207 // number. We still have the sign mask in rdi. |
| 1982 __ bind(&negative_sign); | 2208 __ bind(&negative_sign); |
| 1983 __ xor_(rbx, rdi); | 2209 __ xor_(rbx, rdi); |
| 1984 __ AllocateHeapNumber(rax, rdx, &slow); | 2210 __ AllocateHeapNumber(rax, rdx, &slow); |
| 1985 __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rbx); | 2211 __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rbx); |
| 1986 __ ret(2 * kPointerSize); | 2212 __ ret(2 * kPointerSize); |
| 1987 | 2213 |
| 1988 // Tail call the full function. We do not have to patch the receiver | 2214 // Tail call the full function. We do not have to patch the receiver |
| 1989 // because the function makes no use of it. | 2215 // because the function makes no use of it. |
| 1990 __ bind(&slow); | 2216 __ bind(&slow); |
| 1991 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 2217 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 1992 ? CALL_AS_FUNCTION | 2218 ? CALL_AS_FUNCTION |
| 1993 : CALL_AS_METHOD; | 2219 : CALL_AS_METHOD; |
| 1994 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2220 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 1995 NullCallWrapper(), call_kind); | 2221 NullCallWrapper(), call_kind); |
| 1996 | 2222 |
| 1997 __ bind(&miss); | 2223 __ bind(&miss); |
| 1998 // rcx: function name. | 2224 // rcx: function name. |
| 1999 MaybeObject* maybe_result = GenerateMissBranch(); | 2225 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2000 if (maybe_result->IsFailure()) return maybe_result; | 2226 if (maybe_result->IsFailure()) return maybe_result; |
| 2001 | 2227 |
| 2002 // Return the generated code. | 2228 // Return the generated code. |
| 2003 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2229 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
| 2004 } | 2230 } |
| 2005 | 2231 |
| 2006 | 2232 |
| 2007 MaybeObject* CallStubCompiler::CompileFastApiCall( | 2233 MaybeObject* CallStubCompiler::CompileFastApiCall( |
| 2008 const CallOptimization& optimization, | 2234 const CallOptimization& optimization, |
| 2009 Object* object, | 2235 Object* object, |
| 2010 JSObject* holder, | 2236 JSObject* holder, |
| 2011 JSGlobalPropertyCell* cell, | 2237 JSGlobalPropertyCell* cell, |
| 2012 JSFunction* function, | 2238 JSFunction* function, |
| 2013 String* name) { | 2239 String* name) { |
| 2014 ASSERT(optimization.is_simple_api_call()); | 2240 ASSERT(optimization.is_simple_api_call()); |
| 2015 // Bail out if object is a global object as we don't want to | 2241 // Bail out if object is a global object as we don't want to |
| 2016 // repatch it to global receiver. | 2242 // repatch it to global receiver. |
| 2017 if (object->IsGlobalObject()) return heap()->undefined_value(); | 2243 if (object->IsGlobalObject()) return heap()->undefined_value(); |
| 2018 if (cell != NULL) return heap()->undefined_value(); | 2244 if (cell != NULL) return heap()->undefined_value(); |
| 2019 if (!object->IsJSObject()) return heap()->undefined_value(); | 2245 if (!object->IsJSObject()) return heap()->undefined_value(); |
| 2020 int depth = optimization.GetPrototypeDepthOfExpectedType( | 2246 int depth = optimization.GetPrototypeDepthOfExpectedType( |
| 2021 JSObject::cast(object), holder); | 2247 JSObject::cast(object), holder); |
| 2022 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); | 2248 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); |
| 2023 | 2249 |
| 2024 Label miss, miss_before_stack_reserved; | 2250 Label miss, miss_before_stack_reserved; |
| 2025 | 2251 |
| 2026 GenerateNameCheck(name, &miss_before_stack_reserved); | 2252 GenerateNameCheck(Handle<String>(name), &miss_before_stack_reserved); |
| 2027 | 2253 |
| 2028 // Get the receiver from the stack. | 2254 // Get the receiver from the stack. |
| 2029 const int argc = arguments().immediate(); | 2255 const int argc = arguments().immediate(); |
| 2030 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2256 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2031 | 2257 |
| 2032 // Check that the receiver isn't a smi. | 2258 // Check that the receiver isn't a smi. |
| 2033 __ JumpIfSmi(rdx, &miss_before_stack_reserved); | 2259 __ JumpIfSmi(rdx, &miss_before_stack_reserved); |
| 2034 | 2260 |
| 2035 Counters* counters = isolate()->counters(); | 2261 Counters* counters = isolate()->counters(); |
| 2036 __ IncrementCounter(counters->call_const(), 1); | 2262 __ IncrementCounter(counters->call_const(), 1); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2048 __ movq(rax, Operand(rsp, 3 * kPointerSize)); | 2274 __ movq(rax, Operand(rsp, 3 * kPointerSize)); |
| 2049 __ movq(Operand(rsp, 0 * kPointerSize), rax); | 2275 __ movq(Operand(rsp, 0 * kPointerSize), rax); |
| 2050 | 2276 |
| 2051 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); | 2277 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); |
| 2052 if (result->IsFailure()) return result; | 2278 if (result->IsFailure()) return result; |
| 2053 | 2279 |
| 2054 __ bind(&miss); | 2280 __ bind(&miss); |
| 2055 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 2281 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2056 | 2282 |
| 2057 __ bind(&miss_before_stack_reserved); | 2283 __ bind(&miss_before_stack_reserved); |
| 2058 MaybeObject* maybe_result = GenerateMissBranch(); | 2284 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2059 if (maybe_result->IsFailure()) return maybe_result; | 2285 if (maybe_result->IsFailure()) return maybe_result; |
| 2060 | 2286 |
| 2061 // Return the generated code. | 2287 // Return the generated code. |
| 2062 return GetCode(function); | 2288 return TryGetCode(function); |
| 2063 } | 2289 } |
| 2064 | 2290 |
| 2065 | 2291 |
| 2066 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, | 2292 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, |
| 2067 JSObject* holder, | 2293 JSObject* holder, |
| 2068 JSFunction* function, | 2294 JSFunction* function, |
| 2069 String* name, | 2295 String* name, |
| 2070 CheckType check) { | 2296 CheckType check) { |
| 2071 // ----------- S t a t e ------------- | 2297 // ----------- S t a t e ------------- |
| 2072 // rcx : function name | 2298 // rcx : function name |
| 2073 // rsp[0] : return address | 2299 // rsp[0] : return address |
| 2074 // rsp[8] : argument argc | 2300 // rsp[8] : argument argc |
| 2075 // rsp[16] : argument argc - 1 | 2301 // rsp[16] : argument argc - 1 |
| 2076 // ... | 2302 // ... |
| 2077 // rsp[argc * 8] : argument 1 | 2303 // rsp[argc * 8] : argument 1 |
| 2078 // rsp[(argc + 1) * 8] : argument 0 = receiver | 2304 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 2079 // ----------------------------------- | 2305 // ----------------------------------- |
| 2080 | 2306 |
| 2081 if (HasCustomCallGenerator(function)) { | 2307 if (HasCustomCallGenerator(function)) { |
| 2082 MaybeObject* maybe_result = CompileCustomCall( | 2308 MaybeObject* maybe_result = CompileCustomCall( |
| 2083 object, holder, NULL, function, name); | 2309 object, holder, NULL, function, name); |
| 2084 Object* result; | 2310 Object* result; |
| 2085 if (!maybe_result->ToObject(&result)) return maybe_result; | 2311 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2086 // undefined means bail out to regular compiler. | 2312 // undefined means bail out to regular compiler. |
| 2087 if (!result->IsUndefined()) return result; | 2313 if (!result->IsUndefined()) return result; |
| 2088 } | 2314 } |
| 2089 | 2315 |
| 2090 Label miss; | 2316 Label miss; |
| 2091 | 2317 |
| 2092 GenerateNameCheck(name, &miss); | 2318 GenerateNameCheck(Handle<String>(name), &miss); |
| 2093 | 2319 |
| 2094 // Get the receiver from the stack. | 2320 // Get the receiver from the stack. |
| 2095 const int argc = arguments().immediate(); | 2321 const int argc = arguments().immediate(); |
| 2096 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2322 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2097 | 2323 |
| 2098 // Check that the receiver isn't a smi. | 2324 // Check that the receiver isn't a smi. |
| 2099 if (check != NUMBER_CHECK) { | 2325 if (check != NUMBER_CHECK) { |
| 2100 __ JumpIfSmi(rdx, &miss); | 2326 __ JumpIfSmi(rdx, &miss); |
| 2101 } | 2327 } |
| 2102 | 2328 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2179 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, | 2405 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
| 2180 rbx, rdx, rdi, name, &miss); | 2406 rbx, rdx, rdi, name, &miss); |
| 2181 } | 2407 } |
| 2182 break; | 2408 break; |
| 2183 } | 2409 } |
| 2184 | 2410 |
| 2185 default: | 2411 default: |
| 2186 UNREACHABLE(); | 2412 UNREACHABLE(); |
| 2187 } | 2413 } |
| 2188 | 2414 |
| 2189 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 2415 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2190 ? CALL_AS_FUNCTION | 2416 ? CALL_AS_FUNCTION |
| 2191 : CALL_AS_METHOD; | 2417 : CALL_AS_METHOD; |
| 2192 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2418 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 2193 NullCallWrapper(), call_kind); | 2419 NullCallWrapper(), call_kind); |
| 2194 | 2420 |
| 2195 // Handle call cache miss. | 2421 // Handle call cache miss. |
| 2196 __ bind(&miss); | 2422 __ bind(&miss); |
| 2197 MaybeObject* maybe_result = GenerateMissBranch(); | 2423 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2198 if (maybe_result->IsFailure()) return maybe_result; | 2424 if (maybe_result->IsFailure()) return maybe_result; |
| 2199 | 2425 |
| 2200 // Return the generated code. | 2426 // Return the generated code. |
| 2201 return GetCode(function); | 2427 return TryGetCode(function); |
| 2202 } | 2428 } |
| 2203 | 2429 |
| 2204 | 2430 |
| 2205 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, | 2431 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, |
| 2206 JSObject* holder, | 2432 JSObject* holder, |
| 2207 String* name) { | 2433 String* name) { |
| 2208 // ----------- S t a t e ------------- | 2434 // ----------- S t a t e ------------- |
| 2209 // rcx : function name | 2435 // rcx : function name |
| 2210 // rsp[0] : return address | 2436 // rsp[0] : return address |
| 2211 // rsp[8] : argument argc | 2437 // rsp[8] : argument argc |
| 2212 // rsp[16] : argument argc - 1 | 2438 // rsp[16] : argument argc - 1 |
| 2213 // ... | 2439 // ... |
| 2214 // rsp[argc * 8] : argument 1 | 2440 // rsp[argc * 8] : argument 1 |
| 2215 // rsp[(argc + 1) * 8] : argument 0 = receiver | 2441 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 2216 // ----------------------------------- | 2442 // ----------------------------------- |
| 2217 Label miss; | 2443 Label miss; |
| 2218 | 2444 |
| 2219 GenerateNameCheck(name, &miss); | 2445 GenerateNameCheck(Handle<String>(name), &miss); |
| 2220 | 2446 |
| 2221 // Get the number of arguments. | 2447 // Get the number of arguments. |
| 2222 const int argc = arguments().immediate(); | 2448 const int argc = arguments().immediate(); |
| 2223 | 2449 |
| 2224 LookupResult lookup; | 2450 LookupResult lookup(isolate()); |
| 2225 LookupPostInterceptor(holder, name, &lookup); | 2451 LookupPostInterceptor(holder, name, &lookup); |
| 2226 | 2452 |
| 2227 // Get the receiver from the stack. | 2453 // Get the receiver from the stack. |
| 2228 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2454 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2229 | 2455 |
| 2230 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_ic_state_); | 2456 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_); |
| 2231 MaybeObject* result = compiler.Compile(masm(), | 2457 MaybeObject* result = compiler.Compile(masm(), |
| 2232 object, | 2458 object, |
| 2233 holder, | 2459 holder, |
| 2234 name, | 2460 name, |
| 2235 &lookup, | 2461 &lookup, |
| 2236 rdx, | 2462 rdx, |
| 2237 rbx, | 2463 rbx, |
| 2238 rdi, | 2464 rdi, |
| 2239 rax, | 2465 rax, |
| 2240 &miss); | 2466 &miss); |
| 2241 if (result->IsFailure()) return result; | 2467 if (result->IsFailure()) return result; |
| 2242 | 2468 |
| 2243 // Restore receiver. | 2469 // Restore receiver. |
| 2244 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2470 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2245 | 2471 |
| 2246 // Check that the function really is a function. | 2472 // Check that the function really is a function. |
| 2247 __ JumpIfSmi(rax, &miss); | 2473 __ JumpIfSmi(rax, &miss); |
| 2248 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); | 2474 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); |
| 2249 __ j(not_equal, &miss); | 2475 __ j(not_equal, &miss); |
| 2250 | 2476 |
| 2251 // Patch the receiver on the stack with the global proxy if | 2477 // Patch the receiver on the stack with the global proxy if |
| 2252 // necessary. | 2478 // necessary. |
| 2253 if (object->IsGlobalObject()) { | 2479 if (object->IsGlobalObject()) { |
| 2254 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2480 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2255 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 2481 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 2256 } | 2482 } |
| 2257 | 2483 |
| 2258 // Invoke the function. | 2484 // Invoke the function. |
| 2259 __ movq(rdi, rax); | 2485 __ movq(rdi, rax); |
| 2260 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 2486 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2261 ? CALL_AS_FUNCTION | 2487 ? CALL_AS_FUNCTION |
| 2262 : CALL_AS_METHOD; | 2488 : CALL_AS_METHOD; |
| 2263 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, | 2489 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, |
| 2264 NullCallWrapper(), call_kind); | 2490 NullCallWrapper(), call_kind); |
| 2265 | 2491 |
| 2266 // Handle load cache miss. | 2492 // Handle load cache miss. |
| 2267 __ bind(&miss); | 2493 __ bind(&miss); |
| 2268 MaybeObject* maybe_result = GenerateMissBranch(); | 2494 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2269 if (maybe_result->IsFailure()) return maybe_result; | 2495 if (maybe_result->IsFailure()) return maybe_result; |
| 2270 | 2496 |
| 2271 // Return the generated code. | 2497 // Return the generated code. |
| 2272 return GetCode(INTERCEPTOR, name); | 2498 return TryGetCode(INTERCEPTOR, name); |
| 2273 } | 2499 } |
| 2274 | 2500 |
| 2275 | 2501 |
| 2276 MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, | 2502 MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, |
| 2277 GlobalObject* holder, | 2503 GlobalObject* holder, |
| 2278 JSGlobalPropertyCell* cell, | 2504 JSGlobalPropertyCell* cell, |
| 2279 JSFunction* function, | 2505 JSFunction* function, |
| 2280 String* name) { | 2506 String* name) { |
| 2281 // ----------- S t a t e ------------- | 2507 // ----------- S t a t e ------------- |
| 2282 // rcx : function name | 2508 // rcx : function name |
| 2283 // rsp[0] : return address | 2509 // rsp[0] : return address |
| 2284 // rsp[8] : argument argc | 2510 // rsp[8] : argument argc |
| 2285 // rsp[16] : argument argc - 1 | 2511 // rsp[16] : argument argc - 1 |
| 2286 // ... | 2512 // ... |
| 2287 // rsp[argc * 8] : argument 1 | 2513 // rsp[argc * 8] : argument 1 |
| 2288 // rsp[(argc + 1) * 8] : argument 0 = receiver | 2514 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 2289 // ----------------------------------- | 2515 // ----------------------------------- |
| 2290 | 2516 |
| 2291 if (HasCustomCallGenerator(function)) { | 2517 if (HasCustomCallGenerator(function)) { |
| 2292 MaybeObject* maybe_result = CompileCustomCall( | 2518 MaybeObject* maybe_result = CompileCustomCall( |
| 2293 object, holder, cell, function, name); | 2519 object, holder, cell, function, name); |
| 2294 Object* result; | 2520 Object* result; |
| 2295 if (!maybe_result->ToObject(&result)) return maybe_result; | 2521 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2296 // undefined means bail out to regular compiler. | 2522 // undefined means bail out to regular compiler. |
| 2297 if (!result->IsUndefined()) return result; | 2523 if (!result->IsUndefined()) return result; |
| 2298 } | 2524 } |
| 2299 | 2525 |
| 2300 Label miss; | 2526 Label miss; |
| 2301 | 2527 |
| 2302 GenerateNameCheck(name, &miss); | 2528 GenerateNameCheck(Handle<String>(name), &miss); |
| 2303 | 2529 |
| 2304 // Get the number of arguments. | 2530 // Get the number of arguments. |
| 2305 const int argc = arguments().immediate(); | 2531 const int argc = arguments().immediate(); |
| 2306 | 2532 |
| 2307 GenerateGlobalReceiverCheck(object, holder, name, &miss); | 2533 GenerateGlobalReceiverCheck(object, holder, name, &miss); |
| 2308 | 2534 |
| 2309 GenerateLoadFunctionFromCell(cell, function, &miss); | 2535 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2310 | 2536 |
| 2311 // Patch the receiver on the stack with the global proxy. | 2537 // Patch the receiver on the stack with the global proxy. |
| 2312 if (object->IsGlobalObject()) { | 2538 if (object->IsGlobalObject()) { |
| 2313 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2539 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2314 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 2540 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 2315 } | 2541 } |
| 2316 | 2542 |
| 2317 // Setup the context (function already in rdi). | 2543 // Setup the context (function already in rdi). |
| 2318 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 2544 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 2319 | 2545 |
| 2320 // Jump to the cached code (tail call). | 2546 // Jump to the cached code (tail call). |
| 2321 Counters* counters = isolate()->counters(); | 2547 Counters* counters = isolate()->counters(); |
| 2322 __ IncrementCounter(counters->call_global_inline(), 1); | 2548 __ IncrementCounter(counters->call_global_inline(), 1); |
| 2323 ASSERT(function->is_compiled()); | |
| 2324 ParameterCount expected(function->shared()->formal_parameter_count()); | 2549 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2325 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 2550 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2326 ? CALL_AS_FUNCTION | 2551 ? CALL_AS_FUNCTION |
| 2327 : CALL_AS_METHOD; | 2552 : CALL_AS_METHOD; |
| 2328 if (V8::UseCrankshaft()) { | 2553 // We call indirectly through the code field in the function to |
| 2329 // TODO(kasperl): For now, we always call indirectly through the | 2554 // allow recompilation to take effect without changing any of the |
| 2330 // code field in the function to allow recompilation to take effect | 2555 // call sites. |
| 2331 // without changing any of the call sites. | 2556 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
| 2332 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 2557 __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION, |
| 2333 __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION, | 2558 NullCallWrapper(), call_kind); |
| 2334 NullCallWrapper(), call_kind); | 2559 |
| 2335 } else { | |
| 2336 Handle<Code> code(function->code()); | |
| 2337 __ InvokeCode(code, expected, arguments(), | |
| 2338 RelocInfo::CODE_TARGET, JUMP_FUNCTION, | |
| 2339 NullCallWrapper(), call_kind); | |
| 2340 } | |
| 2341 // Handle call cache miss. | 2560 // Handle call cache miss. |
| 2342 __ bind(&miss); | 2561 __ bind(&miss); |
| 2343 __ IncrementCounter(counters->call_global_inline_miss(), 1); | 2562 __ IncrementCounter(counters->call_global_inline_miss(), 1); |
| 2344 MaybeObject* maybe_result = GenerateMissBranch(); | 2563 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2345 if (maybe_result->IsFailure()) return maybe_result; | 2564 if (maybe_result->IsFailure()) return maybe_result; |
| 2346 | 2565 |
| 2347 // Return the generated code. | 2566 // Return the generated code. |
| 2348 return GetCode(NORMAL, name); | 2567 return TryGetCode(NORMAL, name); |
| 2349 } | 2568 } |
| 2350 | 2569 |
| 2351 | 2570 |
| 2352 MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, | 2571 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, |
| 2353 int index, | 2572 int index, |
| 2354 Map* transition, | 2573 Handle<Map> transition, |
| 2355 String* name) { | 2574 Handle<String> name) { |
| 2356 // ----------- S t a t e ------------- | 2575 // ----------- S t a t e ------------- |
| 2357 // -- rax : value | 2576 // -- rax : value |
| 2358 // -- rcx : name | 2577 // -- rcx : name |
| 2359 // -- rdx : receiver | 2578 // -- rdx : receiver |
| 2360 // -- rsp[0] : return address | 2579 // -- rsp[0] : return address |
| 2361 // ----------------------------------- | 2580 // ----------------------------------- |
| 2362 Label miss; | 2581 Label miss; |
| 2363 | 2582 |
| 2364 // Generate store field code. Preserves receiver and name on jump to miss. | 2583 // Generate store field code. Preserves receiver and name on jump to miss. |
| 2365 GenerateStoreField(masm(), | 2584 GenerateStoreField(masm(), object, index, transition, rdx, rcx, rbx, &miss); |
| 2366 object, | |
| 2367 index, | |
| 2368 transition, | |
| 2369 rdx, rcx, rbx, | |
| 2370 &miss); | |
| 2371 | 2585 |
| 2372 // Handle store cache miss. | 2586 // Handle store cache miss. |
| 2373 __ bind(&miss); | 2587 __ bind(&miss); |
| 2374 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2588 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
| 2375 __ Jump(ic, RelocInfo::CODE_TARGET); | 2589 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 2376 | 2590 |
| 2377 // Return the generated code. | 2591 // Return the generated code. |
| 2378 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2592 return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); |
| 2379 } | 2593 } |
| 2380 | 2594 |
| 2381 | 2595 |
| 2382 MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, | 2596 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2383 AccessorInfo* callback, | 2597 Handle<JSObject> object, |
| 2384 String* name) { | 2598 Handle<AccessorInfo> callback, |
| 2599 Handle<String> name) { |
| 2385 // ----------- S t a t e ------------- | 2600 // ----------- S t a t e ------------- |
| 2386 // -- rax : value | 2601 // -- rax : value |
| 2387 // -- rcx : name | 2602 // -- rcx : name |
| 2388 // -- rdx : receiver | 2603 // -- rdx : receiver |
| 2389 // -- rsp[0] : return address | 2604 // -- rsp[0] : return address |
| 2390 // ----------------------------------- | 2605 // ----------------------------------- |
| 2391 Label miss; | 2606 Label miss; |
| 2392 | 2607 |
| 2393 // Check that the object isn't a smi. | 2608 // Check that the object isn't a smi. |
| 2394 __ JumpIfSmi(rdx, &miss); | 2609 __ JumpIfSmi(rdx, &miss); |
| 2395 | 2610 |
| 2396 // Check that the map of the object hasn't changed. | 2611 // Check that the map of the object hasn't changed. |
| 2397 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), | 2612 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), |
| 2398 Handle<Map>(object->map())); | 2613 Handle<Map>(object->map())); |
| 2399 __ j(not_equal, &miss); | 2614 __ j(not_equal, &miss); |
| 2400 | 2615 |
| 2401 // Perform global security token check if needed. | 2616 // Perform global security token check if needed. |
| 2402 if (object->IsJSGlobalProxy()) { | 2617 if (object->IsJSGlobalProxy()) { |
| 2403 __ CheckAccessGlobalProxy(rdx, rbx, &miss); | 2618 __ CheckAccessGlobalProxy(rdx, rbx, &miss); |
| 2404 } | 2619 } |
| 2405 | 2620 |
| 2406 // Stub never generated for non-global objects that require access | 2621 // Stub never generated for non-global objects that require access |
| 2407 // checks. | 2622 // checks. |
| 2408 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 2623 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 2409 | 2624 |
| 2410 __ pop(rbx); // remove the return address | 2625 __ pop(rbx); // remove the return address |
| 2411 __ push(rdx); // receiver | 2626 __ push(rdx); // receiver |
| 2412 __ Push(Handle<AccessorInfo>(callback)); // callback info | 2627 __ Push(callback); // callback info |
| 2413 __ push(rcx); // name | 2628 __ push(rcx); // name |
| 2414 __ push(rax); // value | 2629 __ push(rax); // value |
| 2415 __ push(rbx); // restore return address | 2630 __ push(rbx); // restore return address |
| 2416 | 2631 |
| 2417 // Do tail-call to the runtime system. | 2632 // Do tail-call to the runtime system. |
| 2418 ExternalReference store_callback_property = | 2633 ExternalReference store_callback_property = |
| 2419 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 2634 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 2420 __ TailCallExternalReference(store_callback_property, 4, 1); | 2635 __ TailCallExternalReference(store_callback_property, 4, 1); |
| 2421 | 2636 |
| 2422 // Handle store cache miss. | 2637 // Handle store cache miss. |
| 2423 __ bind(&miss); | 2638 __ bind(&miss); |
| 2424 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2639 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
| 2425 __ Jump(ic, RelocInfo::CODE_TARGET); | 2640 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 2426 | 2641 |
| 2427 // Return the generated code. | 2642 // Return the generated code. |
| 2428 return GetCode(CALLBACKS, name); | 2643 return GetCode(CALLBACKS, name); |
| 2429 } | 2644 } |
| 2430 | 2645 |
| 2431 | 2646 |
| 2432 MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, | 2647 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( |
| 2433 String* name) { | 2648 Handle<JSObject> receiver, |
| 2649 Handle<String> name) { |
| 2434 // ----------- S t a t e ------------- | 2650 // ----------- S t a t e ------------- |
| 2435 // -- rax : value | 2651 // -- rax : value |
| 2436 // -- rcx : name | 2652 // -- rcx : name |
| 2437 // -- rdx : receiver | 2653 // -- rdx : receiver |
| 2438 // -- rsp[0] : return address | 2654 // -- rsp[0] : return address |
| 2439 // ----------------------------------- | 2655 // ----------------------------------- |
| 2440 Label miss; | 2656 Label miss; |
| 2441 | 2657 |
| 2442 // Check that the object isn't a smi. | 2658 // Check that the object isn't a smi. |
| 2443 __ JumpIfSmi(rdx, &miss); | 2659 __ JumpIfSmi(rdx, &miss); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2471 // Handle store cache miss. | 2687 // Handle store cache miss. |
| 2472 __ bind(&miss); | 2688 __ bind(&miss); |
| 2473 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2689 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
| 2474 __ Jump(ic, RelocInfo::CODE_TARGET); | 2690 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 2475 | 2691 |
| 2476 // Return the generated code. | 2692 // Return the generated code. |
| 2477 return GetCode(INTERCEPTOR, name); | 2693 return GetCode(INTERCEPTOR, name); |
| 2478 } | 2694 } |
| 2479 | 2695 |
| 2480 | 2696 |
| 2481 MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, | 2697 Handle<Code> StoreStubCompiler::CompileStoreGlobal( |
| 2482 JSGlobalPropertyCell* cell, | 2698 Handle<GlobalObject> object, |
| 2483 String* name) { | 2699 Handle<JSGlobalPropertyCell> cell, |
| 2700 Handle<String> name) { |
| 2484 // ----------- S t a t e ------------- | 2701 // ----------- S t a t e ------------- |
| 2485 // -- rax : value | 2702 // -- rax : value |
| 2486 // -- rcx : name | 2703 // -- rcx : name |
| 2487 // -- rdx : receiver | 2704 // -- rdx : receiver |
| 2488 // -- rsp[0] : return address | 2705 // -- rsp[0] : return address |
| 2489 // ----------------------------------- | 2706 // ----------------------------------- |
| 2490 Label miss; | 2707 Label miss; |
| 2491 | 2708 |
| 2492 // Check that the map of the global has not changed. | 2709 // Check that the map of the global has not changed. |
| 2493 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), | 2710 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), |
| 2494 Handle<Map>(object->map())); | 2711 Handle<Map>(object->map())); |
| 2495 __ j(not_equal, &miss); | 2712 __ j(not_equal, &miss); |
| 2496 | 2713 |
| 2497 // Compute the cell operand to use. | 2714 // Compute the cell operand to use. |
| 2498 __ Move(rbx, Handle<JSGlobalPropertyCell>(cell)); | 2715 __ Move(rbx, cell); |
| 2499 Operand cell_operand = FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset); | 2716 Operand cell_operand = FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset); |
| 2500 | 2717 |
| 2501 // Check that the value in the cell is not the hole. If it is, this | 2718 // Check that the value in the cell is not the hole. If it is, this |
| 2502 // cell could have been deleted and reintroducing the global needs | 2719 // cell could have been deleted and reintroducing the global needs |
| 2503 // to update the property details in the property dictionary of the | 2720 // to update the property details in the property dictionary of the |
| 2504 // global object. We bail out to the runtime system to do that. | 2721 // global object. We bail out to the runtime system to do that. |
| 2505 __ CompareRoot(cell_operand, Heap::kTheHoleValueRootIndex); | 2722 __ CompareRoot(cell_operand, Heap::kTheHoleValueRootIndex); |
| 2506 __ j(equal, &miss); | 2723 __ j(equal, &miss); |
| 2507 | 2724 |
| 2508 // Store the value in the cell. | 2725 // Store the value in the cell. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2532 __ bind(&miss); | 2749 __ bind(&miss); |
| 2533 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); | 2750 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); |
| 2534 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2751 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
| 2535 __ Jump(ic, RelocInfo::CODE_TARGET); | 2752 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 2536 | 2753 |
| 2537 // Return the generated code. | 2754 // Return the generated code. |
| 2538 return GetCode(NORMAL, name); | 2755 return GetCode(NORMAL, name); |
| 2539 } | 2756 } |
| 2540 | 2757 |
| 2541 | 2758 |
| 2542 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, | 2759 Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, |
| 2543 int index, | 2760 int index, |
| 2544 Map* transition, | 2761 Handle<Map> transition, |
| 2545 String* name) { | 2762 Handle<String> name) { |
| 2546 // ----------- S t a t e ------------- | 2763 // ----------- S t a t e ------------- |
| 2547 // -- rax : value | 2764 // -- rax : value |
| 2548 // -- rcx : key | 2765 // -- rcx : key |
| 2549 // -- rdx : receiver | 2766 // -- rdx : receiver |
| 2550 // -- rsp[0] : return address | 2767 // -- rsp[0] : return address |
| 2551 // ----------------------------------- | 2768 // ----------------------------------- |
| 2552 Label miss; | 2769 Label miss; |
| 2553 | 2770 |
| 2554 Counters* counters = isolate()->counters(); | 2771 Counters* counters = isolate()->counters(); |
| 2555 __ IncrementCounter(counters->keyed_store_field(), 1); | 2772 __ IncrementCounter(counters->keyed_store_field(), 1); |
| 2556 | 2773 |
| 2557 // Check that the name has not changed. | 2774 // Check that the name has not changed. |
| 2558 __ Cmp(rcx, Handle<String>(name)); | 2775 __ Cmp(rcx, name); |
| 2559 __ j(not_equal, &miss); | 2776 __ j(not_equal, &miss); |
| 2560 | 2777 |
| 2561 // Generate store field code. Preserves receiver and name on jump to miss. | 2778 // Generate store field code. Preserves receiver and name on jump to miss. |
| 2562 GenerateStoreField(masm(), | 2779 GenerateStoreField(masm(), object, index, transition, rdx, rcx, rbx, &miss); |
| 2563 object, | |
| 2564 index, | |
| 2565 transition, | |
| 2566 rdx, rcx, rbx, | |
| 2567 &miss); | |
| 2568 | 2780 |
| 2569 // Handle store cache miss. | 2781 // Handle store cache miss. |
| 2570 __ bind(&miss); | 2782 __ bind(&miss); |
| 2571 __ DecrementCounter(counters->keyed_store_field(), 1); | 2783 __ DecrementCounter(counters->keyed_store_field(), 1); |
| 2572 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2784 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 2573 __ Jump(ic, RelocInfo::CODE_TARGET); | 2785 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 2574 | 2786 |
| 2575 // Return the generated code. | 2787 // Return the generated code. |
| 2576 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2788 return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); |
| 2577 } | 2789 } |
| 2578 | 2790 |
| 2579 | 2791 |
| 2580 MaybeObject* KeyedStoreStubCompiler::CompileStoreElement(Map* receiver_map) { | 2792 Handle<Code> KeyedStoreStubCompiler::CompileStoreElement( |
| 2793 Handle<Map> receiver_map) { |
| 2581 // ----------- S t a t e ------------- | 2794 // ----------- S t a t e ------------- |
| 2582 // -- rax : value | 2795 // -- rax : value |
| 2583 // -- rcx : key | 2796 // -- rcx : key |
| 2584 // -- rdx : receiver | 2797 // -- rdx : receiver |
| 2585 // -- rsp[0] : return address | 2798 // -- rsp[0] : return address |
| 2586 // ----------------------------------- | 2799 // ----------------------------------- |
| 2587 Code* stub; | 2800 |
| 2588 ElementsKind elements_kind = receiver_map->elements_kind(); | 2801 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 2589 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 2802 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| 2590 MaybeObject* maybe_stub = | 2803 Handle<Code> stub = |
| 2591 KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode(); | 2804 KeyedStoreElementStub(is_js_array, elements_kind).GetCode(); |
| 2592 if (!maybe_stub->To(&stub)) return maybe_stub; | 2805 |
| 2593 __ DispatchMap(rdx, | 2806 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); |
| 2594 Handle<Map>(receiver_map), | |
| 2595 Handle<Code>(stub), | |
| 2596 DO_SMI_CHECK); | |
| 2597 | 2807 |
| 2598 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2808 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 2599 __ jmp(ic, RelocInfo::CODE_TARGET); | 2809 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2600 | 2810 |
| 2601 // Return the generated code. | 2811 // Return the generated code. |
| 2602 return GetCode(NORMAL, NULL); | 2812 return GetCode(NORMAL, factory()->empty_string()); |
| 2603 } | 2813 } |
| 2604 | 2814 |
| 2605 | 2815 |
| 2606 MaybeObject* KeyedStoreStubCompiler::CompileStorePolymorphic( | 2816 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( |
| 2607 MapList* receiver_maps, | 2817 MapHandleList* receiver_maps, |
| 2608 CodeList* handler_stubs, | 2818 CodeHandleList* handler_stubs, |
| 2609 MapList* transitioned_maps) { | 2819 MapHandleList* transitioned_maps) { |
| 2610 // ----------- S t a t e ------------- | 2820 // ----------- S t a t e ------------- |
| 2611 // -- rax : value | 2821 // -- rax : value |
| 2612 // -- rcx : key | 2822 // -- rcx : key |
| 2613 // -- rdx : receiver | 2823 // -- rdx : receiver |
| 2614 // -- rsp[0] : return address | 2824 // -- rsp[0] : return address |
| 2615 // ----------------------------------- | 2825 // ----------------------------------- |
| 2616 Label miss; | 2826 Label miss; |
| 2617 __ JumpIfSmi(rdx, &miss, Label::kNear); | 2827 __ JumpIfSmi(rdx, &miss, Label::kNear); |
| 2618 | 2828 |
| 2619 __ movq(rdi, FieldOperand(rdx, HeapObject::kMapOffset)); | 2829 __ movq(rdi, FieldOperand(rdx, HeapObject::kMapOffset)); |
| 2620 int receiver_count = receiver_maps->length(); | 2830 int receiver_count = receiver_maps->length(); |
| 2621 for (int i = 0; i < receiver_count; ++i) { | 2831 for (int i = 0; i < receiver_count; ++i) { |
| 2622 // Check map and tail call if there's a match | 2832 // Check map and tail call if there's a match |
| 2623 Handle<Map> map(receiver_maps->at(i)); | 2833 __ Cmp(rdi, receiver_maps->at(i)); |
| 2624 __ Cmp(rdi, map); | 2834 if (transitioned_maps->at(i).is_null()) { |
| 2625 if (transitioned_maps->at(i) == NULL) { | 2835 __ j(equal, handler_stubs->at(i), RelocInfo::CODE_TARGET); |
| 2626 __ j(equal, Handle<Code>(handler_stubs->at(i)), RelocInfo::CODE_TARGET); | |
| 2627 } else { | 2836 } else { |
| 2628 Label next_map; | 2837 Label next_map; |
| 2629 __ j(not_equal, &next_map, Label::kNear); | 2838 __ j(not_equal, &next_map, Label::kNear); |
| 2630 __ movq(rbx, | 2839 __ movq(rbx, transitioned_maps->at(i), RelocInfo::EMBEDDED_OBJECT); |
| 2631 Handle<Map>(transitioned_maps->at(i)), | 2840 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); |
| 2632 RelocInfo::EMBEDDED_OBJECT); | |
| 2633 __ jmp(Handle<Code>(handler_stubs->at(i)), RelocInfo::CODE_TARGET); | |
| 2634 __ bind(&next_map); | 2841 __ bind(&next_map); |
| 2635 } | 2842 } |
| 2636 } | 2843 } |
| 2637 | 2844 |
| 2638 __ bind(&miss); | 2845 __ bind(&miss); |
| 2639 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2846 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 2640 __ jmp(ic, RelocInfo::CODE_TARGET); | 2847 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2641 | 2848 |
| 2642 // Return the generated code. | 2849 // Return the generated code. |
| 2643 return GetCode(NORMAL, NULL, MEGAMORPHIC); | 2850 return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); |
| 2644 } | 2851 } |
| 2645 | 2852 |
| 2646 | 2853 |
| 2647 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, | 2854 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, |
| 2648 JSObject* object, | 2855 Handle<JSObject> object, |
| 2649 JSObject* last) { | 2856 Handle<JSObject> last) { |
| 2650 // ----------- S t a t e ------------- | 2857 // ----------- S t a t e ------------- |
| 2651 // -- rax : receiver | 2858 // -- rax : receiver |
| 2652 // -- rcx : name | 2859 // -- rcx : name |
| 2653 // -- rsp[0] : return address | 2860 // -- rsp[0] : return address |
| 2654 // ----------------------------------- | 2861 // ----------------------------------- |
| 2655 Label miss; | 2862 Label miss; |
| 2656 | 2863 |
| 2657 // Check that receiver is not a smi. | 2864 // Check that receiver is not a smi. |
| 2658 __ JumpIfSmi(rax, &miss); | 2865 __ JumpIfSmi(rax, &miss); |
| 2659 | 2866 |
| 2660 // Check the maps of the full prototype chain. Also check that | 2867 // Check the maps of the full prototype chain. Also check that |
| 2661 // global property cells up to (but not including) the last object | 2868 // global property cells up to (but not including) the last object |
| 2662 // in the prototype chain are empty. | 2869 // in the prototype chain are empty. |
| 2663 CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss); | 2870 CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss); |
| 2664 | 2871 |
| 2665 // If the last object in the prototype chain is a global object, | 2872 // If the last object in the prototype chain is a global object, |
| 2666 // check that the global property cell is empty. | 2873 // check that the global property cell is empty. |
| 2667 if (last->IsGlobalObject()) { | 2874 if (last->IsGlobalObject()) { |
| 2668 MaybeObject* cell = GenerateCheckPropertyCell(masm(), | 2875 GenerateCheckPropertyCell( |
| 2669 GlobalObject::cast(last), | 2876 masm(), Handle<GlobalObject>::cast(last), name, rdx, &miss); |
| 2670 name, | |
| 2671 rdx, | |
| 2672 &miss); | |
| 2673 if (cell->IsFailure()) { | |
| 2674 miss.Unuse(); | |
| 2675 return cell; | |
| 2676 } | |
| 2677 } | 2877 } |
| 2678 | 2878 |
| 2679 // Return undefined if maps of the full prototype chain are still the | 2879 // Return undefined if maps of the full prototype chain are still the |
| 2680 // same and no global property with this name contains a value. | 2880 // same and no global property with this name contains a value. |
| 2681 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 2881 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 2682 __ ret(0); | 2882 __ ret(0); |
| 2683 | 2883 |
| 2684 __ bind(&miss); | 2884 __ bind(&miss); |
| 2685 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2885 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2686 | 2886 |
| 2687 // Return the generated code. | 2887 // Return the generated code. |
| 2688 return GetCode(NONEXISTENT, heap()->empty_string()); | 2888 return GetCode(NONEXISTENT, factory()->empty_string()); |
| 2689 } | 2889 } |
| 2690 | 2890 |
| 2691 | 2891 |
| 2692 MaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object, | 2892 Handle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object, |
| 2693 JSObject* holder, | 2893 Handle<JSObject> holder, |
| 2694 int index, | 2894 int index, |
| 2695 String* name) { | 2895 Handle<String> name) { |
| 2696 // ----------- S t a t e ------------- | 2896 // ----------- S t a t e ------------- |
| 2697 // -- rax : receiver | 2897 // -- rax : receiver |
| 2698 // -- rcx : name | 2898 // -- rcx : name |
| 2699 // -- rsp[0] : return address | 2899 // -- rsp[0] : return address |
| 2700 // ----------------------------------- | 2900 // ----------------------------------- |
| 2701 Label miss; | 2901 Label miss; |
| 2702 | 2902 |
| 2703 GenerateLoadField(object, holder, rax, rbx, rdx, rdi, index, name, &miss); | 2903 GenerateLoadField(object, holder, rax, rbx, rdx, rdi, index, name, &miss); |
| 2704 __ bind(&miss); | 2904 __ bind(&miss); |
| 2705 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2905 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2724 rdi, callback, name, &miss); | 2924 rdi, callback, name, &miss); |
| 2725 if (result->IsFailure()) { | 2925 if (result->IsFailure()) { |
| 2726 miss.Unuse(); | 2926 miss.Unuse(); |
| 2727 return result; | 2927 return result; |
| 2728 } | 2928 } |
| 2729 | 2929 |
| 2730 __ bind(&miss); | 2930 __ bind(&miss); |
| 2731 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2931 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2732 | 2932 |
| 2733 // Return the generated code. | 2933 // Return the generated code. |
| 2734 return GetCode(CALLBACKS, name); | 2934 return TryGetCode(CALLBACKS, name); |
| 2735 } | 2935 } |
| 2736 | 2936 |
| 2737 | 2937 |
| 2738 MaybeObject* LoadStubCompiler::CompileLoadConstant(JSObject* object, | 2938 Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, |
| 2739 JSObject* holder, | 2939 Handle<JSObject> holder, |
| 2740 Object* value, | 2940 Handle<Object> value, |
| 2741 String* name) { | 2941 Handle<String> name) { |
| 2742 // ----------- S t a t e ------------- | 2942 // ----------- S t a t e ------------- |
| 2743 // -- rax : receiver | 2943 // -- rax : receiver |
| 2744 // -- rcx : name | 2944 // -- rcx : name |
| 2745 // -- rsp[0] : return address | 2945 // -- rsp[0] : return address |
| 2746 // ----------------------------------- | 2946 // ----------------------------------- |
| 2747 Label miss; | 2947 Label miss; |
| 2748 | 2948 |
| 2749 GenerateLoadConstant(object, holder, rax, rbx, rdx, rdi, value, name, &miss); | 2949 GenerateLoadConstant(object, holder, rax, rbx, rdx, rdi, value, name, &miss); |
| 2750 __ bind(&miss); | 2950 __ bind(&miss); |
| 2751 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2951 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2752 | 2952 |
| 2753 // Return the generated code. | 2953 // Return the generated code. |
| 2754 return GetCode(CONSTANT_FUNCTION, name); | 2954 return GetCode(CONSTANT_FUNCTION, name); |
| 2755 } | 2955 } |
| 2756 | 2956 |
| 2757 | 2957 |
| 2758 MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 2958 MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
| 2759 JSObject* holder, | 2959 JSObject* holder, |
| 2760 String* name) { | 2960 String* name) { |
| 2761 // ----------- S t a t e ------------- | 2961 // ----------- S t a t e ------------- |
| 2762 // -- rax : receiver | 2962 // -- rax : receiver |
| 2763 // -- rcx : name | 2963 // -- rcx : name |
| 2764 // -- rsp[0] : return address | 2964 // -- rsp[0] : return address |
| 2765 // ----------------------------------- | 2965 // ----------------------------------- |
| 2766 Label miss; | 2966 Label miss; |
| 2767 | 2967 |
| 2768 LookupResult lookup; | 2968 LookupResult lookup(isolate()); |
| 2769 LookupPostInterceptor(holder, name, &lookup); | 2969 LookupPostInterceptor(holder, name, &lookup); |
| 2770 | 2970 |
| 2771 // TODO(368): Compile in the whole chain: all the interceptors in | 2971 // TODO(368): Compile in the whole chain: all the interceptors in |
| 2772 // prototypes and ultimate answer. | 2972 // prototypes and ultimate answer. |
| 2773 GenerateLoadInterceptor(receiver, | 2973 GenerateLoadInterceptor(receiver, |
| 2774 holder, | 2974 holder, |
| 2775 &lookup, | 2975 &lookup, |
| 2776 rax, | 2976 rax, |
| 2777 rcx, | 2977 rcx, |
| 2778 rdx, | 2978 rdx, |
| 2779 rbx, | 2979 rbx, |
| 2780 rdi, | 2980 rdi, |
| 2781 name, | 2981 name, |
| 2782 &miss); | 2982 &miss); |
| 2783 | 2983 |
| 2784 __ bind(&miss); | 2984 __ bind(&miss); |
| 2785 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2985 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2786 | 2986 |
| 2787 // Return the generated code. | 2987 // Return the generated code. |
| 2788 return GetCode(INTERCEPTOR, name); | 2988 return TryGetCode(INTERCEPTOR, name); |
| 2789 } | 2989 } |
| 2790 | 2990 |
| 2791 | 2991 |
| 2792 MaybeObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object, | 2992 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
| 2793 GlobalObject* holder, | 2993 Handle<JSObject> object, |
| 2794 JSGlobalPropertyCell* cell, | 2994 Handle<GlobalObject> holder, |
| 2795 String* name, | 2995 Handle<JSGlobalPropertyCell> cell, |
| 2796 bool is_dont_delete) { | 2996 Handle<String> name, |
| 2997 bool is_dont_delete) { |
| 2797 // ----------- S t a t e ------------- | 2998 // ----------- S t a t e ------------- |
| 2798 // -- rax : receiver | 2999 // -- rax : receiver |
| 2799 // -- rcx : name | 3000 // -- rcx : name |
| 2800 // -- rsp[0] : return address | 3001 // -- rsp[0] : return address |
| 2801 // ----------------------------------- | 3002 // ----------------------------------- |
| 2802 Label miss; | 3003 Label miss; |
| 2803 | 3004 |
| 2804 // If the object is the holder then we know that it's a global | 3005 // If the object is the holder then we know that it's a global |
| 2805 // object which can only happen for contextual loads. In this case, | 3006 // object which can only happen for contextual loads. In this case, |
| 2806 // the receiver cannot be a smi. | 3007 // the receiver cannot be a smi. |
| 2807 if (object != holder) { | 3008 if (!object.is_identical_to(holder)) { |
| 2808 __ JumpIfSmi(rax, &miss); | 3009 __ JumpIfSmi(rax, &miss); |
| 2809 } | 3010 } |
| 2810 | 3011 |
| 2811 // Check that the maps haven't changed. | 3012 // Check that the maps haven't changed. |
| 2812 CheckPrototypes(object, rax, holder, rbx, rdx, rdi, name, &miss); | 3013 CheckPrototypes(object, rax, holder, rbx, rdx, rdi, name, &miss); |
| 2813 | 3014 |
| 2814 // Get the value from the cell. | 3015 // Get the value from the cell. |
| 2815 __ Move(rbx, Handle<JSGlobalPropertyCell>(cell)); | 3016 __ Move(rbx, cell); |
| 2816 __ movq(rbx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset)); | 3017 __ movq(rbx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset)); |
| 2817 | 3018 |
| 2818 // Check for deleted property if property can actually be deleted. | 3019 // Check for deleted property if property can actually be deleted. |
| 2819 if (!is_dont_delete) { | 3020 if (!is_dont_delete) { |
| 2820 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); | 3021 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); |
| 2821 __ j(equal, &miss); | 3022 __ j(equal, &miss); |
| 2822 } else if (FLAG_debug_code) { | 3023 } else if (FLAG_debug_code) { |
| 2823 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); | 3024 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); |
| 2824 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 3025 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
| 2825 } | 3026 } |
| 2826 | 3027 |
| 2827 Counters* counters = isolate()->counters(); | 3028 Counters* counters = isolate()->counters(); |
| 2828 __ IncrementCounter(counters->named_load_global_stub(), 1); | 3029 __ IncrementCounter(counters->named_load_global_stub(), 1); |
| 2829 __ movq(rax, rbx); | 3030 __ movq(rax, rbx); |
| 2830 __ ret(0); | 3031 __ ret(0); |
| 2831 | 3032 |
| 2832 __ bind(&miss); | 3033 __ bind(&miss); |
| 2833 __ IncrementCounter(counters->named_load_global_stub_miss(), 1); | 3034 __ IncrementCounter(counters->named_load_global_stub_miss(), 1); |
| 2834 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3035 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2835 | 3036 |
| 2836 // Return the generated code. | 3037 // Return the generated code. |
| 2837 return GetCode(NORMAL, name); | 3038 return GetCode(NORMAL, name); |
| 2838 } | 3039 } |
| 2839 | 3040 |
| 2840 | 3041 |
| 2841 MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name, | 3042 Handle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name, |
| 2842 JSObject* receiver, | 3043 Handle<JSObject> receiver, |
| 2843 JSObject* holder, | 3044 Handle<JSObject> holder, |
| 2844 int index) { | 3045 int index) { |
| 2845 // ----------- S t a t e ------------- | 3046 // ----------- S t a t e ------------- |
| 2846 // -- rax : key | 3047 // -- rax : key |
| 2847 // -- rdx : receiver | 3048 // -- rdx : receiver |
| 2848 // -- rsp[0] : return address | 3049 // -- rsp[0] : return address |
| 2849 // ----------------------------------- | 3050 // ----------------------------------- |
| 2850 Label miss; | 3051 Label miss; |
| 2851 | 3052 |
| 2852 Counters* counters = isolate()->counters(); | 3053 Counters* counters = isolate()->counters(); |
| 2853 __ IncrementCounter(counters->keyed_load_field(), 1); | 3054 __ IncrementCounter(counters->keyed_load_field(), 1); |
| 2854 | 3055 |
| 2855 // Check that the name has not changed. | 3056 // Check that the name has not changed. |
| 2856 __ Cmp(rax, Handle<String>(name)); | 3057 __ Cmp(rax, name); |
| 2857 __ j(not_equal, &miss); | 3058 __ j(not_equal, &miss); |
| 2858 | 3059 |
| 2859 GenerateLoadField(receiver, holder, rdx, rbx, rcx, rdi, index, name, &miss); | 3060 GenerateLoadField(receiver, holder, rdx, rbx, rcx, rdi, index, name, &miss); |
| 2860 | 3061 |
| 2861 __ bind(&miss); | 3062 __ bind(&miss); |
| 2862 __ DecrementCounter(counters->keyed_load_field(), 1); | 3063 __ DecrementCounter(counters->keyed_load_field(), 1); |
| 2863 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3064 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 2864 | 3065 |
| 2865 // Return the generated code. | 3066 // Return the generated code. |
| 2866 return GetCode(FIELD, name); | 3067 return GetCode(FIELD, name); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2892 miss.Unuse(); | 3093 miss.Unuse(); |
| 2893 return result; | 3094 return result; |
| 2894 } | 3095 } |
| 2895 | 3096 |
| 2896 __ bind(&miss); | 3097 __ bind(&miss); |
| 2897 | 3098 |
| 2898 __ DecrementCounter(counters->keyed_load_callback(), 1); | 3099 __ DecrementCounter(counters->keyed_load_callback(), 1); |
| 2899 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3100 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 2900 | 3101 |
| 2901 // Return the generated code. | 3102 // Return the generated code. |
| 2902 return GetCode(CALLBACKS, name); | 3103 return TryGetCode(CALLBACKS, name); |
| 2903 } | 3104 } |
| 2904 | 3105 |
| 2905 | 3106 |
| 2906 MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name, | 3107 Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant( |
| 2907 JSObject* receiver, | 3108 Handle<String> name, |
| 2908 JSObject* holder, | 3109 Handle<JSObject> receiver, |
| 2909 Object* value) { | 3110 Handle<JSObject> holder, |
| 3111 Handle<Object> value) { |
| 2910 // ----------- S t a t e ------------- | 3112 // ----------- S t a t e ------------- |
| 2911 // -- rax : key | 3113 // -- rax : key |
| 2912 // -- rdx : receiver | 3114 // -- rdx : receiver |
| 2913 // -- rsp[0] : return address | 3115 // -- rsp[0] : return address |
| 2914 // ----------------------------------- | 3116 // ----------------------------------- |
| 2915 Label miss; | 3117 Label miss; |
| 2916 | 3118 |
| 2917 Counters* counters = isolate()->counters(); | 3119 Counters* counters = isolate()->counters(); |
| 2918 __ IncrementCounter(counters->keyed_load_constant_function(), 1); | 3120 __ IncrementCounter(counters->keyed_load_constant_function(), 1); |
| 2919 | 3121 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2942 // ----------------------------------- | 3144 // ----------------------------------- |
| 2943 Label miss; | 3145 Label miss; |
| 2944 | 3146 |
| 2945 Counters* counters = isolate()->counters(); | 3147 Counters* counters = isolate()->counters(); |
| 2946 __ IncrementCounter(counters->keyed_load_interceptor(), 1); | 3148 __ IncrementCounter(counters->keyed_load_interceptor(), 1); |
| 2947 | 3149 |
| 2948 // Check that the name has not changed. | 3150 // Check that the name has not changed. |
| 2949 __ Cmp(rax, Handle<String>(name)); | 3151 __ Cmp(rax, Handle<String>(name)); |
| 2950 __ j(not_equal, &miss); | 3152 __ j(not_equal, &miss); |
| 2951 | 3153 |
| 2952 LookupResult lookup; | 3154 LookupResult lookup(isolate()); |
| 2953 LookupPostInterceptor(holder, name, &lookup); | 3155 LookupPostInterceptor(holder, name, &lookup); |
| 2954 GenerateLoadInterceptor(receiver, | 3156 GenerateLoadInterceptor(receiver, |
| 2955 holder, | 3157 holder, |
| 2956 &lookup, | 3158 &lookup, |
| 2957 rdx, | 3159 rdx, |
| 2958 rax, | 3160 rax, |
| 2959 rcx, | 3161 rcx, |
| 2960 rbx, | 3162 rbx, |
| 2961 rdi, | 3163 rdi, |
| 2962 name, | 3164 name, |
| 2963 &miss); | 3165 &miss); |
| 2964 __ bind(&miss); | 3166 __ bind(&miss); |
| 2965 __ DecrementCounter(counters->keyed_load_interceptor(), 1); | 3167 __ DecrementCounter(counters->keyed_load_interceptor(), 1); |
| 2966 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3168 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 2967 | 3169 |
| 2968 // Return the generated code. | 3170 // Return the generated code. |
| 2969 return GetCode(INTERCEPTOR, name); | 3171 return TryGetCode(INTERCEPTOR, name); |
| 2970 } | 3172 } |
| 2971 | 3173 |
| 2972 | 3174 |
| 2973 MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { | 3175 Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( |
| 3176 Handle<String> name) { |
| 2974 // ----------- S t a t e ------------- | 3177 // ----------- S t a t e ------------- |
| 2975 // -- rax : key | 3178 // -- rax : key |
| 2976 // -- rdx : receiver | 3179 // -- rdx : receiver |
| 2977 // -- rsp[0] : return address | 3180 // -- rsp[0] : return address |
| 2978 // ----------------------------------- | 3181 // ----------------------------------- |
| 2979 Label miss; | 3182 Label miss; |
| 2980 | 3183 |
| 2981 Counters* counters = isolate()->counters(); | 3184 Counters* counters = isolate()->counters(); |
| 2982 __ IncrementCounter(counters->keyed_load_array_length(), 1); | 3185 __ IncrementCounter(counters->keyed_load_array_length(), 1); |
| 2983 | 3186 |
| 2984 // Check that the name has not changed. | 3187 // Check that the name has not changed. |
| 2985 __ Cmp(rax, Handle<String>(name)); | 3188 __ Cmp(rax, name); |
| 2986 __ j(not_equal, &miss); | 3189 __ j(not_equal, &miss); |
| 2987 | 3190 |
| 2988 GenerateLoadArrayLength(masm(), rdx, rcx, &miss); | 3191 GenerateLoadArrayLength(masm(), rdx, rcx, &miss); |
| 2989 __ bind(&miss); | 3192 __ bind(&miss); |
| 2990 __ DecrementCounter(counters->keyed_load_array_length(), 1); | 3193 __ DecrementCounter(counters->keyed_load_array_length(), 1); |
| 2991 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3194 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 2992 | 3195 |
| 2993 // Return the generated code. | 3196 // Return the generated code. |
| 2994 return GetCode(CALLBACKS, name); | 3197 return GetCode(CALLBACKS, name); |
| 2995 } | 3198 } |
| 2996 | 3199 |
| 2997 | 3200 |
| 2998 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { | 3201 Handle<Code> KeyedLoadStubCompiler::CompileLoadStringLength( |
| 3202 Handle<String> name) { |
| 2999 // ----------- S t a t e ------------- | 3203 // ----------- S t a t e ------------- |
| 3000 // -- rax : key | 3204 // -- rax : key |
| 3001 // -- rdx : receiver | 3205 // -- rdx : receiver |
| 3002 // -- rsp[0] : return address | 3206 // -- rsp[0] : return address |
| 3003 // ----------------------------------- | 3207 // ----------------------------------- |
| 3004 Label miss; | 3208 Label miss; |
| 3005 | 3209 |
| 3006 Counters* counters = isolate()->counters(); | 3210 Counters* counters = isolate()->counters(); |
| 3007 __ IncrementCounter(counters->keyed_load_string_length(), 1); | 3211 __ IncrementCounter(counters->keyed_load_string_length(), 1); |
| 3008 | 3212 |
| 3009 // Check that the name has not changed. | 3213 // Check that the name has not changed. |
| 3010 __ Cmp(rax, Handle<String>(name)); | 3214 __ Cmp(rax, name); |
| 3011 __ j(not_equal, &miss); | 3215 __ j(not_equal, &miss); |
| 3012 | 3216 |
| 3013 GenerateLoadStringLength(masm(), rdx, rcx, rbx, &miss, true); | 3217 GenerateLoadStringLength(masm(), rdx, rcx, rbx, &miss, true); |
| 3014 __ bind(&miss); | 3218 __ bind(&miss); |
| 3015 __ DecrementCounter(counters->keyed_load_string_length(), 1); | 3219 __ DecrementCounter(counters->keyed_load_string_length(), 1); |
| 3016 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3220 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3017 | 3221 |
| 3018 // Return the generated code. | 3222 // Return the generated code. |
| 3019 return GetCode(CALLBACKS, name); | 3223 return GetCode(CALLBACKS, name); |
| 3020 } | 3224 } |
| 3021 | 3225 |
| 3022 | 3226 |
| 3023 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { | 3227 Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype( |
| 3228 Handle<String> name) { |
| 3024 // ----------- S t a t e ------------- | 3229 // ----------- S t a t e ------------- |
| 3025 // -- rax : key | 3230 // -- rax : key |
| 3026 // -- rdx : receiver | 3231 // -- rdx : receiver |
| 3027 // -- rsp[0] : return address | 3232 // -- rsp[0] : return address |
| 3028 // ----------------------------------- | 3233 // ----------------------------------- |
| 3029 Label miss; | 3234 Label miss; |
| 3030 | 3235 |
| 3031 Counters* counters = isolate()->counters(); | 3236 Counters* counters = isolate()->counters(); |
| 3032 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); | 3237 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); |
| 3033 | 3238 |
| 3034 // Check that the name has not changed. | 3239 // Check that the name has not changed. |
| 3035 __ Cmp(rax, Handle<String>(name)); | 3240 __ Cmp(rax, name); |
| 3036 __ j(not_equal, &miss); | 3241 __ j(not_equal, &miss); |
| 3037 | 3242 |
| 3038 GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss); | 3243 GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss); |
| 3039 __ bind(&miss); | 3244 __ bind(&miss); |
| 3040 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); | 3245 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); |
| 3041 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3246 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3042 | 3247 |
| 3043 // Return the generated code. | 3248 // Return the generated code. |
| 3044 return GetCode(CALLBACKS, name); | 3249 return GetCode(CALLBACKS, name); |
| 3045 } | 3250 } |
| 3046 | 3251 |
| 3047 | 3252 |
| 3048 MaybeObject* KeyedLoadStubCompiler::CompileLoadElement(Map* receiver_map) { | 3253 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
| 3254 Handle<Map> receiver_map) { |
| 3049 // ----------- S t a t e ------------- | 3255 // ----------- S t a t e ------------- |
| 3050 // -- rax : key | 3256 // -- rax : key |
| 3051 // -- rdx : receiver | 3257 // -- rdx : receiver |
| 3052 // -- rsp[0] : return address | 3258 // -- rsp[0] : return address |
| 3053 // ----------------------------------- | 3259 // ----------------------------------- |
| 3054 Code* stub; | |
| 3055 ElementsKind elements_kind = receiver_map->elements_kind(); | 3260 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 3056 MaybeObject* maybe_stub = KeyedLoadElementStub(elements_kind).TryGetCode(); | 3261 Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); |
| 3057 if (!maybe_stub->To(&stub)) return maybe_stub; | 3262 |
| 3058 __ DispatchMap(rdx, | 3263 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); |
| 3059 Handle<Map>(receiver_map), | |
| 3060 Handle<Code>(stub), | |
| 3061 DO_SMI_CHECK); | |
| 3062 | 3264 |
| 3063 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); | 3265 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); |
| 3064 __ jmp(ic, RelocInfo::CODE_TARGET); | 3266 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 3065 | 3267 |
| 3066 // Return the generated code. | 3268 // Return the generated code. |
| 3067 return GetCode(NORMAL, NULL); | 3269 return GetCode(NORMAL, factory()->empty_string()); |
| 3068 } | 3270 } |
| 3069 | 3271 |
| 3070 | 3272 |
| 3071 MaybeObject* KeyedLoadStubCompiler::CompileLoadPolymorphic( | 3273 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( |
| 3072 MapList* receiver_maps, | 3274 MapHandleList* receiver_maps, |
| 3073 CodeList* handler_ics) { | 3275 CodeHandleList* handler_ics) { |
| 3074 // ----------- S t a t e ------------- | 3276 // ----------- S t a t e ------------- |
| 3075 // -- rax : key | 3277 // -- rax : key |
| 3076 // -- rdx : receiver | 3278 // -- rdx : receiver |
| 3077 // -- rsp[0] : return address | 3279 // -- rsp[0] : return address |
| 3078 // ----------------------------------- | 3280 // ----------------------------------- |
| 3079 Label miss; | 3281 Label miss; |
| 3080 __ JumpIfSmi(rdx, &miss); | 3282 __ JumpIfSmi(rdx, &miss); |
| 3081 | 3283 |
| 3082 Register map_reg = rbx; | 3284 Register map_reg = rbx; |
| 3083 __ movq(map_reg, FieldOperand(rdx, HeapObject::kMapOffset)); | 3285 __ movq(map_reg, FieldOperand(rdx, HeapObject::kMapOffset)); |
| 3084 int receiver_count = receiver_maps->length(); | 3286 int receiver_count = receiver_maps->length(); |
| 3085 for (int current = 0; current < receiver_count; ++current) { | 3287 for (int current = 0; current < receiver_count; ++current) { |
| 3086 // Check map and tail call if there's a match | 3288 // Check map and tail call if there's a match |
| 3087 Handle<Map> map(receiver_maps->at(current)); | 3289 __ Cmp(map_reg, receiver_maps->at(current)); |
| 3088 __ Cmp(map_reg, map); | 3290 __ j(equal, handler_ics->at(current), RelocInfo::CODE_TARGET); |
| 3089 __ j(equal, | |
| 3090 Handle<Code>(handler_ics->at(current)), | |
| 3091 RelocInfo::CODE_TARGET); | |
| 3092 } | 3291 } |
| 3093 | 3292 |
| 3094 __ bind(&miss); | 3293 __ bind(&miss); |
| 3095 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3294 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3096 | 3295 |
| 3097 // Return the generated code. | 3296 // Return the generated code. |
| 3098 return GetCode(NORMAL, NULL, MEGAMORPHIC); | 3297 return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); |
| 3099 } | 3298 } |
| 3100 | 3299 |
| 3101 | 3300 |
| 3102 // Specialized stub for constructing objects from functions which only have only | 3301 // Specialized stub for constructing objects from functions which only have only |
| 3103 // simple assignments of the form this.x = ...; in their body. | 3302 // simple assignments of the form this.x = ...; in their body. |
| 3104 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { | 3303 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { |
| 3105 // ----------- S t a t e ------------- | 3304 // ----------- S t a t e ------------- |
| 3106 // -- rax : argc | 3305 // -- rax : argc |
| 3107 // -- rdi : constructor | 3306 // -- rdi : constructor |
| 3108 // -- rsp[0] : return address | 3307 // -- rsp[0] : return address |
| (...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3804 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 4003 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3805 __ jmp(ic_miss, RelocInfo::CODE_TARGET); | 4004 __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
| 3806 } | 4005 } |
| 3807 | 4006 |
| 3808 | 4007 |
| 3809 #undef __ | 4008 #undef __ |
| 3810 | 4009 |
| 3811 } } // namespace v8::internal | 4010 } } // namespace v8::internal |
| 3812 | 4011 |
| 3813 #endif // V8_TARGET_ARCH_X64 | 4012 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |