| 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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 __ pop(offset); | 100 __ pop(offset); |
| 101 } | 101 } |
| 102 } | 102 } |
| 103 | 103 |
| 104 | 104 |
| 105 // Helper function used to check that the dictionary doesn't contain | 105 // Helper function used to check that the dictionary doesn't contain |
| 106 // the property. This function may return false negatives, so miss_label | 106 // the property. This function may return false negatives, so miss_label |
| 107 // must always call a backup property check that is complete. | 107 // must always call a backup property check that is complete. |
| 108 // This function is safe to call if the receiver has fast properties. | 108 // This function is safe to call if the receiver has fast properties. |
| 109 // Name must be a symbol and receiver must be a heap object. | 109 // Name must be a symbol and receiver must be a heap object. |
| 110 static MaybeObject* GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 110 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, |
| 111 Label* miss_label, | 111 Label* miss_label, |
| 112 Register receiver, | 112 Register receiver, |
| 113 String* name, | 113 Handle<String> name, |
| 114 Register r0, | 114 Register r0, |
| 115 Register r1) { | 115 Register r1) { |
| 116 ASSERT(name->IsSymbol()); | 116 ASSERT(name->IsSymbol()); |
| 117 Counters* counters = masm->isolate()->counters(); | 117 Counters* counters = masm->isolate()->counters(); |
| 118 __ IncrementCounter(counters->negative_lookups(), 1); | 118 __ IncrementCounter(counters->negative_lookups(), 1); |
| 119 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
| 120 |
| 121 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 122 |
| 123 const int kInterceptorOrAccessCheckNeededMask = |
| 124 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
| 125 |
| 126 // Bail out if the receiver has a named interceptor or requires access checks. |
| 127 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), |
| 128 kInterceptorOrAccessCheckNeededMask); |
| 129 __ j(not_zero, miss_label); |
| 130 |
| 131 // Check that receiver is a JSObject. |
| 132 __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); |
| 133 __ j(below, miss_label); |
| 134 |
| 135 // Load properties array. |
| 136 Register properties = r0; |
| 137 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 138 |
| 139 // Check that the properties array is a dictionary. |
| 140 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), |
| 141 Immediate(masm->isolate()->factory()->hash_table_map())); |
| 142 __ j(not_equal, miss_label); |
| 143 |
| 144 Label done; |
| 145 StringDictionaryLookupStub::GenerateNegativeLookup(masm, |
| 146 miss_label, |
| 147 &done, |
| 148 properties, |
| 149 name, |
| 150 r1); |
| 151 __ bind(&done); |
| 152 __ DecrementCounter(counters->negative_lookups_miss(), 1); |
| 153 } |
| 154 |
| 155 |
| 156 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 157 // handlified. |
| 158 static MaybeObject* TryGenerateDictionaryNegativeLookup(MacroAssembler* masm, |
| 159 Label* miss_label, |
| 160 Register receiver, |
| 161 String* name, |
| 162 Register r0, |
| 163 Register r1) { |
| 164 ASSERT(name->IsSymbol()); |
| 165 Counters* counters = masm->isolate()->counters(); |
| 166 __ IncrementCounter(counters->negative_lookups(), 1); |
| 119 __ IncrementCounter(counters->negative_lookups_miss(), 1); | 167 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
| 120 | 168 |
| 121 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); | 169 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 122 | 170 |
| 123 const int kInterceptorOrAccessCheckNeededMask = | 171 const int kInterceptorOrAccessCheckNeededMask = |
| 124 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 172 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
| 125 | 173 |
| 126 // Bail out if the receiver has a named interceptor or requires access checks. | 174 // Bail out if the receiver has a named interceptor or requires access checks. |
| 127 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), | 175 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), |
| 128 kInterceptorOrAccessCheckNeededMask); | 176 kInterceptorOrAccessCheckNeededMask); |
| 129 __ j(not_zero, miss_label); | 177 __ j(not_zero, miss_label); |
| 130 | 178 |
| 131 // Check that receiver is a JSObject. | 179 // Check that receiver is a JSObject. |
| 132 __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); | 180 __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); |
| 133 __ j(below, miss_label); | 181 __ j(below, miss_label); |
| 134 | 182 |
| 135 // Load properties array. | 183 // Load properties array. |
| 136 Register properties = r0; | 184 Register properties = r0; |
| 137 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 185 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 138 | 186 |
| 139 // Check that the properties array is a dictionary. | 187 // Check that the properties array is a dictionary. |
| 140 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), | 188 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), |
| 141 Immediate(masm->isolate()->factory()->hash_table_map())); | 189 Immediate(masm->isolate()->factory()->hash_table_map())); |
| 142 __ j(not_equal, miss_label); | 190 __ j(not_equal, miss_label); |
| 143 | 191 |
| 144 Label done; | 192 Label done; |
| 145 MaybeObject* result = | 193 MaybeObject* result = |
| 146 StringDictionaryLookupStub::GenerateNegativeLookup(masm, | 194 StringDictionaryLookupStub::TryGenerateNegativeLookup(masm, |
| 147 miss_label, | 195 miss_label, |
| 148 &done, | 196 &done, |
| 149 properties, | 197 properties, |
| 150 name, | 198 name, |
| 151 r1); | 199 r1); |
| 152 if (result->IsFailure()) return result; | 200 if (result->IsFailure()) return result; |
| 153 | 201 |
| 154 __ bind(&done); | 202 __ bind(&done); |
| 155 __ DecrementCounter(counters->negative_lookups_miss(), 1); | 203 __ DecrementCounter(counters->negative_lookups_miss(), 1); |
| 156 | 204 |
| 157 return result; | 205 return result; |
| 158 } | 206 } |
| 159 | 207 |
| 160 | 208 |
| 161 void StubCache::GenerateProbe(MacroAssembler* masm, | 209 void StubCache::GenerateProbe(MacroAssembler* masm, |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 366 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
| 319 __ mov(eax, scratch1); | 367 __ mov(eax, scratch1); |
| 320 __ ret(0); | 368 __ ret(0); |
| 321 } | 369 } |
| 322 | 370 |
| 323 | 371 |
| 324 // Load a fast property out of a holder object (src). In-object properties | 372 // Load a fast property out of a holder object (src). In-object properties |
| 325 // are loaded directly otherwise the property is loaded from the properties | 373 // are loaded directly otherwise the property is loaded from the properties |
| 326 // fixed array. | 374 // fixed array. |
| 327 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | 375 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, |
| 328 Register dst, Register src, | 376 Register dst, |
| 329 JSObject* holder, int index) { | 377 Register src, |
| 378 Handle<JSObject> holder, |
| 379 int index) { |
| 330 // Adjust for the number of properties stored in the holder. | 380 // Adjust for the number of properties stored in the holder. |
| 331 index -= holder->map()->inobject_properties(); | 381 index -= holder->map()->inobject_properties(); |
| 332 if (index < 0) { | 382 if (index < 0) { |
| 333 // Get the property straight out of the holder. | 383 // Get the property straight out of the holder. |
| 334 int offset = holder->map()->instance_size() + (index * kPointerSize); | 384 int offset = holder->map()->instance_size() + (index * kPointerSize); |
| 335 __ mov(dst, FieldOperand(src, offset)); | 385 __ mov(dst, FieldOperand(src, offset)); |
| 336 } else { | 386 } else { |
| 337 // Calculate the offset into the properties array. | 387 // Calculate the offset into the properties array. |
| 338 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 388 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
| 339 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | 389 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); |
| (...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 811 } | 861 } |
| 812 | 862 |
| 813 // Return the value (register eax). | 863 // Return the value (register eax). |
| 814 __ ret(0); | 864 __ ret(0); |
| 815 } | 865 } |
| 816 | 866 |
| 817 | 867 |
| 818 // Generate code to check that a global property cell is empty. Create | 868 // Generate code to check that a global property cell is empty. Create |
| 819 // the property cell at compilation time if no cell exists for the | 869 // the property cell at compilation time if no cell exists for the |
| 820 // property. | 870 // property. |
| 821 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell( | 871 static void GenerateCheckPropertyCell(MacroAssembler* masm, |
| 872 Handle<GlobalObject> global, |
| 873 Handle<String> name, |
| 874 Register scratch, |
| 875 Label* miss) { |
| 876 Handle<JSGlobalPropertyCell> cell = |
| 877 GlobalObject::EnsurePropertyCell(global, name); |
| 878 ASSERT(cell->value()->IsTheHole()); |
| 879 Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value(); |
| 880 if (Serializer::enabled()) { |
| 881 __ mov(scratch, Immediate(cell)); |
| 882 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
| 883 Immediate(the_hole)); |
| 884 } else { |
| 885 __ cmp(Operand::Cell(cell), Immediate(the_hole)); |
| 886 } |
| 887 __ j(not_equal, miss); |
| 888 } |
| 889 |
| 890 |
| 891 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 892 // handlified. |
| 893 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell( |
| 822 MacroAssembler* masm, | 894 MacroAssembler* masm, |
| 823 GlobalObject* global, | 895 GlobalObject* global, |
| 824 String* name, | 896 String* name, |
| 825 Register scratch, | 897 Register scratch, |
| 826 Label* miss) { | 898 Label* miss) { |
| 827 Object* probe; | 899 Object* probe; |
| 828 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); | 900 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); |
| 829 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 901 if (!maybe_probe->ToObject(&probe)) return maybe_probe; |
| 830 } | 902 } |
| 831 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); | 903 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); |
| 832 ASSERT(cell->value()->IsTheHole()); | 904 ASSERT(cell->value()->IsTheHole()); |
| 833 if (Serializer::enabled()) { | 905 if (Serializer::enabled()) { |
| 834 __ mov(scratch, Immediate(Handle<Object>(cell))); | 906 __ mov(scratch, Immediate(Handle<Object>(cell))); |
| 835 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), | 907 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
| 836 Immediate(masm->isolate()->factory()->the_hole_value())); | 908 Immediate(masm->isolate()->factory()->the_hole_value())); |
| 837 } else { | 909 } else { |
| 838 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), | 910 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), |
| 839 Immediate(masm->isolate()->factory()->the_hole_value())); | 911 Immediate(masm->isolate()->factory()->the_hole_value())); |
| 840 } | 912 } |
| 841 __ j(not_equal, miss); | 913 __ j(not_equal, miss); |
| 842 return cell; | 914 return cell; |
| 843 } | 915 } |
| 844 | 916 |
| 845 | 917 |
| 846 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | 918 // Calls GenerateCheckPropertyCell for each global object in the prototype chain |
| 847 // from object to (but not including) holder. | 919 // from object to (but not including) holder. |
| 848 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells( | 920 static void GenerateCheckPropertyCells(MacroAssembler* masm, |
| 921 Handle<JSObject> object, |
| 922 Handle<JSObject> holder, |
| 923 Handle<String> name, |
| 924 Register scratch, |
| 925 Label* miss) { |
| 926 Handle<JSObject> current = object; |
| 927 while (!current.is_identical_to(holder)) { |
| 928 if (current->IsGlobalObject()) { |
| 929 GenerateCheckPropertyCell(masm, |
| 930 Handle<GlobalObject>::cast(current), |
| 931 name, |
| 932 scratch, |
| 933 miss); |
| 934 } |
| 935 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); |
| 936 } |
| 937 } |
| 938 |
| 939 |
| 940 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 941 // handlified. |
| 942 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCells( |
| 849 MacroAssembler* masm, | 943 MacroAssembler* masm, |
| 850 JSObject* object, | 944 JSObject* object, |
| 851 JSObject* holder, | 945 JSObject* holder, |
| 852 String* name, | 946 String* name, |
| 853 Register scratch, | 947 Register scratch, |
| 854 Label* miss) { | 948 Label* miss) { |
| 855 JSObject* current = object; | 949 JSObject* current = object; |
| 856 while (current != holder) { | 950 while (current != holder) { |
| 857 if (current->IsGlobalObject()) { | 951 if (current->IsGlobalObject()) { |
| 858 // Returns a cell or a failure. | 952 // Returns a cell or a failure. |
| 859 MaybeObject* result = GenerateCheckPropertyCell( | 953 MaybeObject* result = TryGenerateCheckPropertyCell( |
| 860 masm, | 954 masm, |
| 861 GlobalObject::cast(current), | 955 GlobalObject::cast(current), |
| 862 name, | 956 name, |
| 863 scratch, | 957 scratch, |
| 864 miss); | 958 miss); |
| 865 if (result->IsFailure()) return result; | 959 if (result->IsFailure()) return result; |
| 866 } | 960 } |
| 867 ASSERT(current->IsJSObject()); | 961 ASSERT(current->IsJSObject()); |
| 868 current = JSObject::cast(current->GetPrototype()); | 962 current = JSObject::cast(current->GetPrototype()); |
| 869 } | 963 } |
| 870 return NULL; | 964 return NULL; |
| 871 } | 965 } |
| 872 | 966 |
| 873 | 967 |
| 874 #undef __ | 968 #undef __ |
| 875 #define __ ACCESS_MASM(masm()) | 969 #define __ ACCESS_MASM(masm()) |
| 876 | 970 |
| 877 | 971 |
| 972 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
| 973 Register object_reg, |
| 974 Handle<JSObject> holder, |
| 975 Register holder_reg, |
| 976 Register scratch1, |
| 977 Register scratch2, |
| 978 Handle<String> name, |
| 979 int save_at_depth, |
| 980 Label* miss) { |
| 981 // Make sure there's no overlap between holder and object registers. |
| 982 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 983 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 984 && !scratch2.is(scratch1)); |
| 985 |
| 986 // Keep track of the current object in register reg. |
| 987 Register reg = object_reg; |
| 988 Handle<JSObject> current = object; |
| 989 int depth = 0; |
| 990 |
| 991 if (save_at_depth == depth) { |
| 992 __ mov(Operand(esp, kPointerSize), reg); |
| 993 } |
| 994 |
| 995 // Traverse the prototype chain and check the maps in the prototype chain for |
| 996 // fast and global objects or do negative lookup for normal objects. |
| 997 while (!current.is_identical_to(holder)) { |
| 998 ++depth; |
| 999 |
| 1000 // Only global objects and objects that do not require access |
| 1001 // checks are allowed in stubs. |
| 1002 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); |
| 1003 |
| 1004 Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); |
| 1005 if (!current->HasFastProperties() && |
| 1006 !current->IsJSGlobalObject() && |
| 1007 !current->IsJSGlobalProxy()) { |
| 1008 if (!name->IsSymbol()) { |
| 1009 name = factory()->LookupSymbol(name); |
| 1010 } |
| 1011 ASSERT(current->property_dictionary()->FindEntry(*name) == |
| 1012 StringDictionary::kNotFound); |
| 1013 |
| 1014 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
| 1015 scratch1, scratch2); |
| 1016 |
| 1017 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1018 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1019 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1020 } else { |
| 1021 bool in_new_space = heap()->InNewSpace(*prototype); |
| 1022 Handle<Map> current_map(current->map()); |
| 1023 if (in_new_space) { |
| 1024 // Save the map in scratch1 for later. |
| 1025 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1026 __ cmp(scratch1, Immediate(current_map)); |
| 1027 } else { |
| 1028 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 1029 Immediate(current_map)); |
| 1030 } |
| 1031 // Branch on the result of the map check. |
| 1032 __ j(not_equal, miss); |
| 1033 // Check access rights to the global object. This has to happen after |
| 1034 // the map check so that we know that the object is actually a global |
| 1035 // object. |
| 1036 if (current->IsJSGlobalProxy()) { |
| 1037 __ CheckAccessGlobalProxy(reg, scratch2, miss); |
| 1038 } |
| 1039 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1040 |
| 1041 if (in_new_space) { |
| 1042 // The prototype is in new space; we cannot store a reference to it |
| 1043 // in the code. Load it from the map. |
| 1044 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1045 } else { |
| 1046 // The prototype is in old space; load it directly. |
| 1047 __ mov(reg, prototype); |
| 1048 } |
| 1049 } |
| 1050 |
| 1051 if (save_at_depth == depth) { |
| 1052 __ mov(Operand(esp, kPointerSize), reg); |
| 1053 } |
| 1054 |
| 1055 // Go to the next object in the prototype chain. |
| 1056 current = prototype; |
| 1057 } |
| 1058 ASSERT(current.is_identical_to(holder)); |
| 1059 |
| 1060 // Log the check depth. |
| 1061 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 1062 |
| 1063 // Check the holder map. |
| 1064 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 1065 Immediate(Handle<Map>(holder->map()))); |
| 1066 __ j(not_equal, miss); |
| 1067 |
| 1068 // Perform security check for access to the global object. |
| 1069 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 1070 if (holder->IsJSGlobalProxy()) { |
| 1071 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 1072 } |
| 1073 |
| 1074 // If we've skipped any global objects, it's not enough to verify that |
| 1075 // their maps haven't changed. We also need to check that the property |
| 1076 // cell for the property is still empty. |
| 1077 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
| 1078 |
| 1079 // Return the register containing the holder. |
| 1080 return reg; |
| 1081 } |
| 1082 |
| 1083 |
| 1084 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 1085 // handlified. |
| 878 Register StubCompiler::CheckPrototypes(JSObject* object, | 1086 Register StubCompiler::CheckPrototypes(JSObject* object, |
| 879 Register object_reg, | 1087 Register object_reg, |
| 880 JSObject* holder, | 1088 JSObject* holder, |
| 881 Register holder_reg, | 1089 Register holder_reg, |
| 882 Register scratch1, | 1090 Register scratch1, |
| 883 Register scratch2, | 1091 Register scratch2, |
| 884 String* name, | 1092 String* name, |
| 885 int save_at_depth, | 1093 int save_at_depth, |
| 886 Label* miss) { | 1094 Label* miss) { |
| 887 // Make sure there's no overlap between holder and object registers. | 1095 // Make sure there's no overlap between holder and object registers. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 917 Object* lookup_result = NULL; // Initialization to please compiler. | 1125 Object* lookup_result = NULL; // Initialization to please compiler. |
| 918 if (!maybe_lookup_result->ToObject(&lookup_result)) { | 1126 if (!maybe_lookup_result->ToObject(&lookup_result)) { |
| 919 set_failure(Failure::cast(maybe_lookup_result)); | 1127 set_failure(Failure::cast(maybe_lookup_result)); |
| 920 return reg; | 1128 return reg; |
| 921 } | 1129 } |
| 922 name = String::cast(lookup_result); | 1130 name = String::cast(lookup_result); |
| 923 } | 1131 } |
| 924 ASSERT(current->property_dictionary()->FindEntry(name) == | 1132 ASSERT(current->property_dictionary()->FindEntry(name) == |
| 925 StringDictionary::kNotFound); | 1133 StringDictionary::kNotFound); |
| 926 | 1134 |
| 927 MaybeObject* negative_lookup = GenerateDictionaryNegativeLookup(masm(), | 1135 MaybeObject* negative_lookup = |
| 928 miss, | 1136 TryGenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
| 929 reg, | 1137 scratch1, scratch2); |
| 930 name, | |
| 931 scratch1, | |
| 932 scratch2); | |
| 933 if (negative_lookup->IsFailure()) { | 1138 if (negative_lookup->IsFailure()) { |
| 934 set_failure(Failure::cast(negative_lookup)); | 1139 set_failure(Failure::cast(negative_lookup)); |
| 935 return reg; | 1140 return reg; |
| 936 } | 1141 } |
| 937 | 1142 |
| 938 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 1143 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 939 reg = holder_reg; // from now the object is in holder_reg | 1144 reg = holder_reg; // from now the object is in holder_reg |
| 940 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1145 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 941 } else if (heap()->InNewSpace(prototype)) { | 1146 } else if (heap()->InNewSpace(prototype)) { |
| 942 // Get the map of the current object. | 1147 // Get the map of the current object. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 989 | 1194 |
| 990 // Check the holder map. | 1195 // Check the holder map. |
| 991 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 1196 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 992 Immediate(Handle<Map>(holder->map()))); | 1197 Immediate(Handle<Map>(holder->map()))); |
| 993 __ j(not_equal, miss); | 1198 __ j(not_equal, miss); |
| 994 | 1199 |
| 995 // Perform security check for access to the global object. | 1200 // Perform security check for access to the global object. |
| 996 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1201 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 997 if (holder->IsJSGlobalProxy()) { | 1202 if (holder->IsJSGlobalProxy()) { |
| 998 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1203 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 999 }; | 1204 } |
| 1000 | 1205 |
| 1001 // If we've skipped any global objects, it's not enough to verify | 1206 // If we've skipped any global objects, it's not enough to verify |
| 1002 // that their maps haven't changed. We also need to check that the | 1207 // that their maps haven't changed. We also need to check that the |
| 1003 // property cell for the property is still empty. | 1208 // property cell for the property is still empty. |
| 1004 MaybeObject* result = GenerateCheckPropertyCells(masm(), | 1209 MaybeObject* result = TryGenerateCheckPropertyCells(masm(), |
| 1005 object, | 1210 object, |
| 1006 holder, | 1211 holder, |
| 1007 name, | 1212 name, |
| 1008 scratch1, | 1213 scratch1, |
| 1009 miss); | 1214 miss); |
| 1010 if (result->IsFailure()) set_failure(Failure::cast(result)); | 1215 if (result->IsFailure()) set_failure(Failure::cast(result)); |
| 1011 | 1216 |
| 1012 // Return the register containing the holder. | 1217 // Return the register containing the holder. |
| 1013 return reg; | 1218 return reg; |
| 1014 } | 1219 } |
| 1015 | 1220 |
| 1016 | 1221 |
| 1017 void StubCompiler::GenerateLoadField(JSObject* object, | 1222 void StubCompiler::GenerateLoadField(JSObject* object, |
| 1018 JSObject* holder, | 1223 JSObject* holder, |
| 1019 Register receiver, | 1224 Register receiver, |
| 1020 Register scratch1, | 1225 Register scratch1, |
| 1021 Register scratch2, | 1226 Register scratch2, |
| 1022 Register scratch3, | 1227 Register scratch3, |
| 1023 int index, | 1228 int index, |
| 1024 String* name, | 1229 String* name, |
| 1025 Label* miss) { | 1230 Label* miss) { |
| 1026 // Check that the receiver isn't a smi. | 1231 // Check that the receiver isn't a smi. |
| 1027 __ JumpIfSmi(receiver, miss); | 1232 __ JumpIfSmi(receiver, miss); |
| 1028 | 1233 |
| 1029 // Check the prototype chain. | 1234 // Check the prototype chain. |
| 1030 Register reg = | 1235 Register reg = |
| 1031 CheckPrototypes(object, receiver, holder, | 1236 CheckPrototypes(object, receiver, holder, |
| 1032 scratch1, scratch2, scratch3, name, miss); | 1237 scratch1, scratch2, scratch3, name, miss); |
| 1033 | 1238 |
| 1034 // Get the value from the properties. | 1239 // Get the value from the properties. |
| 1035 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); | 1240 GenerateFastPropertyLoad(masm(), eax, reg, Handle<JSObject>(holder), index); |
| 1036 __ ret(0); | 1241 __ ret(0); |
| 1037 } | 1242 } |
| 1038 | 1243 |
| 1039 | 1244 |
| 1040 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, | 1245 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, |
| 1041 JSObject* holder, | 1246 JSObject* holder, |
| 1042 Register receiver, | 1247 Register receiver, |
| 1043 Register name_reg, | 1248 Register name_reg, |
| 1044 Register scratch1, | 1249 Register scratch1, |
| 1045 Register scratch2, | 1250 Register scratch2, |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1214 scratch2, | 1419 scratch2, |
| 1215 scratch3, | 1420 scratch3, |
| 1216 name, | 1421 name, |
| 1217 miss); | 1422 miss); |
| 1218 } | 1423 } |
| 1219 | 1424 |
| 1220 if (lookup->type() == FIELD) { | 1425 if (lookup->type() == FIELD) { |
| 1221 // We found FIELD property in prototype chain of interceptor's holder. | 1426 // We found FIELD property in prototype chain of interceptor's holder. |
| 1222 // Retrieve a field from field's holder. | 1427 // Retrieve a field from field's holder. |
| 1223 GenerateFastPropertyLoad(masm(), eax, holder_reg, | 1428 GenerateFastPropertyLoad(masm(), eax, holder_reg, |
| 1224 lookup->holder(), lookup->GetFieldIndex()); | 1429 Handle<JSObject>(lookup->holder()), |
| 1430 lookup->GetFieldIndex()); |
| 1225 __ ret(0); | 1431 __ ret(0); |
| 1226 } else { | 1432 } else { |
| 1227 // We found CALLBACKS property in prototype chain of interceptor's | 1433 // We found CALLBACKS property in prototype chain of interceptor's |
| 1228 // holder. | 1434 // holder. |
| 1229 ASSERT(lookup->type() == CALLBACKS); | 1435 ASSERT(lookup->type() == CALLBACKS); |
| 1230 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); | 1436 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); |
| 1231 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 1437 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); |
| 1232 ASSERT(callback != NULL); | 1438 ASSERT(callback != NULL); |
| 1233 ASSERT(callback->getter() != NULL); | 1439 ASSERT(callback->getter() != NULL); |
| 1234 | 1440 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1261 __ push(scratch2); // restore old return address | 1467 __ push(scratch2); // restore old return address |
| 1262 | 1468 |
| 1263 ExternalReference ref = | 1469 ExternalReference ref = |
| 1264 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), | 1470 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), |
| 1265 isolate()); | 1471 isolate()); |
| 1266 __ TailCallExternalReference(ref, 5, 1); | 1472 __ TailCallExternalReference(ref, 5, 1); |
| 1267 } | 1473 } |
| 1268 } | 1474 } |
| 1269 | 1475 |
| 1270 | 1476 |
| 1271 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { | 1477 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { |
| 1272 if (kind_ == Code::KEYED_CALL_IC) { | 1478 if (kind_ == Code::KEYED_CALL_IC) { |
| 1273 __ cmp(ecx, Immediate(Handle<String>(name))); | 1479 __ cmp(ecx, Immediate(name)); |
| 1274 __ j(not_equal, miss); | 1480 __ j(not_equal, miss); |
| 1275 } | 1481 } |
| 1276 } | 1482 } |
| 1277 | 1483 |
| 1278 | 1484 |
| 1279 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, | 1485 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, |
| 1280 JSObject* holder, | 1486 JSObject* holder, |
| 1281 String* name, | 1487 String* name, |
| 1282 Label* miss) { | 1488 Label* miss) { |
| 1283 ASSERT(holder->IsGlobalObject()); | 1489 ASSERT(holder->IsGlobalObject()); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1326 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), | 1532 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), |
| 1327 Immediate(Handle<SharedFunctionInfo>(function->shared()))); | 1533 Immediate(Handle<SharedFunctionInfo>(function->shared()))); |
| 1328 __ j(not_equal, miss); | 1534 __ j(not_equal, miss); |
| 1329 } else { | 1535 } else { |
| 1330 __ cmp(edi, Immediate(Handle<JSFunction>(function))); | 1536 __ cmp(edi, Immediate(Handle<JSFunction>(function))); |
| 1331 __ j(not_equal, miss); | 1537 __ j(not_equal, miss); |
| 1332 } | 1538 } |
| 1333 } | 1539 } |
| 1334 | 1540 |
| 1335 | 1541 |
| 1336 MaybeObject* CallStubCompiler::GenerateMissBranch() { | 1542 void CallStubCompiler::GenerateMissBranch() { |
| 1543 Handle<Code> code = |
| 1544 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
| 1545 kind_, |
| 1546 extra_state_); |
| 1547 __ jmp(code, RelocInfo::CODE_TARGET); |
| 1548 } |
| 1549 |
| 1550 |
| 1551 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 1552 // handlified. |
| 1553 MaybeObject* CallStubCompiler::TryGenerateMissBranch() { |
| 1337 MaybeObject* maybe_obj = | 1554 MaybeObject* maybe_obj = |
| 1338 isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(), | 1555 isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(), |
| 1339 kind_, | 1556 kind_, |
| 1340 extra_state_); | 1557 extra_state_); |
| 1341 Object* obj; | 1558 Object* obj; |
| 1342 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1559 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 1343 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | 1560 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); |
| 1344 return obj; | 1561 return obj; |
| 1345 } | 1562 } |
| 1346 | 1563 |
| 1347 | 1564 |
| 1348 MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField( | 1565 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| 1349 JSObject* object, | 1566 Handle<JSObject> holder, |
| 1350 JSObject* holder, | 1567 int index, |
| 1351 int index, | 1568 Handle<String> name) { |
| 1352 String* name) { | |
| 1353 // ----------- S t a t e ------------- | 1569 // ----------- S t a t e ------------- |
| 1354 // -- ecx : name | 1570 // -- ecx : name |
| 1355 // -- esp[0] : return address | 1571 // -- esp[0] : return address |
| 1356 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1572 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1357 // -- ... | 1573 // -- ... |
| 1358 // -- esp[(argc + 1) * 4] : receiver | 1574 // -- esp[(argc + 1) * 4] : receiver |
| 1359 // ----------------------------------- | 1575 // ----------------------------------- |
| 1360 Label miss; | 1576 Label miss; |
| 1361 | 1577 |
| 1362 GenerateNameCheck(name, &miss); | 1578 GenerateNameCheck(name, &miss); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1388 | 1604 |
| 1389 // Invoke the function. | 1605 // Invoke the function. |
| 1390 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 1606 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 1391 ? CALL_AS_FUNCTION | 1607 ? CALL_AS_FUNCTION |
| 1392 : CALL_AS_METHOD; | 1608 : CALL_AS_METHOD; |
| 1393 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, | 1609 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, |
| 1394 NullCallWrapper(), call_kind); | 1610 NullCallWrapper(), call_kind); |
| 1395 | 1611 |
| 1396 // Handle call cache miss. | 1612 // Handle call cache miss. |
| 1397 __ bind(&miss); | 1613 __ bind(&miss); |
| 1398 MaybeObject* maybe_result = GenerateMissBranch(); | 1614 GenerateMissBranch(); |
| 1399 if (maybe_result->IsFailure()) return maybe_result; | |
| 1400 | 1615 |
| 1401 // Return the generated code. | 1616 // Return the generated code. |
| 1402 return GetCode(FIELD, name); | 1617 return GetCode(FIELD, name); |
| 1403 } | 1618 } |
| 1404 | 1619 |
| 1405 | 1620 |
| 1406 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, | 1621 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, |
| 1407 JSObject* holder, | 1622 JSObject* holder, |
| 1408 JSGlobalPropertyCell* cell, | 1623 JSGlobalPropertyCell* cell, |
| 1409 JSFunction* function, | 1624 JSFunction* function, |
| 1410 String* name) { | 1625 String* name) { |
| 1411 // ----------- S t a t e ------------- | 1626 // ----------- S t a t e ------------- |
| 1412 // -- ecx : name | 1627 // -- ecx : name |
| 1413 // -- esp[0] : return address | 1628 // -- esp[0] : return address |
| 1414 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1629 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1415 // -- ... | 1630 // -- ... |
| 1416 // -- esp[(argc + 1) * 4] : receiver | 1631 // -- esp[(argc + 1) * 4] : receiver |
| 1417 // ----------------------------------- | 1632 // ----------------------------------- |
| 1418 | 1633 |
| 1419 // If object is not an array, bail out to regular call. | 1634 // If object is not an array, bail out to regular call. |
| 1420 if (!object->IsJSArray() || cell != NULL) { | 1635 if (!object->IsJSArray() || cell != NULL) { |
| 1421 return isolate()->heap()->undefined_value(); | 1636 return isolate()->heap()->undefined_value(); |
| 1422 } | 1637 } |
| 1423 | 1638 |
| 1424 Label miss; | 1639 Label miss; |
| 1425 | 1640 |
| 1426 GenerateNameCheck(name, &miss); | 1641 GenerateNameCheck(Handle<String>(name), &miss); |
| 1427 | 1642 |
| 1428 // Get the receiver from the stack. | 1643 // Get the receiver from the stack. |
| 1429 const int argc = arguments().immediate(); | 1644 const int argc = arguments().immediate(); |
| 1430 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1645 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1431 | 1646 |
| 1432 // Check that the receiver isn't a smi. | 1647 // Check that the receiver isn't a smi. |
| 1433 __ JumpIfSmi(edx, &miss); | 1648 __ JumpIfSmi(edx, &miss); |
| 1434 | 1649 |
| 1435 CheckPrototypes(JSObject::cast(object), edx, | 1650 CheckPrototypes(JSObject::cast(object), edx, |
| 1436 holder, ebx, | 1651 holder, ebx, |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1573 } | 1788 } |
| 1574 | 1789 |
| 1575 __ bind(&call_builtin); | 1790 __ bind(&call_builtin); |
| 1576 __ TailCallExternalReference( | 1791 __ TailCallExternalReference( |
| 1577 ExternalReference(Builtins::c_ArrayPush, isolate()), | 1792 ExternalReference(Builtins::c_ArrayPush, isolate()), |
| 1578 argc + 1, | 1793 argc + 1, |
| 1579 1); | 1794 1); |
| 1580 } | 1795 } |
| 1581 | 1796 |
| 1582 __ bind(&miss); | 1797 __ bind(&miss); |
| 1583 MaybeObject* maybe_result = GenerateMissBranch(); | 1798 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1584 if (maybe_result->IsFailure()) return maybe_result; | 1799 if (maybe_result->IsFailure()) return maybe_result; |
| 1585 | 1800 |
| 1586 // Return the generated code. | 1801 // Return the generated code. |
| 1587 return GetCode(function); | 1802 return TryGetCode(function); |
| 1588 } | 1803 } |
| 1589 | 1804 |
| 1590 | 1805 |
| 1591 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, | 1806 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, |
| 1592 JSObject* holder, | 1807 JSObject* holder, |
| 1593 JSGlobalPropertyCell* cell, | 1808 JSGlobalPropertyCell* cell, |
| 1594 JSFunction* function, | 1809 JSFunction* function, |
| 1595 String* name) { | 1810 String* name) { |
| 1596 // ----------- S t a t e ------------- | 1811 // ----------- S t a t e ------------- |
| 1597 // -- ecx : name | 1812 // -- ecx : name |
| 1598 // -- esp[0] : return address | 1813 // -- esp[0] : return address |
| 1599 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1814 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1600 // -- ... | 1815 // -- ... |
| 1601 // -- esp[(argc + 1) * 4] : receiver | 1816 // -- esp[(argc + 1) * 4] : receiver |
| 1602 // ----------------------------------- | 1817 // ----------------------------------- |
| 1603 | 1818 |
| 1604 // If object is not an array, bail out to regular call. | 1819 // If object is not an array, bail out to regular call. |
| 1605 if (!object->IsJSArray() || cell != NULL) { | 1820 if (!object->IsJSArray() || cell != NULL) { |
| 1606 return heap()->undefined_value(); | 1821 return heap()->undefined_value(); |
| 1607 } | 1822 } |
| 1608 | 1823 |
| 1609 Label miss, return_undefined, call_builtin; | 1824 Label miss, return_undefined, call_builtin; |
| 1610 | 1825 |
| 1611 GenerateNameCheck(name, &miss); | 1826 GenerateNameCheck(Handle<String>(name), &miss); |
| 1612 | 1827 |
| 1613 // Get the receiver from the stack. | 1828 // Get the receiver from the stack. |
| 1614 const int argc = arguments().immediate(); | 1829 const int argc = arguments().immediate(); |
| 1615 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1830 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1616 | 1831 |
| 1617 // Check that the receiver isn't a smi. | 1832 // Check that the receiver isn't a smi. |
| 1618 __ JumpIfSmi(edx, &miss); | 1833 __ JumpIfSmi(edx, &miss); |
| 1619 CheckPrototypes(JSObject::cast(object), edx, | 1834 CheckPrototypes(JSObject::cast(object), edx, |
| 1620 holder, ebx, | 1835 holder, ebx, |
| 1621 eax, edi, name, &miss); | 1836 eax, edi, name, &miss); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1656 __ mov(eax, Immediate(factory()->undefined_value())); | 1871 __ mov(eax, Immediate(factory()->undefined_value())); |
| 1657 __ ret((argc + 1) * kPointerSize); | 1872 __ ret((argc + 1) * kPointerSize); |
| 1658 | 1873 |
| 1659 __ bind(&call_builtin); | 1874 __ bind(&call_builtin); |
| 1660 __ TailCallExternalReference( | 1875 __ TailCallExternalReference( |
| 1661 ExternalReference(Builtins::c_ArrayPop, isolate()), | 1876 ExternalReference(Builtins::c_ArrayPop, isolate()), |
| 1662 argc + 1, | 1877 argc + 1, |
| 1663 1); | 1878 1); |
| 1664 | 1879 |
| 1665 __ bind(&miss); | 1880 __ bind(&miss); |
| 1666 MaybeObject* maybe_result = GenerateMissBranch(); | 1881 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1667 if (maybe_result->IsFailure()) return maybe_result; | 1882 if (maybe_result->IsFailure()) return maybe_result; |
| 1668 | 1883 |
| 1669 // Return the generated code. | 1884 // Return the generated code. |
| 1670 return GetCode(function); | 1885 return TryGetCode(function); |
| 1671 } | 1886 } |
| 1672 | 1887 |
| 1673 | 1888 |
| 1674 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( | 1889 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( |
| 1675 Object* object, | 1890 Object* object, |
| 1676 JSObject* holder, | 1891 JSObject* holder, |
| 1677 JSGlobalPropertyCell* cell, | 1892 JSGlobalPropertyCell* cell, |
| 1678 JSFunction* function, | 1893 JSFunction* function, |
| 1679 String* name) { | 1894 String* name) { |
| 1680 // ----------- S t a t e ------------- | 1895 // ----------- S t a t e ------------- |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1696 Label name_miss; | 1911 Label name_miss; |
| 1697 Label index_out_of_range; | 1912 Label index_out_of_range; |
| 1698 Label* index_out_of_range_label = &index_out_of_range; | 1913 Label* index_out_of_range_label = &index_out_of_range; |
| 1699 | 1914 |
| 1700 if (kind_ == Code::CALL_IC && | 1915 if (kind_ == Code::CALL_IC && |
| 1701 (CallICBase::StringStubState::decode(extra_state_) == | 1916 (CallICBase::StringStubState::decode(extra_state_) == |
| 1702 DEFAULT_STRING_STUB)) { | 1917 DEFAULT_STRING_STUB)) { |
| 1703 index_out_of_range_label = &miss; | 1918 index_out_of_range_label = &miss; |
| 1704 } | 1919 } |
| 1705 | 1920 |
| 1706 GenerateNameCheck(name, &name_miss); | 1921 GenerateNameCheck(Handle<String>(name), &name_miss); |
| 1707 | 1922 |
| 1708 // Check that the maps starting from the prototype haven't changed. | 1923 // Check that the maps starting from the prototype haven't changed. |
| 1709 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1924 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 1710 Context::STRING_FUNCTION_INDEX, | 1925 Context::STRING_FUNCTION_INDEX, |
| 1711 eax, | 1926 eax, |
| 1712 &miss); | 1927 &miss); |
| 1713 ASSERT(object != holder); | 1928 ASSERT(object != holder); |
| 1714 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 1929 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
| 1715 ebx, edx, edi, name, &miss); | 1930 ebx, edx, edi, name, &miss); |
| 1716 | 1931 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1742 if (index_out_of_range.is_linked()) { | 1957 if (index_out_of_range.is_linked()) { |
| 1743 __ bind(&index_out_of_range); | 1958 __ bind(&index_out_of_range); |
| 1744 __ Set(eax, Immediate(factory()->nan_value())); | 1959 __ Set(eax, Immediate(factory()->nan_value())); |
| 1745 __ ret((argc + 1) * kPointerSize); | 1960 __ ret((argc + 1) * kPointerSize); |
| 1746 } | 1961 } |
| 1747 | 1962 |
| 1748 __ bind(&miss); | 1963 __ bind(&miss); |
| 1749 // Restore function name in ecx. | 1964 // Restore function name in ecx. |
| 1750 __ Set(ecx, Immediate(Handle<String>(name))); | 1965 __ Set(ecx, Immediate(Handle<String>(name))); |
| 1751 __ bind(&name_miss); | 1966 __ bind(&name_miss); |
| 1752 MaybeObject* maybe_result = GenerateMissBranch(); | 1967 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1753 if (maybe_result->IsFailure()) return maybe_result; | 1968 if (maybe_result->IsFailure()) return maybe_result; |
| 1754 | 1969 |
| 1755 // Return the generated code. | 1970 // Return the generated code. |
| 1756 return GetCode(function); | 1971 return TryGetCode(function); |
| 1757 } | 1972 } |
| 1758 | 1973 |
| 1759 | 1974 |
| 1760 MaybeObject* CallStubCompiler::CompileStringCharAtCall( | 1975 MaybeObject* CallStubCompiler::CompileStringCharAtCall( |
| 1761 Object* object, | 1976 Object* object, |
| 1762 JSObject* holder, | 1977 JSObject* holder, |
| 1763 JSGlobalPropertyCell* cell, | 1978 JSGlobalPropertyCell* cell, |
| 1764 JSFunction* function, | 1979 JSFunction* function, |
| 1765 String* name) { | 1980 String* name) { |
| 1766 // ----------- S t a t e ------------- | 1981 // ----------- S t a t e ------------- |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1782 Label name_miss; | 1997 Label name_miss; |
| 1783 Label index_out_of_range; | 1998 Label index_out_of_range; |
| 1784 Label* index_out_of_range_label = &index_out_of_range; | 1999 Label* index_out_of_range_label = &index_out_of_range; |
| 1785 | 2000 |
| 1786 if (kind_ == Code::CALL_IC && | 2001 if (kind_ == Code::CALL_IC && |
| 1787 (CallICBase::StringStubState::decode(extra_state_) == | 2002 (CallICBase::StringStubState::decode(extra_state_) == |
| 1788 DEFAULT_STRING_STUB)) { | 2003 DEFAULT_STRING_STUB)) { |
| 1789 index_out_of_range_label = &miss; | 2004 index_out_of_range_label = &miss; |
| 1790 } | 2005 } |
| 1791 | 2006 |
| 1792 GenerateNameCheck(name, &name_miss); | 2007 GenerateNameCheck(Handle<String>(name), &name_miss); |
| 1793 | 2008 |
| 1794 // Check that the maps starting from the prototype haven't changed. | 2009 // Check that the maps starting from the prototype haven't changed. |
| 1795 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 2010 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 1796 Context::STRING_FUNCTION_INDEX, | 2011 Context::STRING_FUNCTION_INDEX, |
| 1797 eax, | 2012 eax, |
| 1798 &miss); | 2013 &miss); |
| 1799 ASSERT(object != holder); | 2014 ASSERT(object != holder); |
| 1800 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2015 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
| 1801 ebx, edx, edi, name, &miss); | 2016 ebx, edx, edi, name, &miss); |
| 1802 | 2017 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1830 if (index_out_of_range.is_linked()) { | 2045 if (index_out_of_range.is_linked()) { |
| 1831 __ bind(&index_out_of_range); | 2046 __ bind(&index_out_of_range); |
| 1832 __ Set(eax, Immediate(factory()->empty_string())); | 2047 __ Set(eax, Immediate(factory()->empty_string())); |
| 1833 __ ret((argc + 1) * kPointerSize); | 2048 __ ret((argc + 1) * kPointerSize); |
| 1834 } | 2049 } |
| 1835 | 2050 |
| 1836 __ bind(&miss); | 2051 __ bind(&miss); |
| 1837 // Restore function name in ecx. | 2052 // Restore function name in ecx. |
| 1838 __ Set(ecx, Immediate(Handle<String>(name))); | 2053 __ Set(ecx, Immediate(Handle<String>(name))); |
| 1839 __ bind(&name_miss); | 2054 __ bind(&name_miss); |
| 1840 MaybeObject* maybe_result = GenerateMissBranch(); | 2055 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1841 if (maybe_result->IsFailure()) return maybe_result; | 2056 if (maybe_result->IsFailure()) return maybe_result; |
| 1842 | 2057 |
| 1843 // Return the generated code. | 2058 // Return the generated code. |
| 1844 return GetCode(function); | 2059 return TryGetCode(function); |
| 1845 } | 2060 } |
| 1846 | 2061 |
| 1847 | 2062 |
| 1848 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( | 2063 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( |
| 1849 Object* object, | 2064 Object* object, |
| 1850 JSObject* holder, | 2065 JSObject* holder, |
| 1851 JSGlobalPropertyCell* cell, | 2066 JSGlobalPropertyCell* cell, |
| 1852 JSFunction* function, | 2067 JSFunction* function, |
| 1853 String* name) { | 2068 String* name) { |
| 1854 // ----------- S t a t e ------------- | 2069 // ----------- S t a t e ------------- |
| 1855 // -- ecx : function name | 2070 // -- ecx : function name |
| 1856 // -- esp[0] : return address | 2071 // -- esp[0] : return address |
| 1857 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2072 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1858 // -- ... | 2073 // -- ... |
| 1859 // -- esp[(argc + 1) * 4] : receiver | 2074 // -- esp[(argc + 1) * 4] : receiver |
| 1860 // ----------------------------------- | 2075 // ----------------------------------- |
| 1861 | 2076 |
| 1862 const int argc = arguments().immediate(); | 2077 const int argc = arguments().immediate(); |
| 1863 | 2078 |
| 1864 // If the object is not a JSObject or we got an unexpected number of | 2079 // If the object is not a JSObject or we got an unexpected number of |
| 1865 // arguments, bail out to the regular call. | 2080 // arguments, bail out to the regular call. |
| 1866 if (!object->IsJSObject() || argc != 1) { | 2081 if (!object->IsJSObject() || argc != 1) { |
| 1867 return isolate()->heap()->undefined_value(); | 2082 return isolate()->heap()->undefined_value(); |
| 1868 } | 2083 } |
| 1869 | 2084 |
| 1870 Label miss; | 2085 Label miss; |
| 1871 GenerateNameCheck(name, &miss); | 2086 GenerateNameCheck(Handle<String>(name), &miss); |
| 1872 | 2087 |
| 1873 if (cell == NULL) { | 2088 if (cell == NULL) { |
| 1874 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2089 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 1875 | 2090 |
| 1876 STATIC_ASSERT(kSmiTag == 0); | 2091 STATIC_ASSERT(kSmiTag == 0); |
| 1877 __ JumpIfSmi(edx, &miss); | 2092 __ JumpIfSmi(edx, &miss); |
| 1878 | 2093 |
| 1879 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | 2094 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, |
| 1880 &miss); | 2095 &miss); |
| 1881 } else { | 2096 } else { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1907 // because the function makes no use of it. | 2122 // because the function makes no use of it. |
| 1908 __ bind(&slow); | 2123 __ bind(&slow); |
| 1909 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2124 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 1910 ? CALL_AS_FUNCTION | 2125 ? CALL_AS_FUNCTION |
| 1911 : CALL_AS_METHOD; | 2126 : CALL_AS_METHOD; |
| 1912 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2127 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 1913 NullCallWrapper(), call_kind); | 2128 NullCallWrapper(), call_kind); |
| 1914 | 2129 |
| 1915 __ bind(&miss); | 2130 __ bind(&miss); |
| 1916 // ecx: function name. | 2131 // ecx: function name. |
| 1917 MaybeObject* maybe_result = GenerateMissBranch(); | 2132 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1918 if (maybe_result->IsFailure()) return maybe_result; | 2133 if (maybe_result->IsFailure()) return maybe_result; |
| 1919 | 2134 |
| 1920 // Return the generated code. | 2135 // Return the generated code. |
| 1921 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2136 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
| 1922 } | 2137 } |
| 1923 | 2138 |
| 1924 | 2139 |
| 1925 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, | 2140 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, |
| 1926 JSObject* holder, | 2141 JSObject* holder, |
| 1927 JSGlobalPropertyCell* cell, | 2142 JSGlobalPropertyCell* cell, |
| 1928 JSFunction* function, | 2143 JSFunction* function, |
| 1929 String* name) { | 2144 String* name) { |
| 1930 // ----------- S t a t e ------------- | 2145 // ----------- S t a t e ------------- |
| 1931 // -- ecx : name | 2146 // -- ecx : name |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1943 | 2158 |
| 1944 const int argc = arguments().immediate(); | 2159 const int argc = arguments().immediate(); |
| 1945 | 2160 |
| 1946 // If the object is not a JSObject or we got an unexpected number of | 2161 // If the object is not a JSObject or we got an unexpected number of |
| 1947 // arguments, bail out to the regular call. | 2162 // arguments, bail out to the regular call. |
| 1948 if (!object->IsJSObject() || argc != 1) { | 2163 if (!object->IsJSObject() || argc != 1) { |
| 1949 return isolate()->heap()->undefined_value(); | 2164 return isolate()->heap()->undefined_value(); |
| 1950 } | 2165 } |
| 1951 | 2166 |
| 1952 Label miss; | 2167 Label miss; |
| 1953 GenerateNameCheck(name, &miss); | 2168 GenerateNameCheck(Handle<String>(name), &miss); |
| 1954 | 2169 |
| 1955 if (cell == NULL) { | 2170 if (cell == NULL) { |
| 1956 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2171 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 1957 | 2172 |
| 1958 STATIC_ASSERT(kSmiTag == 0); | 2173 STATIC_ASSERT(kSmiTag == 0); |
| 1959 __ JumpIfSmi(edx, &miss); | 2174 __ JumpIfSmi(edx, &miss); |
| 1960 | 2175 |
| 1961 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | 2176 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, |
| 1962 &miss); | 2177 &miss); |
| 1963 } else { | 2178 } else { |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2036 __ ret(2 * kPointerSize); | 2251 __ ret(2 * kPointerSize); |
| 2037 | 2252 |
| 2038 // Tail call the full function. We do not have to patch the receiver | 2253 // Tail call the full function. We do not have to patch the receiver |
| 2039 // because the function makes no use of it. | 2254 // because the function makes no use of it. |
| 2040 __ bind(&slow); | 2255 __ bind(&slow); |
| 2041 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2256 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 2042 NullCallWrapper(), CALL_AS_METHOD); | 2257 NullCallWrapper(), CALL_AS_METHOD); |
| 2043 | 2258 |
| 2044 __ bind(&miss); | 2259 __ bind(&miss); |
| 2045 // ecx: function name. | 2260 // ecx: function name. |
| 2046 MaybeObject* maybe_result = GenerateMissBranch(); | 2261 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2047 if (maybe_result->IsFailure()) return maybe_result; | 2262 if (maybe_result->IsFailure()) return maybe_result; |
| 2048 | 2263 |
| 2049 // Return the generated code. | 2264 // Return the generated code. |
| 2050 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2265 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
| 2051 } | 2266 } |
| 2052 | 2267 |
| 2053 | 2268 |
| 2054 MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, | 2269 MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, |
| 2055 JSObject* holder, | 2270 JSObject* holder, |
| 2056 JSGlobalPropertyCell* cell, | 2271 JSGlobalPropertyCell* cell, |
| 2057 JSFunction* function, | 2272 JSFunction* function, |
| 2058 String* name) { | 2273 String* name) { |
| 2059 // ----------- S t a t e ------------- | 2274 // ----------- S t a t e ------------- |
| 2060 // -- ecx : name | 2275 // -- ecx : name |
| 2061 // -- esp[0] : return address | 2276 // -- esp[0] : return address |
| 2062 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2277 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 2063 // -- ... | 2278 // -- ... |
| 2064 // -- esp[(argc + 1) * 4] : receiver | 2279 // -- esp[(argc + 1) * 4] : receiver |
| 2065 // ----------------------------------- | 2280 // ----------------------------------- |
| 2066 | 2281 |
| 2067 const int argc = arguments().immediate(); | 2282 const int argc = arguments().immediate(); |
| 2068 | 2283 |
| 2069 // If the object is not a JSObject or we got an unexpected number of | 2284 // If the object is not a JSObject or we got an unexpected number of |
| 2070 // arguments, bail out to the regular call. | 2285 // arguments, bail out to the regular call. |
| 2071 if (!object->IsJSObject() || argc != 1) { | 2286 if (!object->IsJSObject() || argc != 1) { |
| 2072 return isolate()->heap()->undefined_value(); | 2287 return isolate()->heap()->undefined_value(); |
| 2073 } | 2288 } |
| 2074 | 2289 |
| 2075 Label miss; | 2290 Label miss; |
| 2076 GenerateNameCheck(name, &miss); | 2291 GenerateNameCheck(Handle<String>(name), &miss); |
| 2077 | 2292 |
| 2078 if (cell == NULL) { | 2293 if (cell == NULL) { |
| 2079 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2294 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 2080 | 2295 |
| 2081 STATIC_ASSERT(kSmiTag == 0); | 2296 STATIC_ASSERT(kSmiTag == 0); |
| 2082 __ JumpIfSmi(edx, &miss); | 2297 __ JumpIfSmi(edx, &miss); |
| 2083 | 2298 |
| 2084 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | 2299 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, |
| 2085 &miss); | 2300 &miss); |
| 2086 } else { | 2301 } else { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2140 __ ret(2 * kPointerSize); | 2355 __ ret(2 * kPointerSize); |
| 2141 | 2356 |
| 2142 // Tail call the full function. We do not have to patch the receiver | 2357 // Tail call the full function. We do not have to patch the receiver |
| 2143 // because the function makes no use of it. | 2358 // because the function makes no use of it. |
| 2144 __ bind(&slow); | 2359 __ bind(&slow); |
| 2145 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2360 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 2146 NullCallWrapper(), CALL_AS_METHOD); | 2361 NullCallWrapper(), CALL_AS_METHOD); |
| 2147 | 2362 |
| 2148 __ bind(&miss); | 2363 __ bind(&miss); |
| 2149 // ecx: function name. | 2364 // ecx: function name. |
| 2150 MaybeObject* maybe_result = GenerateMissBranch(); | 2365 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2151 if (maybe_result->IsFailure()) return maybe_result; | 2366 if (maybe_result->IsFailure()) return maybe_result; |
| 2152 | 2367 |
| 2153 // Return the generated code. | 2368 // Return the generated code. |
| 2154 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2369 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
| 2155 } | 2370 } |
| 2156 | 2371 |
| 2157 | 2372 |
| 2158 MaybeObject* CallStubCompiler::CompileFastApiCall( | 2373 MaybeObject* CallStubCompiler::CompileFastApiCall( |
| 2159 const CallOptimization& optimization, | 2374 const CallOptimization& optimization, |
| 2160 Object* object, | 2375 Object* object, |
| 2161 JSObject* holder, | 2376 JSObject* holder, |
| 2162 JSGlobalPropertyCell* cell, | 2377 JSGlobalPropertyCell* cell, |
| 2163 JSFunction* function, | 2378 JSFunction* function, |
| 2164 String* name) { | 2379 String* name) { |
| 2165 ASSERT(optimization.is_simple_api_call()); | 2380 ASSERT(optimization.is_simple_api_call()); |
| 2166 // Bail out if object is a global object as we don't want to | 2381 // Bail out if object is a global object as we don't want to |
| 2167 // repatch it to global receiver. | 2382 // repatch it to global receiver. |
| 2168 if (object->IsGlobalObject()) return heap()->undefined_value(); | 2383 if (object->IsGlobalObject()) return heap()->undefined_value(); |
| 2169 if (cell != NULL) return heap()->undefined_value(); | 2384 if (cell != NULL) return heap()->undefined_value(); |
| 2170 if (!object->IsJSObject()) return heap()->undefined_value(); | 2385 if (!object->IsJSObject()) return heap()->undefined_value(); |
| 2171 int depth = optimization.GetPrototypeDepthOfExpectedType( | 2386 int depth = optimization.GetPrototypeDepthOfExpectedType( |
| 2172 JSObject::cast(object), holder); | 2387 JSObject::cast(object), holder); |
| 2173 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); | 2388 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); |
| 2174 | 2389 |
| 2175 Label miss, miss_before_stack_reserved; | 2390 Label miss, miss_before_stack_reserved; |
| 2176 | 2391 |
| 2177 GenerateNameCheck(name, &miss_before_stack_reserved); | 2392 GenerateNameCheck(Handle<String>(name), &miss_before_stack_reserved); |
| 2178 | 2393 |
| 2179 // Get the receiver from the stack. | 2394 // Get the receiver from the stack. |
| 2180 const int argc = arguments().immediate(); | 2395 const int argc = arguments().immediate(); |
| 2181 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2396 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2182 | 2397 |
| 2183 // Check that the receiver isn't a smi. | 2398 // Check that the receiver isn't a smi. |
| 2184 __ JumpIfSmi(edx, &miss_before_stack_reserved); | 2399 __ JumpIfSmi(edx, &miss_before_stack_reserved); |
| 2185 | 2400 |
| 2186 Counters* counters = isolate()->counters(); | 2401 Counters* counters = isolate()->counters(); |
| 2187 __ IncrementCounter(counters->call_const(), 1); | 2402 __ IncrementCounter(counters->call_const(), 1); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2201 | 2416 |
| 2202 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains | 2417 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains |
| 2203 // duplicate of return address and will be overwritten. | 2418 // duplicate of return address and will be overwritten. |
| 2204 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); | 2419 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); |
| 2205 if (result->IsFailure()) return result; | 2420 if (result->IsFailure()) return result; |
| 2206 | 2421 |
| 2207 __ bind(&miss); | 2422 __ bind(&miss); |
| 2208 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); | 2423 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2209 | 2424 |
| 2210 __ bind(&miss_before_stack_reserved); | 2425 __ bind(&miss_before_stack_reserved); |
| 2211 MaybeObject* maybe_result = GenerateMissBranch(); | 2426 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2212 if (maybe_result->IsFailure()) return maybe_result; | 2427 if (maybe_result->IsFailure()) return maybe_result; |
| 2213 | 2428 |
| 2214 // Return the generated code. | 2429 // Return the generated code. |
| 2215 return GetCode(function); | 2430 return TryGetCode(function); |
| 2216 } | 2431 } |
| 2217 | 2432 |
| 2218 | 2433 |
| 2219 MaybeObject* CallStubCompiler::CompileCallConstant( | 2434 MaybeObject* CallStubCompiler::CompileCallConstant( |
| 2220 Object* object, | 2435 Object* object, |
| 2221 JSObject* holder, | 2436 JSObject* holder, |
| 2222 JSFunction* function, | 2437 JSFunction* function, |
| 2223 String* name, | 2438 String* name, |
| 2224 CheckType check) { | 2439 CheckType check) { |
| 2225 // ----------- S t a t e ------------- | 2440 // ----------- S t a t e ------------- |
| 2226 // -- ecx : name | 2441 // -- ecx : name |
| 2227 // -- esp[0] : return address | 2442 // -- esp[0] : return address |
| 2228 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2443 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 2229 // -- ... | 2444 // -- ... |
| 2230 // -- esp[(argc + 1) * 4] : receiver | 2445 // -- esp[(argc + 1) * 4] : receiver |
| 2231 // ----------------------------------- | 2446 // ----------------------------------- |
| 2232 | 2447 |
| 2233 if (HasCustomCallGenerator(function)) { | 2448 if (HasCustomCallGenerator(function)) { |
| 2234 MaybeObject* maybe_result = CompileCustomCall( | 2449 MaybeObject* maybe_result = CompileCustomCall( |
| 2235 object, holder, NULL, function, name); | 2450 object, holder, NULL, function, name); |
| 2236 Object* result; | 2451 Object* result; |
| 2237 if (!maybe_result->ToObject(&result)) return maybe_result; | 2452 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2238 // undefined means bail out to regular compiler. | 2453 // undefined means bail out to regular compiler. |
| 2239 if (!result->IsUndefined()) return result; | 2454 if (!result->IsUndefined()) return result; |
| 2240 } | 2455 } |
| 2241 | 2456 |
| 2242 Label miss; | 2457 Label miss; |
| 2243 | 2458 |
| 2244 GenerateNameCheck(name, &miss); | 2459 GenerateNameCheck(Handle<String>(name), &miss); |
| 2245 | 2460 |
| 2246 // Get the receiver from the stack. | 2461 // Get the receiver from the stack. |
| 2247 const int argc = arguments().immediate(); | 2462 const int argc = arguments().immediate(); |
| 2248 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2463 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2249 | 2464 |
| 2250 // Check that the receiver isn't a smi. | 2465 // Check that the receiver isn't a smi. |
| 2251 if (check != NUMBER_CHECK) { | 2466 if (check != NUMBER_CHECK) { |
| 2252 __ JumpIfSmi(edx, &miss); | 2467 __ JumpIfSmi(edx, &miss); |
| 2253 } | 2468 } |
| 2254 | 2469 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2338 } | 2553 } |
| 2339 | 2554 |
| 2340 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2555 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2341 ? CALL_AS_FUNCTION | 2556 ? CALL_AS_FUNCTION |
| 2342 : CALL_AS_METHOD; | 2557 : CALL_AS_METHOD; |
| 2343 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2558 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 2344 NullCallWrapper(), call_kind); | 2559 NullCallWrapper(), call_kind); |
| 2345 | 2560 |
| 2346 // Handle call cache miss. | 2561 // Handle call cache miss. |
| 2347 __ bind(&miss); | 2562 __ bind(&miss); |
| 2348 MaybeObject* maybe_result = GenerateMissBranch(); | 2563 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2349 if (maybe_result->IsFailure()) return maybe_result; | 2564 if (maybe_result->IsFailure()) return maybe_result; |
| 2350 | 2565 |
| 2351 // Return the generated code. | 2566 // Return the generated code. |
| 2352 return GetCode(function); | 2567 return TryGetCode(function); |
| 2353 } | 2568 } |
| 2354 | 2569 |
| 2355 | 2570 |
| 2356 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, | 2571 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, |
| 2357 JSObject* holder, | 2572 JSObject* holder, |
| 2358 String* name) { | 2573 String* name) { |
| 2359 // ----------- S t a t e ------------- | 2574 // ----------- S t a t e ------------- |
| 2360 // -- ecx : name | 2575 // -- ecx : name |
| 2361 // -- esp[0] : return address | 2576 // -- esp[0] : return address |
| 2362 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2577 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 2363 // -- ... | 2578 // -- ... |
| 2364 // -- esp[(argc + 1) * 4] : receiver | 2579 // -- esp[(argc + 1) * 4] : receiver |
| 2365 // ----------------------------------- | 2580 // ----------------------------------- |
| 2366 Label miss; | 2581 Label miss; |
| 2367 | 2582 |
| 2368 GenerateNameCheck(name, &miss); | 2583 GenerateNameCheck(Handle<String>(name), &miss); |
| 2369 | 2584 |
| 2370 // Get the number of arguments. | 2585 // Get the number of arguments. |
| 2371 const int argc = arguments().immediate(); | 2586 const int argc = arguments().immediate(); |
| 2372 | 2587 |
| 2373 LookupResult lookup(isolate()); | 2588 LookupResult lookup(isolate()); |
| 2374 LookupPostInterceptor(holder, name, &lookup); | 2589 LookupPostInterceptor(holder, name, &lookup); |
| 2375 | 2590 |
| 2376 // Get the receiver from the stack. | 2591 // Get the receiver from the stack. |
| 2377 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2592 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2378 | 2593 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2407 // Invoke the function. | 2622 // Invoke the function. |
| 2408 __ mov(edi, eax); | 2623 __ mov(edi, eax); |
| 2409 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2624 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2410 ? CALL_AS_FUNCTION | 2625 ? CALL_AS_FUNCTION |
| 2411 : CALL_AS_METHOD; | 2626 : CALL_AS_METHOD; |
| 2412 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, | 2627 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, |
| 2413 NullCallWrapper(), call_kind); | 2628 NullCallWrapper(), call_kind); |
| 2414 | 2629 |
| 2415 // Handle load cache miss. | 2630 // Handle load cache miss. |
| 2416 __ bind(&miss); | 2631 __ bind(&miss); |
| 2417 MaybeObject* maybe_result = GenerateMissBranch(); | 2632 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2418 if (maybe_result->IsFailure()) return maybe_result; | 2633 if (maybe_result->IsFailure()) return maybe_result; |
| 2419 | 2634 |
| 2420 // Return the generated code. | 2635 // Return the generated code. |
| 2421 return GetCode(INTERCEPTOR, name); | 2636 return TryGetCode(INTERCEPTOR, name); |
| 2422 } | 2637 } |
| 2423 | 2638 |
| 2424 | 2639 |
| 2425 MaybeObject* CallStubCompiler::CompileCallGlobal( | 2640 MaybeObject* CallStubCompiler::CompileCallGlobal( |
| 2426 JSObject* object, | 2641 JSObject* object, |
| 2427 GlobalObject* holder, | 2642 GlobalObject* holder, |
| 2428 JSGlobalPropertyCell* cell, | 2643 JSGlobalPropertyCell* cell, |
| 2429 JSFunction* function, | 2644 JSFunction* function, |
| 2430 String* name) { | 2645 String* name) { |
| 2431 // ----------- S t a t e ------------- | 2646 // ----------- S t a t e ------------- |
| 2432 // -- ecx : name | 2647 // -- ecx : name |
| 2433 // -- esp[0] : return address | 2648 // -- esp[0] : return address |
| 2434 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2649 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 2435 // -- ... | 2650 // -- ... |
| 2436 // -- esp[(argc + 1) * 4] : receiver | 2651 // -- esp[(argc + 1) * 4] : receiver |
| 2437 // ----------------------------------- | 2652 // ----------------------------------- |
| 2438 | 2653 |
| 2439 if (HasCustomCallGenerator(function)) { | 2654 if (HasCustomCallGenerator(function)) { |
| 2440 MaybeObject* maybe_result = CompileCustomCall( | 2655 MaybeObject* maybe_result = CompileCustomCall( |
| 2441 object, holder, cell, function, name); | 2656 object, holder, cell, function, name); |
| 2442 Object* result; | 2657 Object* result; |
| 2443 if (!maybe_result->ToObject(&result)) return maybe_result; | 2658 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2444 // undefined means bail out to regular compiler. | 2659 // undefined means bail out to regular compiler. |
| 2445 if (!result->IsUndefined()) return result; | 2660 if (!result->IsUndefined()) return result; |
| 2446 } | 2661 } |
| 2447 | 2662 |
| 2448 Label miss; | 2663 Label miss; |
| 2449 | 2664 |
| 2450 GenerateNameCheck(name, &miss); | 2665 GenerateNameCheck(Handle<String>(name), &miss); |
| 2451 | 2666 |
| 2452 // Get the number of arguments. | 2667 // Get the number of arguments. |
| 2453 const int argc = arguments().immediate(); | 2668 const int argc = arguments().immediate(); |
| 2454 | 2669 |
| 2455 GenerateGlobalReceiverCheck(object, holder, name, &miss); | 2670 GenerateGlobalReceiverCheck(object, holder, name, &miss); |
| 2456 | 2671 |
| 2457 GenerateLoadFunctionFromCell(cell, function, &miss); | 2672 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2458 | 2673 |
| 2459 // Patch the receiver on the stack with the global proxy. | 2674 // Patch the receiver on the stack with the global proxy. |
| 2460 if (object->IsGlobalObject()) { | 2675 if (object->IsGlobalObject()) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2475 // We call indirectly through the code field in the function to | 2690 // We call indirectly through the code field in the function to |
| 2476 // allow recompilation to take effect without changing any of the | 2691 // allow recompilation to take effect without changing any of the |
| 2477 // call sites. | 2692 // call sites. |
| 2478 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), | 2693 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), |
| 2479 expected, arguments(), JUMP_FUNCTION, | 2694 expected, arguments(), JUMP_FUNCTION, |
| 2480 NullCallWrapper(), call_kind); | 2695 NullCallWrapper(), call_kind); |
| 2481 | 2696 |
| 2482 // Handle call cache miss. | 2697 // Handle call cache miss. |
| 2483 __ bind(&miss); | 2698 __ bind(&miss); |
| 2484 __ IncrementCounter(counters->call_global_inline_miss(), 1); | 2699 __ IncrementCounter(counters->call_global_inline_miss(), 1); |
| 2485 MaybeObject* maybe_result = GenerateMissBranch(); | 2700 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2486 if (maybe_result->IsFailure()) return maybe_result; | 2701 if (maybe_result->IsFailure()) return maybe_result; |
| 2487 | 2702 |
| 2488 // Return the generated code. | 2703 // Return the generated code. |
| 2489 return GetCode(NORMAL, name); | 2704 return TryGetCode(NORMAL, name); |
| 2490 } | 2705 } |
| 2491 | 2706 |
| 2492 | 2707 |
| 2493 MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, | 2708 MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, |
| 2494 int index, | 2709 int index, |
| 2495 Map* transition, | 2710 Map* transition, |
| 2496 String* name) { | 2711 String* name) { |
| 2497 // ----------- S t a t e ------------- | 2712 // ----------- S t a t e ------------- |
| 2498 // -- eax : value | 2713 // -- eax : value |
| 2499 // -- ecx : name | 2714 // -- ecx : name |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2797 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); | 3012 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); |
| 2798 | 3013 |
| 2799 // Check the maps of the full prototype chain. Also check that | 3014 // Check the maps of the full prototype chain. Also check that |
| 2800 // global property cells up to (but not including) the last object | 3015 // global property cells up to (but not including) the last object |
| 2801 // in the prototype chain are empty. | 3016 // in the prototype chain are empty. |
| 2802 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); | 3017 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); |
| 2803 | 3018 |
| 2804 // If the last object in the prototype chain is a global object, | 3019 // If the last object in the prototype chain is a global object, |
| 2805 // check that the global property cell is empty. | 3020 // check that the global property cell is empty. |
| 2806 if (last->IsGlobalObject()) { | 3021 if (last->IsGlobalObject()) { |
| 2807 MaybeObject* cell = GenerateCheckPropertyCell(masm(), | 3022 MaybeObject* cell = TryGenerateCheckPropertyCell(masm(), |
| 2808 GlobalObject::cast(last), | 3023 GlobalObject::cast(last), |
| 2809 name, | 3024 name, |
| 2810 edx, | 3025 edx, |
| 2811 &miss); | 3026 &miss); |
| 2812 if (cell->IsFailure()) { | 3027 if (cell->IsFailure()) { |
| 2813 miss.Unuse(); | 3028 miss.Unuse(); |
| 2814 return cell; | 3029 return cell; |
| 2815 } | 3030 } |
| 2816 } | 3031 } |
| 2817 | 3032 |
| 2818 // Return undefined if maps of the full prototype chain are still the | 3033 // Return undefined if maps of the full prototype chain are still the |
| 2819 // same and no global property with this name contains a value. | 3034 // same and no global property with this name contains a value. |
| 2820 __ mov(eax, isolate()->factory()->undefined_value()); | 3035 __ mov(eax, isolate()->factory()->undefined_value()); |
| 2821 __ ret(0); | 3036 __ ret(0); |
| (...skipping 1194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4016 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 4231 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 4017 __ jmp(ic_miss, RelocInfo::CODE_TARGET); | 4232 __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
| 4018 } | 4233 } |
| 4019 | 4234 |
| 4020 | 4235 |
| 4021 #undef __ | 4236 #undef __ |
| 4022 | 4237 |
| 4023 } } // namespace v8::internal | 4238 } } // namespace v8::internal |
| 4024 | 4239 |
| 4025 #endif // V8_TARGET_ARCH_IA32 | 4240 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |