Chromium Code Reviews| 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, | |
|
ulan
2011/10/24 16:28:25
Indentation is broken.
| |
| 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 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 801 } | 851 } |
| 802 | 852 |
| 803 // Return the value (register rax). | 853 // Return the value (register rax). |
| 804 __ ret(0); | 854 __ ret(0); |
| 805 } | 855 } |
| 806 | 856 |
| 807 | 857 |
| 808 // Generate code to check that a global property cell is empty. Create | 858 // 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 | 859 // the property cell at compilation time if no cell exists for the |
| 810 // property. | 860 // property. |
| 811 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell( | 861 static void GenerateCheckPropertyCell(MacroAssembler* masm, |
| 862 Handle<GlobalObject> global, | |
| 863 Handle<String> name, | |
| 864 Register scratch, | |
| 865 Label* miss) { | |
| 866 Handle<JSGlobalPropertyCell> cell = | |
| 867 GlobalObject::EnsurePropertyCell(global, name); | |
| 868 ASSERT(cell->value()->IsTheHole()); | |
| 869 __ Move(scratch, cell); | |
| 870 __ Cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), | |
| 871 masm->isolate()->factory()->the_hole_value()); | |
| 872 __ j(not_equal, miss); | |
| 873 } | |
| 874 | |
| 875 | |
| 876 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
| 877 // handlified. | |
| 878 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell( | |
| 812 MacroAssembler* masm, | 879 MacroAssembler* masm, |
| 813 GlobalObject* global, | 880 GlobalObject* global, |
| 814 String* name, | 881 String* name, |
| 815 Register scratch, | 882 Register scratch, |
| 816 Label* miss) { | 883 Label* miss) { |
| 817 Object* probe; | 884 Object* probe; |
| 818 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); | 885 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); |
| 819 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 886 if (!maybe_probe->ToObject(&probe)) return maybe_probe; |
| 820 } | 887 } |
| 821 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); | 888 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); |
| 822 ASSERT(cell->value()->IsTheHole()); | 889 ASSERT(cell->value()->IsTheHole()); |
| 823 __ Move(scratch, Handle<Object>(cell)); | 890 __ Move(scratch, Handle<Object>(cell)); |
| 824 __ Cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), | 891 __ Cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
| 825 masm->isolate()->factory()->the_hole_value()); | 892 masm->isolate()->factory()->the_hole_value()); |
| 826 __ j(not_equal, miss); | 893 __ j(not_equal, miss); |
| 827 return cell; | 894 return cell; |
| 828 } | 895 } |
| 829 | 896 |
| 830 | 897 |
| 898 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | |
| 899 // from object to (but not including) holder. | |
| 900 static void GenerateCheckPropertyCells(MacroAssembler* masm, | |
| 901 Handle<JSObject> object, | |
| 902 Handle<JSObject> holder, | |
| 903 Handle<String> name, | |
| 904 Register scratch, | |
| 905 Label* miss) { | |
| 906 Handle<JSObject> current = object; | |
| 907 while (!current.is_identical_to(holder)) { | |
| 908 if (current->IsGlobalObject()) { | |
| 909 GenerateCheckPropertyCell(masm, | |
| 910 Handle<GlobalObject>::cast(current), | |
| 911 name, | |
| 912 scratch, | |
| 913 miss); | |
| 914 } | |
| 915 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); | |
| 916 } | |
| 917 } | |
| 918 | |
| 919 | |
| 920 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
| 921 // handlified. | |
| 922 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCells( | |
| 923 MacroAssembler* masm, | |
| 924 JSObject* object, | |
| 925 JSObject* holder, | |
| 926 String* name, | |
| 927 Register scratch, | |
| 928 Label* miss) { | |
| 929 JSObject* current = object; | |
| 930 while (current != holder) { | |
| 931 if (current->IsGlobalObject()) { | |
| 932 // Returns a cell or a failure. | |
| 933 MaybeObject* result = TryGenerateCheckPropertyCell( | |
| 934 masm, | |
| 935 GlobalObject::cast(current), | |
| 936 name, | |
| 937 scratch, | |
| 938 miss); | |
| 939 if (result->IsFailure()) return result; | |
| 940 } | |
| 941 ASSERT(current->IsJSObject()); | |
| 942 current = JSObject::cast(current->GetPrototype()); | |
| 943 } | |
| 944 return NULL; | |
| 945 } | |
| 946 | |
| 947 | |
| 831 #undef __ | 948 #undef __ |
| 832 #define __ ACCESS_MASM((masm())) | 949 #define __ ACCESS_MASM((masm())) |
| 833 | 950 |
| 834 | 951 |
| 952 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | |
| 953 Register object_reg, | |
| 954 Handle<JSObject> holder, | |
| 955 Register holder_reg, | |
| 956 Register scratch1, | |
| 957 Register scratch2, | |
| 958 Handle<String> name, | |
| 959 int save_at_depth, | |
| 960 Label* miss) { | |
| 961 // Make sure there's no overlap between holder and object registers. | |
| 962 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | |
| 963 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | |
| 964 && !scratch2.is(scratch1)); | |
| 965 | |
| 966 // Keep track of the current object in register reg. On the first | |
| 967 // iteration, reg is an alias for object_reg, on later iterations, | |
| 968 // it is an alias for holder_reg. | |
| 969 Register reg = object_reg; | |
| 970 int depth = 0; | |
| 971 | |
| 972 if (save_at_depth == depth) { | |
| 973 __ movq(Operand(rsp, kPointerSize), object_reg); | |
| 974 } | |
| 975 | |
| 976 // Check the maps in the prototype chain. | |
| 977 // Traverse the prototype chain from the object and do map checks. | |
| 978 Handle<JSObject> current = object; | |
| 979 while (!current.is_identical_to(holder)) { | |
| 980 ++depth; | |
| 981 | |
| 982 // Only global objects and objects that do not require access | |
| 983 // checks are allowed in stubs. | |
| 984 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | |
| 985 | |
| 986 Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); | |
| 987 if (!current->HasFastProperties() && | |
| 988 !current->IsJSGlobalObject() && | |
| 989 !current->IsJSGlobalProxy()) { | |
| 990 if (!name->IsSymbol()) { | |
| 991 name = factory()->LookupSymbol(name); | |
| 992 } | |
| 993 ASSERT(current->property_dictionary()->FindEntry(*name) == | |
| 994 StringDictionary::kNotFound); | |
| 995 | |
| 996 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, | |
| 997 scratch1, scratch2); | |
| 998 | |
| 999 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | |
| 1000 reg = holder_reg; // From now on the object will be in holder_reg. | |
| 1001 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | |
| 1002 } else { | |
| 1003 bool in_new_space = heap()->InNewSpace(*prototype); | |
| 1004 Handle<Map> current_map(current->map()); | |
| 1005 if (in_new_space) { | |
| 1006 // Save the map in scratch1 for later. | |
| 1007 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | |
| 1008 __ Cmp(scratch1, current_map); | |
| 1009 } else { | |
| 1010 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), current_map); | |
| 1011 } | |
| 1012 // Branch on the result of the map check. | |
| 1013 __ j(not_equal, miss); | |
| 1014 // Check access rights to the global object. This has to happen after | |
| 1015 // the map check so that we know that the object is actually a global | |
| 1016 // object. | |
| 1017 if (current->IsJSGlobalProxy()) { | |
| 1018 __ CheckAccessGlobalProxy(reg, scratch2, miss); | |
| 1019 } | |
| 1020 reg = holder_reg; // From now on the object will be in holder_reg. | |
| 1021 | |
| 1022 if (in_new_space) { | |
| 1023 // The prototype is in new space; we cannot store a reference to it | |
| 1024 // in the code. Load it from the map. | |
| 1025 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | |
| 1026 } else { | |
| 1027 // The prototype is in old space; load it directly. | |
| 1028 __ Move(reg, prototype); | |
| 1029 } | |
| 1030 } | |
| 1031 | |
| 1032 if (save_at_depth == depth) { | |
| 1033 __ movq(Operand(rsp, kPointerSize), reg); | |
| 1034 } | |
| 1035 | |
| 1036 // Go to the next object in the prototype chain. | |
| 1037 current = prototype; | |
| 1038 } | |
| 1039 ASSERT(current.is_identical_to(holder)); | |
| 1040 | |
| 1041 // Log the check depth. | |
| 1042 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | |
| 1043 | |
| 1044 // Check the holder map. | |
| 1045 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), Handle<Map>(holder->map())); | |
| 1046 __ j(not_equal, miss); | |
| 1047 | |
| 1048 // Perform security check for access to the global object. | |
| 1049 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | |
| 1050 if (current->IsJSGlobalProxy()) { | |
| 1051 __ CheckAccessGlobalProxy(reg, scratch1, miss); | |
| 1052 } | |
| 1053 | |
| 1054 // If we've skipped any global objects, it's not enough to verify that | |
| 1055 // their maps haven't changed. We also need to check that the property | |
| 1056 // cell for the property is still empty. | |
| 1057 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | |
| 1058 | |
| 1059 // Return the register containing the holder. | |
| 1060 return reg; | |
| 1061 } | |
| 1062 | |
| 1063 | |
| 835 Register StubCompiler::CheckPrototypes(JSObject* object, | 1064 Register StubCompiler::CheckPrototypes(JSObject* object, |
| 836 Register object_reg, | 1065 Register object_reg, |
| 837 JSObject* holder, | 1066 JSObject* holder, |
| 838 Register holder_reg, | 1067 Register holder_reg, |
| 839 Register scratch1, | 1068 Register scratch1, |
| 840 Register scratch2, | 1069 Register scratch2, |
| 841 String* name, | 1070 String* name, |
| 842 int save_at_depth, | 1071 int save_at_depth, |
| 843 Label* miss) { | 1072 Label* miss) { |
| 844 // Make sure there's no overlap between holder and object registers. | 1073 // Make sure there's no overlap between holder and object registers. |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 875 if (lookup_result->IsFailure()) { | 1104 if (lookup_result->IsFailure()) { |
| 876 set_failure(Failure::cast(lookup_result)); | 1105 set_failure(Failure::cast(lookup_result)); |
| 877 return reg; | 1106 return reg; |
| 878 } else { | 1107 } else { |
| 879 name = String::cast(lookup_result->ToObjectUnchecked()); | 1108 name = String::cast(lookup_result->ToObjectUnchecked()); |
| 880 } | 1109 } |
| 881 } | 1110 } |
| 882 ASSERT(current->property_dictionary()->FindEntry(name) == | 1111 ASSERT(current->property_dictionary()->FindEntry(name) == |
| 883 StringDictionary::kNotFound); | 1112 StringDictionary::kNotFound); |
| 884 | 1113 |
| 885 MaybeObject* negative_lookup = GenerateDictionaryNegativeLookup(masm(), | 1114 MaybeObject* negative_lookup = |
| 886 miss, | 1115 TryGenerateDictionaryNegativeLookup(masm(), |
| 887 reg, | 1116 miss, |
| 888 name, | 1117 reg, |
| 889 scratch1, | 1118 name, |
| 890 scratch2); | 1119 scratch1, |
| 1120 scratch2); | |
| 891 if (negative_lookup->IsFailure()) { | 1121 if (negative_lookup->IsFailure()) { |
| 892 set_failure(Failure::cast(negative_lookup)); | 1122 set_failure(Failure::cast(negative_lookup)); |
| 893 return reg; | 1123 return reg; |
| 894 } | 1124 } |
| 895 | 1125 |
| 896 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 1126 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 897 reg = holder_reg; // from now the object is in holder_reg | 1127 reg = holder_reg; // from now the object is in holder_reg |
| 898 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1128 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 899 } else if (heap()->InNewSpace(prototype)) { | 1129 } else if (heap()->InNewSpace(prototype)) { |
| 900 // Get the map of the current object. | 1130 // Get the map of the current object. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 953 // the holder register. | 1183 // the holder register. |
| 954 ASSERT(current == holder); | 1184 ASSERT(current == holder); |
| 955 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 1185 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); |
| 956 if (current->IsJSGlobalProxy()) { | 1186 if (current->IsJSGlobalProxy()) { |
| 957 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1187 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 958 } | 1188 } |
| 959 | 1189 |
| 960 // If we've skipped any global objects, it's not enough to verify | 1190 // 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 | 1191 // that their maps haven't changed. We also need to check that the |
| 962 // property cell for the property is still empty. | 1192 // property cell for the property is still empty. |
| 963 current = object; | 1193 MaybeObject* result = TryGenerateCheckPropertyCells(masm(), |
| 964 while (current != holder) { | 1194 object, |
| 965 if (current->IsGlobalObject()) { | 1195 holder, |
| 966 MaybeObject* cell = GenerateCheckPropertyCell(masm(), | 1196 name, |
| 967 GlobalObject::cast(current), | 1197 scratch1, |
| 968 name, | 1198 miss); |
| 969 scratch1, | 1199 if (result->IsFailure()) set_failure(Failure::cast(result)); |
|
ulan
2011/10/24 16:28:25
The result can be NULL. It works but looks suspici
| |
| 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 | 1200 |
| 979 // Return the register containing the holder. | 1201 // Return the register containing the holder. |
| 980 return reg; | 1202 return reg; |
| 981 } | 1203 } |
| 982 | 1204 |
| 983 | 1205 |
| 984 void StubCompiler::GenerateLoadField(JSObject* object, | 1206 void StubCompiler::GenerateLoadField(JSObject* object, |
| 985 JSObject* holder, | 1207 JSObject* holder, |
| 986 Register receiver, | 1208 Register receiver, |
| 987 Register scratch1, | 1209 Register scratch1, |
| 988 Register scratch2, | 1210 Register scratch2, |
| 989 Register scratch3, | 1211 Register scratch3, |
| 990 int index, | 1212 int index, |
| 991 String* name, | 1213 String* name, |
| 992 Label* miss) { | 1214 Label* miss) { |
| 993 // Check that the receiver isn't a smi. | 1215 // Check that the receiver isn't a smi. |
| 994 __ JumpIfSmi(receiver, miss); | 1216 __ JumpIfSmi(receiver, miss); |
| 995 | 1217 |
| 996 // Check the prototype chain. | 1218 // Check the prototype chain. |
| 997 Register reg = | 1219 Register reg = |
| 998 CheckPrototypes(object, receiver, holder, | 1220 CheckPrototypes(object, receiver, holder, |
| 999 scratch1, scratch2, scratch3, name, miss); | 1221 scratch1, scratch2, scratch3, name, miss); |
| 1000 | 1222 |
| 1001 // Get the value from the properties. | 1223 // Get the value from the properties. |
| 1002 GenerateFastPropertyLoad(masm(), rax, reg, holder, index); | 1224 GenerateFastPropertyLoad(masm(), rax, reg, Handle<JSObject>(holder), index); |
| 1003 __ ret(0); | 1225 __ ret(0); |
| 1004 } | 1226 } |
| 1005 | 1227 |
| 1006 | 1228 |
| 1007 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, | 1229 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, |
| 1008 JSObject* holder, | 1230 JSObject* holder, |
| 1009 Register receiver, | 1231 Register receiver, |
| 1010 Register name_reg, | 1232 Register name_reg, |
| 1011 Register scratch1, | 1233 Register scratch1, |
| 1012 Register scratch2, | 1234 Register scratch2, |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1191 scratch2, | 1413 scratch2, |
| 1192 scratch3, | 1414 scratch3, |
| 1193 name, | 1415 name, |
| 1194 miss); | 1416 miss); |
| 1195 } | 1417 } |
| 1196 | 1418 |
| 1197 if (lookup->type() == FIELD) { | 1419 if (lookup->type() == FIELD) { |
| 1198 // We found FIELD property in prototype chain of interceptor's holder. | 1420 // We found FIELD property in prototype chain of interceptor's holder. |
| 1199 // Retrieve a field from field's holder. | 1421 // Retrieve a field from field's holder. |
| 1200 GenerateFastPropertyLoad(masm(), rax, holder_reg, | 1422 GenerateFastPropertyLoad(masm(), rax, holder_reg, |
| 1201 lookup->holder(), lookup->GetFieldIndex()); | 1423 Handle<JSObject>(lookup->holder()), |
| 1424 lookup->GetFieldIndex()); | |
| 1202 __ ret(0); | 1425 __ ret(0); |
| 1203 } else { | 1426 } else { |
| 1204 // We found CALLBACKS property in prototype chain of interceptor's | 1427 // We found CALLBACKS property in prototype chain of interceptor's |
| 1205 // holder. | 1428 // holder. |
| 1206 ASSERT(lookup->type() == CALLBACKS); | 1429 ASSERT(lookup->type() == CALLBACKS); |
| 1207 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); | 1430 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); |
| 1208 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 1431 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); |
| 1209 ASSERT(callback != NULL); | 1432 ASSERT(callback != NULL); |
| 1210 ASSERT(callback->getter() != NULL); | 1433 ASSERT(callback->getter() != NULL); |
| 1211 | 1434 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 1237 name_reg, interceptor_holder); | 1460 name_reg, interceptor_holder); |
| 1238 __ push(scratch2); // restore old return address | 1461 __ push(scratch2); // restore old return address |
| 1239 | 1462 |
| 1240 ExternalReference ref = ExternalReference( | 1463 ExternalReference ref = ExternalReference( |
| 1241 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate()); | 1464 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate()); |
| 1242 __ TailCallExternalReference(ref, 5, 1); | 1465 __ TailCallExternalReference(ref, 5, 1); |
| 1243 } | 1466 } |
| 1244 } | 1467 } |
| 1245 | 1468 |
| 1246 | 1469 |
| 1247 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { | 1470 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { |
| 1248 if (kind_ == Code::KEYED_CALL_IC) { | 1471 if (kind_ == Code::KEYED_CALL_IC) { |
| 1249 __ Cmp(rcx, Handle<String>(name)); | 1472 __ Cmp(rcx, name); |
| 1250 __ j(not_equal, miss); | 1473 __ j(not_equal, miss); |
| 1251 } | 1474 } |
| 1252 } | 1475 } |
| 1253 | 1476 |
| 1254 | 1477 |
| 1255 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, | 1478 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, |
| 1256 JSObject* holder, | 1479 JSObject* holder, |
| 1257 String* name, | 1480 String* name, |
| 1258 Label* miss) { | 1481 Label* miss) { |
| 1259 ASSERT(holder->IsGlobalObject()); | 1482 ASSERT(holder->IsGlobalObject()); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1298 __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); | 1521 __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); |
| 1299 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); | 1522 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); |
| 1300 __ j(not_equal, miss); | 1523 __ j(not_equal, miss); |
| 1301 } else { | 1524 } else { |
| 1302 __ Cmp(rdi, Handle<JSFunction>(function)); | 1525 __ Cmp(rdi, Handle<JSFunction>(function)); |
| 1303 __ j(not_equal, miss); | 1526 __ j(not_equal, miss); |
| 1304 } | 1527 } |
| 1305 } | 1528 } |
| 1306 | 1529 |
| 1307 | 1530 |
| 1308 MaybeObject* CallStubCompiler::GenerateMissBranch() { | 1531 void CallStubCompiler::GenerateMissBranch() { |
| 1532 Handle<Code> code = | |
| 1533 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | |
| 1534 kind_, | |
| 1535 extra_state_); | |
| 1536 __ Jump(code, RelocInfo::CODE_TARGET); | |
| 1537 } | |
| 1538 | |
| 1539 | |
| 1540 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
| 1541 // handlified. | |
| 1542 MaybeObject* CallStubCompiler::TryGenerateMissBranch() { | |
| 1309 MaybeObject* maybe_obj = | 1543 MaybeObject* maybe_obj = |
| 1310 isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(), | 1544 isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(), |
| 1311 kind_, | 1545 kind_, |
| 1312 extra_state_); | 1546 extra_state_); |
| 1313 Object* obj; | 1547 Object* obj; |
| 1314 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1548 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 1315 __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | 1549 __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); |
| 1316 return obj; | 1550 return obj; |
| 1317 } | 1551 } |
| 1318 | 1552 |
| 1319 | 1553 |
| 1320 MaybeObject* CallStubCompiler::CompileCallField(JSObject* object, | 1554 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| 1321 JSObject* holder, | 1555 Handle<JSObject> holder, |
| 1322 int index, | 1556 int index, |
| 1323 String* name) { | 1557 Handle<String> name) { |
| 1324 // ----------- S t a t e ------------- | 1558 // ----------- S t a t e ------------- |
| 1325 // rcx : function name | 1559 // rcx : function name |
| 1326 // rsp[0] : return address | 1560 // rsp[0] : return address |
| 1327 // rsp[8] : argument argc | 1561 // rsp[8] : argument argc |
| 1328 // rsp[16] : argument argc - 1 | 1562 // rsp[16] : argument argc - 1 |
| 1329 // ... | 1563 // ... |
| 1330 // rsp[argc * 8] : argument 1 | 1564 // rsp[argc * 8] : argument 1 |
| 1331 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1565 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1332 // ----------------------------------- | 1566 // ----------------------------------- |
| 1333 Label miss; | 1567 Label miss; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1360 } | 1594 } |
| 1361 | 1595 |
| 1362 // Invoke the function. | 1596 // Invoke the function. |
| 1363 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 1597 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 1364 ? CALL_AS_FUNCTION | 1598 ? CALL_AS_FUNCTION |
| 1365 : CALL_AS_METHOD; | 1599 : CALL_AS_METHOD; |
| 1366 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, | 1600 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, |
| 1367 NullCallWrapper(), call_kind); | 1601 NullCallWrapper(), call_kind); |
| 1368 | 1602 |
| 1369 // Handle call cache miss. | 1603 // Handle call cache miss. |
| 1370 __ bind(&miss); | 1604 __ bind(&miss);GenerateMissBranch(); |
|
ulan
2011/10/24 16:28:25
New line between statements.
| |
| 1371 MaybeObject* maybe_result = GenerateMissBranch(); | |
| 1372 if (maybe_result->IsFailure()) return maybe_result; | |
| 1373 | 1605 |
| 1374 // Return the generated code. | 1606 // Return the generated code. |
| 1375 return GetCode(FIELD, name); | 1607 return GetCode(FIELD, name); |
| 1376 } | 1608 } |
| 1377 | 1609 |
| 1378 | 1610 |
| 1379 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, | 1611 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, |
| 1380 JSObject* holder, | 1612 JSObject* holder, |
| 1381 JSGlobalPropertyCell* cell, | 1613 JSGlobalPropertyCell* cell, |
| 1382 JSFunction* function, | 1614 JSFunction* function, |
| 1383 String* name) { | 1615 String* name) { |
| 1384 // ----------- S t a t e ------------- | 1616 // ----------- S t a t e ------------- |
| 1385 // -- rcx : name | 1617 // -- rcx : name |
| 1386 // -- rsp[0] : return address | 1618 // -- rsp[0] : return address |
| 1387 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1619 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1388 // -- ... | 1620 // -- ... |
| 1389 // -- rsp[(argc + 1) * 8] : receiver | 1621 // -- rsp[(argc + 1) * 8] : receiver |
| 1390 // ----------------------------------- | 1622 // ----------------------------------- |
| 1391 | 1623 |
| 1392 // If object is not an array, bail out to regular call. | 1624 // If object is not an array, bail out to regular call. |
| 1393 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); | 1625 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); |
| 1394 | 1626 |
| 1395 Label miss; | 1627 Label miss; |
| 1396 | 1628 |
| 1397 GenerateNameCheck(name, &miss); | 1629 GenerateNameCheck(Handle<String>(name), &miss); |
| 1398 | 1630 |
| 1399 // Get the receiver from the stack. | 1631 // Get the receiver from the stack. |
| 1400 const int argc = arguments().immediate(); | 1632 const int argc = arguments().immediate(); |
| 1401 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1633 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1402 | 1634 |
| 1403 // Check that the receiver isn't a smi. | 1635 // Check that the receiver isn't a smi. |
| 1404 __ JumpIfSmi(rdx, &miss); | 1636 __ JumpIfSmi(rdx, &miss); |
| 1405 | 1637 |
| 1406 CheckPrototypes(JSObject::cast(object), | 1638 CheckPrototypes(JSObject::cast(object), |
| 1407 rdx, | 1639 rdx, |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1546 } | 1778 } |
| 1547 | 1779 |
| 1548 __ bind(&call_builtin); | 1780 __ bind(&call_builtin); |
| 1549 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, | 1781 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, |
| 1550 isolate()), | 1782 isolate()), |
| 1551 argc + 1, | 1783 argc + 1, |
| 1552 1); | 1784 1); |
| 1553 } | 1785 } |
| 1554 | 1786 |
| 1555 __ bind(&miss); | 1787 __ bind(&miss); |
| 1556 MaybeObject* maybe_result = GenerateMissBranch(); | 1788 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1557 if (maybe_result->IsFailure()) return maybe_result; | 1789 if (maybe_result->IsFailure()) return maybe_result; |
| 1558 | 1790 |
| 1559 // Return the generated code. | 1791 // Return the generated code. |
| 1560 return GetCode(function); | 1792 return TryGetCode(function); |
| 1561 } | 1793 } |
| 1562 | 1794 |
| 1563 | 1795 |
| 1564 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, | 1796 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, |
| 1565 JSObject* holder, | 1797 JSObject* holder, |
| 1566 JSGlobalPropertyCell* cell, | 1798 JSGlobalPropertyCell* cell, |
| 1567 JSFunction* function, | 1799 JSFunction* function, |
| 1568 String* name) { | 1800 String* name) { |
| 1569 // ----------- S t a t e ------------- | 1801 // ----------- S t a t e ------------- |
| 1570 // -- rcx : name | 1802 // -- rcx : name |
| 1571 // -- rsp[0] : return address | 1803 // -- rsp[0] : return address |
| 1572 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1804 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1573 // -- ... | 1805 // -- ... |
| 1574 // -- rsp[(argc + 1) * 8] : receiver | 1806 // -- rsp[(argc + 1) * 8] : receiver |
| 1575 // ----------------------------------- | 1807 // ----------------------------------- |
| 1576 | 1808 |
| 1577 // If object is not an array, bail out to regular call. | 1809 // If object is not an array, bail out to regular call. |
| 1578 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); | 1810 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); |
| 1579 | 1811 |
| 1580 Label miss, return_undefined, call_builtin; | 1812 Label miss, return_undefined, call_builtin; |
| 1581 | 1813 |
| 1582 GenerateNameCheck(name, &miss); | 1814 GenerateNameCheck(Handle<String>(name), &miss); |
| 1583 | 1815 |
| 1584 // Get the receiver from the stack. | 1816 // Get the receiver from the stack. |
| 1585 const int argc = arguments().immediate(); | 1817 const int argc = arguments().immediate(); |
| 1586 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1818 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1587 | 1819 |
| 1588 // Check that the receiver isn't a smi. | 1820 // Check that the receiver isn't a smi. |
| 1589 __ JumpIfSmi(rdx, &miss); | 1821 __ JumpIfSmi(rdx, &miss); |
| 1590 | 1822 |
| 1591 CheckPrototypes(JSObject::cast(object), rdx, | 1823 CheckPrototypes(JSObject::cast(object), rdx, |
| 1592 holder, rbx, | 1824 holder, rbx, |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1629 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 1861 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 1630 __ ret((argc + 1) * kPointerSize); | 1862 __ ret((argc + 1) * kPointerSize); |
| 1631 | 1863 |
| 1632 __ bind(&call_builtin); | 1864 __ bind(&call_builtin); |
| 1633 __ TailCallExternalReference( | 1865 __ TailCallExternalReference( |
| 1634 ExternalReference(Builtins::c_ArrayPop, isolate()), | 1866 ExternalReference(Builtins::c_ArrayPop, isolate()), |
| 1635 argc + 1, | 1867 argc + 1, |
| 1636 1); | 1868 1); |
| 1637 | 1869 |
| 1638 __ bind(&miss); | 1870 __ bind(&miss); |
| 1639 MaybeObject* maybe_result = GenerateMissBranch(); | 1871 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1640 if (maybe_result->IsFailure()) return maybe_result; | 1872 if (maybe_result->IsFailure()) return maybe_result; |
| 1641 | 1873 |
| 1642 // Return the generated code. | 1874 // Return the generated code. |
| 1643 return GetCode(function); | 1875 return TryGetCode(function); |
| 1644 } | 1876 } |
| 1645 | 1877 |
| 1646 | 1878 |
| 1647 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( | 1879 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( |
| 1648 Object* object, | 1880 Object* object, |
| 1649 JSObject* holder, | 1881 JSObject* holder, |
| 1650 JSGlobalPropertyCell* cell, | 1882 JSGlobalPropertyCell* cell, |
| 1651 JSFunction* function, | 1883 JSFunction* function, |
| 1652 String* name) { | 1884 String* name) { |
| 1653 // ----------- S t a t e ------------- | 1885 // ----------- S t a t e ------------- |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1667 Label name_miss; | 1899 Label name_miss; |
| 1668 Label index_out_of_range; | 1900 Label index_out_of_range; |
| 1669 Label* index_out_of_range_label = &index_out_of_range; | 1901 Label* index_out_of_range_label = &index_out_of_range; |
| 1670 | 1902 |
| 1671 if (kind_ == Code::CALL_IC && | 1903 if (kind_ == Code::CALL_IC && |
| 1672 (CallICBase::StringStubState::decode(extra_state_) == | 1904 (CallICBase::StringStubState::decode(extra_state_) == |
| 1673 DEFAULT_STRING_STUB)) { | 1905 DEFAULT_STRING_STUB)) { |
| 1674 index_out_of_range_label = &miss; | 1906 index_out_of_range_label = &miss; |
| 1675 } | 1907 } |
| 1676 | 1908 |
| 1677 GenerateNameCheck(name, &name_miss); | 1909 GenerateNameCheck(Handle<String>(name), &name_miss); |
| 1678 | 1910 |
| 1679 // Check that the maps starting from the prototype haven't changed. | 1911 // Check that the maps starting from the prototype haven't changed. |
| 1680 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1912 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 1681 Context::STRING_FUNCTION_INDEX, | 1913 Context::STRING_FUNCTION_INDEX, |
| 1682 rax, | 1914 rax, |
| 1683 &miss); | 1915 &miss); |
| 1684 ASSERT(object != holder); | 1916 ASSERT(object != holder); |
| 1685 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, | 1917 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
| 1686 rbx, rdx, rdi, name, &miss); | 1918 rbx, rdx, rdi, name, &miss); |
| 1687 | 1919 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 1713 if (index_out_of_range.is_linked()) { | 1945 if (index_out_of_range.is_linked()) { |
| 1714 __ bind(&index_out_of_range); | 1946 __ bind(&index_out_of_range); |
| 1715 __ LoadRoot(rax, Heap::kNanValueRootIndex); | 1947 __ LoadRoot(rax, Heap::kNanValueRootIndex); |
| 1716 __ ret((argc + 1) * kPointerSize); | 1948 __ ret((argc + 1) * kPointerSize); |
| 1717 } | 1949 } |
| 1718 | 1950 |
| 1719 __ bind(&miss); | 1951 __ bind(&miss); |
| 1720 // Restore function name in rcx. | 1952 // Restore function name in rcx. |
| 1721 __ Move(rcx, Handle<String>(name)); | 1953 __ Move(rcx, Handle<String>(name)); |
| 1722 __ bind(&name_miss); | 1954 __ bind(&name_miss); |
| 1723 MaybeObject* maybe_result = GenerateMissBranch(); | 1955 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1724 if (maybe_result->IsFailure()) return maybe_result; | 1956 if (maybe_result->IsFailure()) return maybe_result; |
| 1725 | 1957 |
| 1726 // Return the generated code. | 1958 // Return the generated code. |
| 1727 return GetCode(function); | 1959 return TryGetCode(function); |
| 1728 } | 1960 } |
| 1729 | 1961 |
| 1730 | 1962 |
| 1731 MaybeObject* CallStubCompiler::CompileStringCharAtCall( | 1963 MaybeObject* CallStubCompiler::CompileStringCharAtCall( |
| 1732 Object* object, | 1964 Object* object, |
| 1733 JSObject* holder, | 1965 JSObject* holder, |
| 1734 JSGlobalPropertyCell* cell, | 1966 JSGlobalPropertyCell* cell, |
| 1735 JSFunction* function, | 1967 JSFunction* function, |
| 1736 String* name) { | 1968 String* name) { |
| 1737 // ----------- S t a t e ------------- | 1969 // ----------- S t a t e ------------- |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1751 Label name_miss; | 1983 Label name_miss; |
| 1752 Label index_out_of_range; | 1984 Label index_out_of_range; |
| 1753 Label* index_out_of_range_label = &index_out_of_range; | 1985 Label* index_out_of_range_label = &index_out_of_range; |
| 1754 | 1986 |
| 1755 if (kind_ == Code::CALL_IC && | 1987 if (kind_ == Code::CALL_IC && |
| 1756 (CallICBase::StringStubState::decode(extra_state_) == | 1988 (CallICBase::StringStubState::decode(extra_state_) == |
| 1757 DEFAULT_STRING_STUB)) { | 1989 DEFAULT_STRING_STUB)) { |
| 1758 index_out_of_range_label = &miss; | 1990 index_out_of_range_label = &miss; |
| 1759 } | 1991 } |
| 1760 | 1992 |
| 1761 GenerateNameCheck(name, &name_miss); | 1993 GenerateNameCheck(Handle<String>(name), &name_miss); |
| 1762 | 1994 |
| 1763 // Check that the maps starting from the prototype haven't changed. | 1995 // Check that the maps starting from the prototype haven't changed. |
| 1764 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1996 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 1765 Context::STRING_FUNCTION_INDEX, | 1997 Context::STRING_FUNCTION_INDEX, |
| 1766 rax, | 1998 rax, |
| 1767 &miss); | 1999 &miss); |
| 1768 ASSERT(object != holder); | 2000 ASSERT(object != holder); |
| 1769 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, | 2001 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
| 1770 rbx, rdx, rdi, name, &miss); | 2002 rbx, rdx, rdi, name, &miss); |
| 1771 | 2003 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 1799 if (index_out_of_range.is_linked()) { | 2031 if (index_out_of_range.is_linked()) { |
| 1800 __ bind(&index_out_of_range); | 2032 __ bind(&index_out_of_range); |
| 1801 __ LoadRoot(rax, Heap::kEmptyStringRootIndex); | 2033 __ LoadRoot(rax, Heap::kEmptyStringRootIndex); |
| 1802 __ ret((argc + 1) * kPointerSize); | 2034 __ ret((argc + 1) * kPointerSize); |
| 1803 } | 2035 } |
| 1804 | 2036 |
| 1805 __ bind(&miss); | 2037 __ bind(&miss); |
| 1806 // Restore function name in rcx. | 2038 // Restore function name in rcx. |
| 1807 __ Move(rcx, Handle<String>(name)); | 2039 __ Move(rcx, Handle<String>(name)); |
| 1808 __ bind(&name_miss); | 2040 __ bind(&name_miss); |
| 1809 MaybeObject* maybe_result = GenerateMissBranch(); | 2041 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1810 if (maybe_result->IsFailure()) return maybe_result; | 2042 if (maybe_result->IsFailure()) return maybe_result; |
| 1811 | 2043 |
| 1812 // Return the generated code. | 2044 // Return the generated code. |
| 1813 return GetCode(function); | 2045 return TryGetCode(function); |
| 1814 } | 2046 } |
| 1815 | 2047 |
| 1816 | 2048 |
| 1817 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( | 2049 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( |
| 1818 Object* object, | 2050 Object* object, |
| 1819 JSObject* holder, | 2051 JSObject* holder, |
| 1820 JSGlobalPropertyCell* cell, | 2052 JSGlobalPropertyCell* cell, |
| 1821 JSFunction* function, | 2053 JSFunction* function, |
| 1822 String* name) { | 2054 String* name) { |
| 1823 // ----------- S t a t e ------------- | 2055 // ----------- S t a t e ------------- |
| 1824 // -- rcx : function name | 2056 // -- rcx : function name |
| 1825 // -- rsp[0] : return address | 2057 // -- rsp[0] : return address |
| 1826 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 2058 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1827 // -- ... | 2059 // -- ... |
| 1828 // -- rsp[(argc + 1) * 8] : receiver | 2060 // -- rsp[(argc + 1) * 8] : receiver |
| 1829 // ----------------------------------- | 2061 // ----------------------------------- |
| 1830 | 2062 |
| 1831 const int argc = arguments().immediate(); | 2063 const int argc = arguments().immediate(); |
| 1832 | 2064 |
| 1833 // If the object is not a JSObject or we got an unexpected number of | 2065 // If the object is not a JSObject or we got an unexpected number of |
| 1834 // arguments, bail out to the regular call. | 2066 // arguments, bail out to the regular call. |
| 1835 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 2067 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); |
| 1836 | 2068 |
| 1837 Label miss; | 2069 Label miss; |
| 1838 GenerateNameCheck(name, &miss); | 2070 GenerateNameCheck(Handle<String>(name), &miss); |
| 1839 | 2071 |
| 1840 if (cell == NULL) { | 2072 if (cell == NULL) { |
| 1841 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); | 2073 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); |
| 1842 | 2074 |
| 1843 __ JumpIfSmi(rdx, &miss); | 2075 __ JumpIfSmi(rdx, &miss); |
| 1844 | 2076 |
| 1845 CheckPrototypes(JSObject::cast(object), rdx, holder, rbx, rax, rdi, name, | 2077 CheckPrototypes(JSObject::cast(object), rdx, holder, rbx, rax, rdi, name, |
| 1846 &miss); | 2078 &miss); |
| 1847 } else { | 2079 } else { |
| 1848 ASSERT(cell->value() == function); | 2080 ASSERT(cell->value() == function); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1872 // because the function makes no use of it. | 2104 // because the function makes no use of it. |
| 1873 __ bind(&slow); | 2105 __ bind(&slow); |
| 1874 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2106 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 1875 ? CALL_AS_FUNCTION | 2107 ? CALL_AS_FUNCTION |
| 1876 : CALL_AS_METHOD; | 2108 : CALL_AS_METHOD; |
| 1877 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2109 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 1878 NullCallWrapper(), call_kind); | 2110 NullCallWrapper(), call_kind); |
| 1879 | 2111 |
| 1880 __ bind(&miss); | 2112 __ bind(&miss); |
| 1881 // rcx: function name. | 2113 // rcx: function name. |
| 1882 MaybeObject* maybe_result = GenerateMissBranch(); | 2114 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1883 if (maybe_result->IsFailure()) return maybe_result; | 2115 if (maybe_result->IsFailure()) return maybe_result; |
| 1884 | 2116 |
| 1885 // Return the generated code. | 2117 // Return the generated code. |
| 1886 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2118 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
| 1887 } | 2119 } |
| 1888 | 2120 |
| 1889 | 2121 |
| 1890 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, | 2122 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, |
| 1891 JSObject* holder, | 2123 JSObject* holder, |
| 1892 JSGlobalPropertyCell* cell, | 2124 JSGlobalPropertyCell* cell, |
| 1893 JSFunction* function, | 2125 JSFunction* function, |
| 1894 String* name) { | 2126 String* name) { |
| 1895 // TODO(872): implement this. | 2127 // TODO(872): implement this. |
| 1896 return heap()->undefined_value(); | 2128 return heap()->undefined_value(); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1910 // -- rsp[(argc + 1) * 8] : receiver | 2142 // -- rsp[(argc + 1) * 8] : receiver |
| 1911 // ----------------------------------- | 2143 // ----------------------------------- |
| 1912 | 2144 |
| 1913 const int argc = arguments().immediate(); | 2145 const int argc = arguments().immediate(); |
| 1914 | 2146 |
| 1915 // If the object is not a JSObject or we got an unexpected number of | 2147 // If the object is not a JSObject or we got an unexpected number of |
| 1916 // arguments, bail out to the regular call. | 2148 // arguments, bail out to the regular call. |
| 1917 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 2149 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); |
| 1918 | 2150 |
| 1919 Label miss; | 2151 Label miss; |
| 1920 GenerateNameCheck(name, &miss); | 2152 GenerateNameCheck(Handle<String>(name), &miss); |
| 1921 | 2153 |
| 1922 if (cell == NULL) { | 2154 if (cell == NULL) { |
| 1923 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); | 2155 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); |
| 1924 | 2156 |
| 1925 __ JumpIfSmi(rdx, &miss); | 2157 __ JumpIfSmi(rdx, &miss); |
| 1926 | 2158 |
| 1927 CheckPrototypes(JSObject::cast(object), rdx, holder, rbx, rax, rdi, name, | 2159 CheckPrototypes(JSObject::cast(object), rdx, holder, rbx, rax, rdi, name, |
| 1928 &miss); | 2160 &miss); |
| 1929 } else { | 2161 } else { |
| 1930 ASSERT(cell->value() == function); | 2162 ASSERT(cell->value() == function); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1989 // because the function makes no use of it. | 2221 // because the function makes no use of it. |
| 1990 __ bind(&slow); | 2222 __ bind(&slow); |
| 1991 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2223 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 1992 ? CALL_AS_FUNCTION | 2224 ? CALL_AS_FUNCTION |
| 1993 : CALL_AS_METHOD; | 2225 : CALL_AS_METHOD; |
| 1994 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2226 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 1995 NullCallWrapper(), call_kind); | 2227 NullCallWrapper(), call_kind); |
| 1996 | 2228 |
| 1997 __ bind(&miss); | 2229 __ bind(&miss); |
| 1998 // rcx: function name. | 2230 // rcx: function name. |
| 1999 MaybeObject* maybe_result = GenerateMissBranch(); | 2231 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2000 if (maybe_result->IsFailure()) return maybe_result; | 2232 if (maybe_result->IsFailure()) return maybe_result; |
| 2001 | 2233 |
| 2002 // Return the generated code. | 2234 // Return the generated code. |
| 2003 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2235 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
| 2004 } | 2236 } |
| 2005 | 2237 |
| 2006 | 2238 |
| 2007 MaybeObject* CallStubCompiler::CompileFastApiCall( | 2239 MaybeObject* CallStubCompiler::CompileFastApiCall( |
| 2008 const CallOptimization& optimization, | 2240 const CallOptimization& optimization, |
| 2009 Object* object, | 2241 Object* object, |
| 2010 JSObject* holder, | 2242 JSObject* holder, |
| 2011 JSGlobalPropertyCell* cell, | 2243 JSGlobalPropertyCell* cell, |
| 2012 JSFunction* function, | 2244 JSFunction* function, |
| 2013 String* name) { | 2245 String* name) { |
| 2014 ASSERT(optimization.is_simple_api_call()); | 2246 ASSERT(optimization.is_simple_api_call()); |
| 2015 // Bail out if object is a global object as we don't want to | 2247 // Bail out if object is a global object as we don't want to |
| 2016 // repatch it to global receiver. | 2248 // repatch it to global receiver. |
| 2017 if (object->IsGlobalObject()) return heap()->undefined_value(); | 2249 if (object->IsGlobalObject()) return heap()->undefined_value(); |
| 2018 if (cell != NULL) return heap()->undefined_value(); | 2250 if (cell != NULL) return heap()->undefined_value(); |
| 2019 if (!object->IsJSObject()) return heap()->undefined_value(); | 2251 if (!object->IsJSObject()) return heap()->undefined_value(); |
| 2020 int depth = optimization.GetPrototypeDepthOfExpectedType( | 2252 int depth = optimization.GetPrototypeDepthOfExpectedType( |
| 2021 JSObject::cast(object), holder); | 2253 JSObject::cast(object), holder); |
| 2022 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); | 2254 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); |
| 2023 | 2255 |
| 2024 Label miss, miss_before_stack_reserved; | 2256 Label miss, miss_before_stack_reserved; |
| 2025 | 2257 |
| 2026 GenerateNameCheck(name, &miss_before_stack_reserved); | 2258 GenerateNameCheck(Handle<String>(name), &miss_before_stack_reserved); |
| 2027 | 2259 |
| 2028 // Get the receiver from the stack. | 2260 // Get the receiver from the stack. |
| 2029 const int argc = arguments().immediate(); | 2261 const int argc = arguments().immediate(); |
| 2030 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2262 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2031 | 2263 |
| 2032 // Check that the receiver isn't a smi. | 2264 // Check that the receiver isn't a smi. |
| 2033 __ JumpIfSmi(rdx, &miss_before_stack_reserved); | 2265 __ JumpIfSmi(rdx, &miss_before_stack_reserved); |
| 2034 | 2266 |
| 2035 Counters* counters = isolate()->counters(); | 2267 Counters* counters = isolate()->counters(); |
| 2036 __ IncrementCounter(counters->call_const(), 1); | 2268 __ IncrementCounter(counters->call_const(), 1); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 2048 __ movq(rax, Operand(rsp, 3 * kPointerSize)); | 2280 __ movq(rax, Operand(rsp, 3 * kPointerSize)); |
| 2049 __ movq(Operand(rsp, 0 * kPointerSize), rax); | 2281 __ movq(Operand(rsp, 0 * kPointerSize), rax); |
| 2050 | 2282 |
| 2051 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); | 2283 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); |
| 2052 if (result->IsFailure()) return result; | 2284 if (result->IsFailure()) return result; |
| 2053 | 2285 |
| 2054 __ bind(&miss); | 2286 __ bind(&miss); |
| 2055 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 2287 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2056 | 2288 |
| 2057 __ bind(&miss_before_stack_reserved); | 2289 __ bind(&miss_before_stack_reserved); |
| 2058 MaybeObject* maybe_result = GenerateMissBranch(); | 2290 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2059 if (maybe_result->IsFailure()) return maybe_result; | 2291 if (maybe_result->IsFailure()) return maybe_result; |
| 2060 | 2292 |
| 2061 // Return the generated code. | 2293 // Return the generated code. |
| 2062 return GetCode(function); | 2294 return TryGetCode(function); |
| 2063 } | 2295 } |
| 2064 | 2296 |
| 2065 | 2297 |
| 2066 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, | 2298 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, |
| 2067 JSObject* holder, | 2299 JSObject* holder, |
| 2068 JSFunction* function, | 2300 JSFunction* function, |
| 2069 String* name, | 2301 String* name, |
| 2070 CheckType check) { | 2302 CheckType check) { |
| 2071 // ----------- S t a t e ------------- | 2303 // ----------- S t a t e ------------- |
| 2072 // rcx : function name | 2304 // rcx : function name |
| 2073 // rsp[0] : return address | 2305 // rsp[0] : return address |
| 2074 // rsp[8] : argument argc | 2306 // rsp[8] : argument argc |
| 2075 // rsp[16] : argument argc - 1 | 2307 // rsp[16] : argument argc - 1 |
| 2076 // ... | 2308 // ... |
| 2077 // rsp[argc * 8] : argument 1 | 2309 // rsp[argc * 8] : argument 1 |
| 2078 // rsp[(argc + 1) * 8] : argument 0 = receiver | 2310 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 2079 // ----------------------------------- | 2311 // ----------------------------------- |
| 2080 | 2312 |
| 2081 if (HasCustomCallGenerator(function)) { | 2313 if (HasCustomCallGenerator(function)) { |
| 2082 MaybeObject* maybe_result = CompileCustomCall( | 2314 MaybeObject* maybe_result = CompileCustomCall( |
| 2083 object, holder, NULL, function, name); | 2315 object, holder, NULL, function, name); |
| 2084 Object* result; | 2316 Object* result; |
| 2085 if (!maybe_result->ToObject(&result)) return maybe_result; | 2317 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2086 // undefined means bail out to regular compiler. | 2318 // undefined means bail out to regular compiler. |
| 2087 if (!result->IsUndefined()) return result; | 2319 if (!result->IsUndefined()) return result; |
| 2088 } | 2320 } |
| 2089 | 2321 |
| 2090 Label miss; | 2322 Label miss; |
| 2091 | 2323 |
| 2092 GenerateNameCheck(name, &miss); | 2324 GenerateNameCheck(Handle<String>(name), &miss); |
| 2093 | 2325 |
| 2094 // Get the receiver from the stack. | 2326 // Get the receiver from the stack. |
| 2095 const int argc = arguments().immediate(); | 2327 const int argc = arguments().immediate(); |
| 2096 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2328 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2097 | 2329 |
| 2098 // Check that the receiver isn't a smi. | 2330 // Check that the receiver isn't a smi. |
| 2099 if (check != NUMBER_CHECK) { | 2331 if (check != NUMBER_CHECK) { |
| 2100 __ JumpIfSmi(rdx, &miss); | 2332 __ JumpIfSmi(rdx, &miss); |
| 2101 } | 2333 } |
| 2102 | 2334 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2187 } | 2419 } |
| 2188 | 2420 |
| 2189 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2421 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2190 ? CALL_AS_FUNCTION | 2422 ? CALL_AS_FUNCTION |
| 2191 : CALL_AS_METHOD; | 2423 : CALL_AS_METHOD; |
| 2192 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2424 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 2193 NullCallWrapper(), call_kind); | 2425 NullCallWrapper(), call_kind); |
| 2194 | 2426 |
| 2195 // Handle call cache miss. | 2427 // Handle call cache miss. |
| 2196 __ bind(&miss); | 2428 __ bind(&miss); |
| 2197 MaybeObject* maybe_result = GenerateMissBranch(); | 2429 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2198 if (maybe_result->IsFailure()) return maybe_result; | 2430 if (maybe_result->IsFailure()) return maybe_result; |
| 2199 | 2431 |
| 2200 // Return the generated code. | 2432 // Return the generated code. |
| 2201 return GetCode(function); | 2433 return TryGetCode(function); |
| 2202 } | 2434 } |
| 2203 | 2435 |
| 2204 | 2436 |
| 2205 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, | 2437 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, |
| 2206 JSObject* holder, | 2438 JSObject* holder, |
| 2207 String* name) { | 2439 String* name) { |
| 2208 // ----------- S t a t e ------------- | 2440 // ----------- S t a t e ------------- |
| 2209 // rcx : function name | 2441 // rcx : function name |
| 2210 // rsp[0] : return address | 2442 // rsp[0] : return address |
| 2211 // rsp[8] : argument argc | 2443 // rsp[8] : argument argc |
| 2212 // rsp[16] : argument argc - 1 | 2444 // rsp[16] : argument argc - 1 |
| 2213 // ... | 2445 // ... |
| 2214 // rsp[argc * 8] : argument 1 | 2446 // rsp[argc * 8] : argument 1 |
| 2215 // rsp[(argc + 1) * 8] : argument 0 = receiver | 2447 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 2216 // ----------------------------------- | 2448 // ----------------------------------- |
| 2217 Label miss; | 2449 Label miss; |
| 2218 | 2450 |
| 2219 GenerateNameCheck(name, &miss); | 2451 GenerateNameCheck(Handle<String>(name), &miss); |
| 2220 | 2452 |
| 2221 // Get the number of arguments. | 2453 // Get the number of arguments. |
| 2222 const int argc = arguments().immediate(); | 2454 const int argc = arguments().immediate(); |
| 2223 | 2455 |
| 2224 LookupResult lookup(isolate()); | 2456 LookupResult lookup(isolate()); |
| 2225 LookupPostInterceptor(holder, name, &lookup); | 2457 LookupPostInterceptor(holder, name, &lookup); |
| 2226 | 2458 |
| 2227 // Get the receiver from the stack. | 2459 // Get the receiver from the stack. |
| 2228 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2460 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2229 | 2461 |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 2258 // Invoke the function. | 2490 // Invoke the function. |
| 2259 __ movq(rdi, rax); | 2491 __ movq(rdi, rax); |
| 2260 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2492 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2261 ? CALL_AS_FUNCTION | 2493 ? CALL_AS_FUNCTION |
| 2262 : CALL_AS_METHOD; | 2494 : CALL_AS_METHOD; |
| 2263 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, | 2495 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, |
| 2264 NullCallWrapper(), call_kind); | 2496 NullCallWrapper(), call_kind); |
| 2265 | 2497 |
| 2266 // Handle load cache miss. | 2498 // Handle load cache miss. |
| 2267 __ bind(&miss); | 2499 __ bind(&miss); |
| 2268 MaybeObject* maybe_result = GenerateMissBranch(); | 2500 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2269 if (maybe_result->IsFailure()) return maybe_result; | 2501 if (maybe_result->IsFailure()) return maybe_result; |
| 2270 | 2502 |
| 2271 // Return the generated code. | 2503 // Return the generated code. |
| 2272 return GetCode(INTERCEPTOR, name); | 2504 return TryGetCode(INTERCEPTOR, name); |
| 2273 } | 2505 } |
| 2274 | 2506 |
| 2275 | 2507 |
| 2276 MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, | 2508 MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, |
| 2277 GlobalObject* holder, | 2509 GlobalObject* holder, |
| 2278 JSGlobalPropertyCell* cell, | 2510 JSGlobalPropertyCell* cell, |
| 2279 JSFunction* function, | 2511 JSFunction* function, |
| 2280 String* name) { | 2512 String* name) { |
| 2281 // ----------- S t a t e ------------- | 2513 // ----------- S t a t e ------------- |
| 2282 // rcx : function name | 2514 // rcx : function name |
| 2283 // rsp[0] : return address | 2515 // rsp[0] : return address |
| 2284 // rsp[8] : argument argc | 2516 // rsp[8] : argument argc |
| 2285 // rsp[16] : argument argc - 1 | 2517 // rsp[16] : argument argc - 1 |
| 2286 // ... | 2518 // ... |
| 2287 // rsp[argc * 8] : argument 1 | 2519 // rsp[argc * 8] : argument 1 |
| 2288 // rsp[(argc + 1) * 8] : argument 0 = receiver | 2520 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 2289 // ----------------------------------- | 2521 // ----------------------------------- |
| 2290 | 2522 |
| 2291 if (HasCustomCallGenerator(function)) { | 2523 if (HasCustomCallGenerator(function)) { |
| 2292 MaybeObject* maybe_result = CompileCustomCall( | 2524 MaybeObject* maybe_result = CompileCustomCall( |
| 2293 object, holder, cell, function, name); | 2525 object, holder, cell, function, name); |
| 2294 Object* result; | 2526 Object* result; |
| 2295 if (!maybe_result->ToObject(&result)) return maybe_result; | 2527 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2296 // undefined means bail out to regular compiler. | 2528 // undefined means bail out to regular compiler. |
| 2297 if (!result->IsUndefined()) return result; | 2529 if (!result->IsUndefined()) return result; |
| 2298 } | 2530 } |
| 2299 | 2531 |
| 2300 Label miss; | 2532 Label miss; |
| 2301 | 2533 |
| 2302 GenerateNameCheck(name, &miss); | 2534 GenerateNameCheck(Handle<String>(name), &miss); |
| 2303 | 2535 |
| 2304 // Get the number of arguments. | 2536 // Get the number of arguments. |
| 2305 const int argc = arguments().immediate(); | 2537 const int argc = arguments().immediate(); |
| 2306 | 2538 |
| 2307 GenerateGlobalReceiverCheck(object, holder, name, &miss); | 2539 GenerateGlobalReceiverCheck(object, holder, name, &miss); |
| 2308 | 2540 |
| 2309 GenerateLoadFunctionFromCell(cell, function, &miss); | 2541 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2310 | 2542 |
| 2311 // Patch the receiver on the stack with the global proxy. | 2543 // Patch the receiver on the stack with the global proxy. |
| 2312 if (object->IsGlobalObject()) { | 2544 if (object->IsGlobalObject()) { |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 2327 // We call indirectly through the code field in the function to | 2559 // We call indirectly through the code field in the function to |
| 2328 // allow recompilation to take effect without changing any of the | 2560 // allow recompilation to take effect without changing any of the |
| 2329 // call sites. | 2561 // call sites. |
| 2330 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 2562 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
| 2331 __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION, | 2563 __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION, |
| 2332 NullCallWrapper(), call_kind); | 2564 NullCallWrapper(), call_kind); |
| 2333 | 2565 |
| 2334 // Handle call cache miss. | 2566 // Handle call cache miss. |
| 2335 __ bind(&miss); | 2567 __ bind(&miss); |
| 2336 __ IncrementCounter(counters->call_global_inline_miss(), 1); | 2568 __ IncrementCounter(counters->call_global_inline_miss(), 1); |
| 2337 MaybeObject* maybe_result = GenerateMissBranch(); | 2569 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2338 if (maybe_result->IsFailure()) return maybe_result; | 2570 if (maybe_result->IsFailure()) return maybe_result; |
| 2339 | 2571 |
| 2340 // Return the generated code. | 2572 // Return the generated code. |
| 2341 return GetCode(NORMAL, name); | 2573 return TryGetCode(NORMAL, name); |
| 2342 } | 2574 } |
| 2343 | 2575 |
| 2344 | 2576 |
| 2345 MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, | 2577 MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, |
| 2346 int index, | 2578 int index, |
| 2347 Map* transition, | 2579 Map* transition, |
| 2348 String* name) { | 2580 String* name) { |
| 2349 // ----------- S t a t e ------------- | 2581 // ----------- S t a t e ------------- |
| 2350 // -- rax : value | 2582 // -- rax : value |
| 2351 // -- rcx : name | 2583 // -- rcx : name |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2651 __ JumpIfSmi(rax, &miss); | 2883 __ JumpIfSmi(rax, &miss); |
| 2652 | 2884 |
| 2653 // Check the maps of the full prototype chain. Also check that | 2885 // Check the maps of the full prototype chain. Also check that |
| 2654 // global property cells up to (but not including) the last object | 2886 // global property cells up to (but not including) the last object |
| 2655 // in the prototype chain are empty. | 2887 // in the prototype chain are empty. |
| 2656 CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss); | 2888 CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss); |
| 2657 | 2889 |
| 2658 // If the last object in the prototype chain is a global object, | 2890 // If the last object in the prototype chain is a global object, |
| 2659 // check that the global property cell is empty. | 2891 // check that the global property cell is empty. |
| 2660 if (last->IsGlobalObject()) { | 2892 if (last->IsGlobalObject()) { |
| 2661 MaybeObject* cell = GenerateCheckPropertyCell(masm(), | 2893 MaybeObject* cell = TryGenerateCheckPropertyCell(masm(), |
| 2662 GlobalObject::cast(last), | 2894 GlobalObject::cast(last), |
| 2663 name, | 2895 name, |
| 2664 rdx, | 2896 rdx, |
| 2665 &miss); | 2897 &miss); |
| 2666 if (cell->IsFailure()) { | 2898 if (cell->IsFailure()) { |
| 2667 miss.Unuse(); | 2899 miss.Unuse(); |
| 2668 return cell; | 2900 return cell; |
| 2669 } | 2901 } |
| 2670 } | 2902 } |
| 2671 | 2903 |
| 2672 // Return undefined if maps of the full prototype chain are still the | 2904 // Return undefined if maps of the full prototype chain are still the |
| 2673 // same and no global property with this name contains a value. | 2905 // same and no global property with this name contains a value. |
| 2674 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 2906 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 2675 __ ret(0); | 2907 __ ret(0); |
| (...skipping 1121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3797 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 4029 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3798 __ jmp(ic_miss, RelocInfo::CODE_TARGET); | 4030 __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
| 3799 } | 4031 } |
| 3800 | 4032 |
| 3801 | 4033 |
| 3802 #undef __ | 4034 #undef __ |
| 3803 | 4035 |
| 3804 } } // namespace v8::internal | 4036 } } // namespace v8::internal |
| 3805 | 4037 |
| 3806 #endif // V8_TARGET_ARCH_X64 | 4038 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |