| 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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 // Miss: fall through. | 92 // Miss: fall through. |
| 93 __ bind(&miss); | 93 __ bind(&miss); |
| 94 } | 94 } |
| 95 | 95 |
| 96 | 96 |
| 97 // Helper function used to check that the dictionary doesn't contain | 97 // Helper function used to check that the dictionary doesn't contain |
| 98 // the property. This function may return false negatives, so miss_label | 98 // the property. This function may return false negatives, so miss_label |
| 99 // must always call a backup property check that is complete. | 99 // must always call a backup property check that is complete. |
| 100 // This function is safe to call if the receiver has fast properties. | 100 // This function is safe to call if the receiver has fast properties. |
| 101 // Name must be a symbol and receiver must be a heap object. | 101 // Name must be a symbol and receiver must be a heap object. |
| 102 MUST_USE_RESULT static MaybeObject* GenerateDictionaryNegativeLookup( | 102 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, |
| 103 Label* miss_label, |
| 104 Register receiver, |
| 105 Handle<String> name, |
| 106 Register scratch0, |
| 107 Register scratch1) { |
| 108 ASSERT(name->IsSymbol()); |
| 109 Counters* counters = masm->isolate()->counters(); |
| 110 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); |
| 111 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
| 112 |
| 113 Label done; |
| 114 |
| 115 const int kInterceptorOrAccessCheckNeededMask = |
| 116 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
| 117 |
| 118 // Bail out if the receiver has a named interceptor or requires access checks. |
| 119 Register map = scratch1; |
| 120 __ lw(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 121 __ lbu(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); |
| 122 __ And(scratch0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); |
| 123 __ Branch(miss_label, ne, scratch0, Operand(zero_reg)); |
| 124 |
| 125 // Check that receiver is a JSObject. |
| 126 __ lbu(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
| 127 __ Branch(miss_label, lt, scratch0, Operand(FIRST_SPEC_OBJECT_TYPE)); |
| 128 |
| 129 // Load properties array. |
| 130 Register properties = scratch0; |
| 131 __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 132 // Check that the properties array is a dictionary. |
| 133 __ lw(map, FieldMemOperand(properties, HeapObject::kMapOffset)); |
| 134 Register tmp = properties; |
| 135 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); |
| 136 __ Branch(miss_label, ne, map, Operand(tmp)); |
| 137 |
| 138 // Restore the temporarily used register. |
| 139 __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 140 |
| 141 |
| 142 StringDictionaryLookupStub::GenerateNegativeLookup(masm, |
| 143 miss_label, |
| 144 &done, |
| 145 receiver, |
| 146 properties, |
| 147 name, |
| 148 scratch1); |
| 149 __ bind(&done); |
| 150 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
| 151 } |
| 152 |
| 153 |
| 154 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 155 // handlified. |
| 156 MUST_USE_RESULT static MaybeObject* TryGenerateDictionaryNegativeLookup( |
| 103 MacroAssembler* masm, | 157 MacroAssembler* masm, |
| 104 Label* miss_label, | 158 Label* miss_label, |
| 105 Register receiver, | 159 Register receiver, |
| 106 String* name, | 160 String* name, |
| 107 Register scratch0, | 161 Register scratch0, |
| 108 Register scratch1) { | 162 Register scratch1) { |
| 109 ASSERT(name->IsSymbol()); | 163 ASSERT(name->IsSymbol()); |
| 110 Counters* counters = masm->isolate()->counters(); | 164 Counters* counters = masm->isolate()->counters(); |
| 111 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); | 165 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); |
| 112 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | 166 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 133 __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 187 __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 134 // Check that the properties array is a dictionary. | 188 // Check that the properties array is a dictionary. |
| 135 __ lw(map, FieldMemOperand(properties, HeapObject::kMapOffset)); | 189 __ lw(map, FieldMemOperand(properties, HeapObject::kMapOffset)); |
| 136 Register tmp = properties; | 190 Register tmp = properties; |
| 137 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); | 191 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); |
| 138 __ Branch(miss_label, ne, map, Operand(tmp)); | 192 __ Branch(miss_label, ne, map, Operand(tmp)); |
| 139 | 193 |
| 140 // Restore the temporarily used register. | 194 // Restore the temporarily used register. |
| 141 __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 195 __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 142 | 196 |
| 143 MaybeObject* result = StringDictionaryLookupStub::GenerateNegativeLookup( | 197 MaybeObject* result = StringDictionaryLookupStub::TryGenerateNegativeLookup( |
| 144 masm, | 198 masm, |
| 145 miss_label, | 199 miss_label, |
| 146 &done, | 200 &done, |
| 147 receiver, | 201 receiver, |
| 148 properties, | 202 properties, |
| 149 name, | 203 name, |
| 150 scratch1); | 204 scratch1); |
| 151 if (result->IsFailure()) return result; | 205 if (result->IsFailure()) return result; |
| 152 | 206 |
| 153 __ bind(&done); | 207 __ bind(&done); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 __ li(prototype, Handle<Map>(function->initial_map())); | 308 __ li(prototype, Handle<Map>(function->initial_map())); |
| 255 // Load the prototype from the initial map. | 309 // Load the prototype from the initial map. |
| 256 __ lw(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); | 310 __ lw(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); |
| 257 } | 311 } |
| 258 | 312 |
| 259 | 313 |
| 260 // Load a fast property out of a holder object (src). In-object properties | 314 // Load a fast property out of a holder object (src). In-object properties |
| 261 // are loaded directly otherwise the property is loaded from the properties | 315 // are loaded directly otherwise the property is loaded from the properties |
| 262 // fixed array. | 316 // fixed array. |
| 263 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | 317 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, |
| 264 Register dst, Register src, | 318 Register dst, |
| 265 JSObject* holder, int index) { | 319 Register src, |
| 320 Handle<JSObject> holder, |
| 321 int index) { |
| 266 // Adjust for the number of properties stored in the holder. | 322 // Adjust for the number of properties stored in the holder. |
| 267 index -= holder->map()->inobject_properties(); | 323 index -= holder->map()->inobject_properties(); |
| 268 if (index < 0) { | 324 if (index < 0) { |
| 269 // Get the property straight out of the holder. | 325 // Get the property straight out of the holder. |
| 270 int offset = holder->map()->instance_size() + (index * kPointerSize); | 326 int offset = holder->map()->instance_size() + (index * kPointerSize); |
| 271 __ lw(dst, FieldMemOperand(src, offset)); | 327 __ lw(dst, FieldMemOperand(src, offset)); |
| 272 } else { | 328 } else { |
| 273 // Calculate the offset into the properties array. | 329 // Calculate the offset into the properties array. |
| 274 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 330 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
| 275 __ lw(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); | 331 __ lw(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 462 | 518 |
| 463 // Return the value (register v0). | 519 // Return the value (register v0). |
| 464 __ bind(&exit); | 520 __ bind(&exit); |
| 465 __ mov(v0, a0); | 521 __ mov(v0, a0); |
| 466 __ Ret(); | 522 __ Ret(); |
| 467 } | 523 } |
| 468 | 524 |
| 469 | 525 |
| 470 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { | 526 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { |
| 471 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); | 527 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); |
| 472 Code* code = NULL; | 528 Handle<Code> code = (kind == Code::LOAD_IC) |
| 473 if (kind == Code::LOAD_IC) { | 529 ? masm->isolate()->builtins()->LoadIC_Miss() |
| 474 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss); | 530 : masm->isolate()->builtins()->KeyedLoadIC_Miss(); |
| 475 } else { | 531 __ Jump(code, RelocInfo::CODE_TARGET); |
| 476 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss); | |
| 477 } | |
| 478 | |
| 479 Handle<Code> ic(code); | |
| 480 __ Jump(ic, RelocInfo::CODE_TARGET); | |
| 481 } | 532 } |
| 482 | 533 |
| 483 | 534 |
| 484 static void GenerateCallFunction(MacroAssembler* masm, | 535 static void GenerateCallFunction(MacroAssembler* masm, |
| 485 Object* object, | 536 Handle<Object> object, |
| 486 const ParameterCount& arguments, | 537 const ParameterCount& arguments, |
| 487 Label* miss, | 538 Label* miss, |
| 488 Code::ExtraICState extra_ic_state) { | 539 Code::ExtraICState extra_ic_state) { |
| 489 // ----------- S t a t e ------------- | 540 // ----------- S t a t e ------------- |
| 490 // -- a0: receiver | 541 // -- a0: receiver |
| 491 // -- a1: function to call | 542 // -- a1: function to call |
| 492 // ----------------------------------- | 543 // ----------------------------------- |
| 493 // Check that the function really is a function. | 544 // Check that the function really is a function. |
| 494 __ JumpIfSmi(a1, miss); | 545 __ JumpIfSmi(a1, miss); |
| 495 __ GetObjectType(a1, a3, a3); | 546 __ GetObjectType(a1, a3, a3); |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 871 const ParameterCount& arguments_; | 922 const ParameterCount& arguments_; |
| 872 Register name_; | 923 Register name_; |
| 873 Code::ExtraICState extra_ic_state_; | 924 Code::ExtraICState extra_ic_state_; |
| 874 }; | 925 }; |
| 875 | 926 |
| 876 | 927 |
| 877 | 928 |
| 878 // Generate code to check that a global property cell is empty. Create | 929 // Generate code to check that a global property cell is empty. Create |
| 879 // the property cell at compilation time if no cell exists for the | 930 // the property cell at compilation time if no cell exists for the |
| 880 // property. | 931 // property. |
| 881 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell( | 932 static void GenerateCheckPropertyCell(MacroAssembler* masm, |
| 933 Handle<GlobalObject> global, |
| 934 Handle<String> name, |
| 935 Register scratch, |
| 936 Label* miss) { |
| 937 Handle<JSGlobalPropertyCell> cell = |
| 938 GlobalObject::EnsurePropertyCell(global, name); |
| 939 ASSERT(cell->value()->IsTheHole()); |
| 940 __ li(scratch, Operand(cell)); |
| 941 __ lw(scratch, |
| 942 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); |
| 943 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 944 __ Branch(miss, ne, scratch, Operand(at)); |
| 945 } |
| 946 |
| 947 |
| 948 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 949 // handlified. |
| 950 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell( |
| 882 MacroAssembler* masm, | 951 MacroAssembler* masm, |
| 883 GlobalObject* global, | 952 GlobalObject* global, |
| 884 String* name, | 953 String* name, |
| 885 Register scratch, | 954 Register scratch, |
| 886 Label* miss) { | 955 Label* miss) { |
| 887 Object* probe; | 956 Object* probe; |
| 888 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); | 957 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); |
| 889 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 958 if (!maybe_probe->ToObject(&probe)) return maybe_probe; |
| 890 } | 959 } |
| 891 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); | 960 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); |
| 892 ASSERT(cell->value()->IsTheHole()); | 961 ASSERT(cell->value()->IsTheHole()); |
| 893 __ li(scratch, Operand(Handle<Object>(cell))); | 962 __ li(scratch, Operand(Handle<Object>(cell))); |
| 894 __ lw(scratch, | 963 __ lw(scratch, |
| 895 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); | 964 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); |
| 896 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 965 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 897 __ Branch(miss, ne, scratch, Operand(at)); | 966 __ Branch(miss, ne, scratch, Operand(at)); |
| 898 return cell; | 967 return cell; |
| 899 } | 968 } |
| 900 | 969 |
| 901 | 970 |
| 902 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | 971 // Calls GenerateCheckPropertyCell for each global object in the prototype chain |
| 903 // from object to (but not including) holder. | 972 // from object to (but not including) holder. |
| 904 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells( | 973 static void GenerateCheckPropertyCells(MacroAssembler* masm, |
| 974 Handle<JSObject> object, |
| 975 Handle<JSObject> holder, |
| 976 Handle<String> name, |
| 977 Register scratch, |
| 978 Label* miss) { |
| 979 Handle<JSObject> current = object; |
| 980 while (!current.is_identical_to(holder)) { |
| 981 if (current->IsGlobalObject()) { |
| 982 GenerateCheckPropertyCell(masm, |
| 983 Handle<GlobalObject>::cast(current), |
| 984 name, |
| 985 scratch, |
| 986 miss); |
| 987 } |
| 988 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); |
| 989 } |
| 990 } |
| 991 |
| 992 |
| 993 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 994 // handlified. |
| 995 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCells( |
| 905 MacroAssembler* masm, | 996 MacroAssembler* masm, |
| 906 JSObject* object, | 997 JSObject* object, |
| 907 JSObject* holder, | 998 JSObject* holder, |
| 908 String* name, | 999 String* name, |
| 909 Register scratch, | 1000 Register scratch, |
| 910 Label* miss) { | 1001 Label* miss) { |
| 911 JSObject* current = object; | 1002 JSObject* current = object; |
| 912 while (current != holder) { | 1003 while (current != holder) { |
| 913 if (current->IsGlobalObject()) { | 1004 if (current->IsGlobalObject()) { |
| 914 // Returns a cell or a failure. | 1005 // Returns a cell or a failure. |
| 915 MaybeObject* result = GenerateCheckPropertyCell( | 1006 MaybeObject* result = TryGenerateCheckPropertyCell( |
| 916 masm, | 1007 masm, |
| 917 GlobalObject::cast(current), | 1008 GlobalObject::cast(current), |
| 918 name, | 1009 name, |
| 919 scratch, | 1010 scratch, |
| 920 miss); | 1011 miss); |
| 921 if (result->IsFailure()) return result; | 1012 if (result->IsFailure()) return result; |
| 922 } | 1013 } |
| 923 ASSERT(current->IsJSObject()); | 1014 ASSERT(current->IsJSObject()); |
| 924 current = JSObject::cast(current->GetPrototype()); | 1015 current = JSObject::cast(current->GetPrototype()); |
| 925 } | 1016 } |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1040 __ nor(scratch, scratch, scratch); | 1131 __ nor(scratch, scratch, scratch); |
| 1041 __ and_(hiword, hiword, scratch); | 1132 __ and_(hiword, hiword, scratch); |
| 1042 } | 1133 } |
| 1043 } | 1134 } |
| 1044 | 1135 |
| 1045 | 1136 |
| 1046 #undef __ | 1137 #undef __ |
| 1047 #define __ ACCESS_MASM(masm()) | 1138 #define __ ACCESS_MASM(masm()) |
| 1048 | 1139 |
| 1049 | 1140 |
| 1141 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
| 1142 Register object_reg, |
| 1143 Handle<JSObject> holder, |
| 1144 Register holder_reg, |
| 1145 Register scratch1, |
| 1146 Register scratch2, |
| 1147 Handle<String> name, |
| 1148 int save_at_depth, |
| 1149 Label* miss) { |
| 1150 // Make sure there's no overlap between holder and object registers. |
| 1151 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 1152 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 1153 && !scratch2.is(scratch1)); |
| 1154 |
| 1155 // Keep track of the current object in register reg. |
| 1156 Register reg = object_reg; |
| 1157 int depth = 0; |
| 1158 |
| 1159 if (save_at_depth == depth) { |
| 1160 __ sw(reg, MemOperand(sp)); |
| 1161 } |
| 1162 |
| 1163 // Check the maps in the prototype chain. |
| 1164 // Traverse the prototype chain from the object and do map checks. |
| 1165 Handle<JSObject> current = object; |
| 1166 while (!current.is_identical_to(holder)) { |
| 1167 ++depth; |
| 1168 |
| 1169 // Only global objects and objects that do not require access |
| 1170 // checks are allowed in stubs. |
| 1171 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); |
| 1172 |
| 1173 Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); |
| 1174 if (!current->HasFastProperties() && |
| 1175 !current->IsJSGlobalObject() && |
| 1176 !current->IsJSGlobalProxy()) { |
| 1177 if (!name->IsSymbol()) { |
| 1178 name = factory()->LookupSymbol(name); |
| 1179 } |
| 1180 ASSERT(current->property_dictionary()->FindEntry(*name) == |
| 1181 StringDictionary::kNotFound); |
| 1182 |
| 1183 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
| 1184 scratch1, scratch2); |
| 1185 |
| 1186 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1187 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1188 __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
| 1189 } else { |
| 1190 Handle<Map> current_map(current->map()); |
| 1191 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1192 // Branch on the result of the map check. |
| 1193 __ Branch(miss, ne, scratch1, Operand(current_map)); |
| 1194 // Check access rights to the global object. This has to happen after |
| 1195 // the map check so that we know that the object is actually a global |
| 1196 // object. |
| 1197 if (current->IsJSGlobalProxy()) { |
| 1198 __ CheckAccessGlobalProxy(reg, scratch2, miss); |
| 1199 } |
| 1200 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1201 |
| 1202 if (heap()->InNewSpace(*prototype)) { |
| 1203 // The prototype is in new space; we cannot store a reference to it |
| 1204 // in the code. Load it from the map. |
| 1205 __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
| 1206 } else { |
| 1207 // The prototype is in old space; load it directly. |
| 1208 __ li(reg, Operand(prototype)); |
| 1209 } |
| 1210 } |
| 1211 |
| 1212 if (save_at_depth == depth) { |
| 1213 __ sw(reg, MemOperand(sp)); |
| 1214 } |
| 1215 |
| 1216 // Go to the next object in the prototype chain. |
| 1217 current = prototype; |
| 1218 } |
| 1219 |
| 1220 // Log the check depth. |
| 1221 LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 1222 |
| 1223 // Check the holder map. |
| 1224 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1225 __ Branch(miss, ne, scratch1, Operand(Handle<Map>(current->map()))); |
| 1226 |
| 1227 // Perform security check for access to the global object. |
| 1228 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 1229 if (holder->IsJSGlobalProxy()) { |
| 1230 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 1231 } |
| 1232 |
| 1233 // If we've skipped any global objects, it's not enough to verify that |
| 1234 // their maps haven't changed. We also need to check that the property |
| 1235 // cell for the property is still empty. |
| 1236 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
| 1237 |
| 1238 // Return the register containing the holder. |
| 1239 return reg; |
| 1240 } |
| 1241 |
| 1242 |
| 1050 Register StubCompiler::CheckPrototypes(JSObject* object, | 1243 Register StubCompiler::CheckPrototypes(JSObject* object, |
| 1051 Register object_reg, | 1244 Register object_reg, |
| 1052 JSObject* holder, | 1245 JSObject* holder, |
| 1053 Register holder_reg, | 1246 Register holder_reg, |
| 1054 Register scratch1, | 1247 Register scratch1, |
| 1055 Register scratch2, | 1248 Register scratch2, |
| 1056 String* name, | 1249 String* name, |
| 1057 int save_at_depth, | 1250 int save_at_depth, |
| 1058 Label* miss) { | 1251 Label* miss) { |
| 1059 // Make sure there's no overlap between holder and object registers. | 1252 // Make sure there's no overlap between holder and object registers. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1089 Object* lookup_result = NULL; // Initialization to please compiler. | 1282 Object* lookup_result = NULL; // Initialization to please compiler. |
| 1090 if (!maybe_lookup_result->ToObject(&lookup_result)) { | 1283 if (!maybe_lookup_result->ToObject(&lookup_result)) { |
| 1091 set_failure(Failure::cast(maybe_lookup_result)); | 1284 set_failure(Failure::cast(maybe_lookup_result)); |
| 1092 return reg; | 1285 return reg; |
| 1093 } | 1286 } |
| 1094 name = String::cast(lookup_result); | 1287 name = String::cast(lookup_result); |
| 1095 } | 1288 } |
| 1096 ASSERT(current->property_dictionary()->FindEntry(name) == | 1289 ASSERT(current->property_dictionary()->FindEntry(name) == |
| 1097 StringDictionary::kNotFound); | 1290 StringDictionary::kNotFound); |
| 1098 | 1291 |
| 1099 MaybeObject* negative_lookup = GenerateDictionaryNegativeLookup(masm(), | 1292 MaybeObject* negative_lookup = |
| 1100 miss, | 1293 TryGenerateDictionaryNegativeLookup(masm(), |
| 1101 reg, | 1294 miss, |
| 1102 name, | 1295 reg, |
| 1103 scratch1, | 1296 name, |
| 1104 scratch2); | 1297 scratch1, |
| 1298 scratch2); |
| 1299 |
| 1105 if (negative_lookup->IsFailure()) { | 1300 if (negative_lookup->IsFailure()) { |
| 1106 set_failure(Failure::cast(negative_lookup)); | 1301 set_failure(Failure::cast(negative_lookup)); |
| 1107 return reg; | 1302 return reg; |
| 1108 } | 1303 } |
| 1109 | 1304 |
| 1110 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1305 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1111 reg = holder_reg; // From now the object is in holder_reg. | 1306 reg = holder_reg; // From now the object is in holder_reg. |
| 1112 __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | 1307 __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
| 1113 } else if (heap()->InNewSpace(prototype)) { | 1308 } else if (heap()->InNewSpace(prototype)) { |
| 1114 // Get the map of the current object. | 1309 // Get the map of the current object. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1159 // Check the holder map. | 1354 // Check the holder map. |
| 1160 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1355 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1161 __ Branch(miss, ne, scratch1, Operand(Handle<Map>(current->map()))); | 1356 __ Branch(miss, ne, scratch1, Operand(Handle<Map>(current->map()))); |
| 1162 | 1357 |
| 1163 // Log the check depth. | 1358 // Log the check depth. |
| 1164 LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1)); | 1359 LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 1165 // Perform security check for access to the global object. | 1360 // Perform security check for access to the global object. |
| 1166 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1361 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 1167 if (holder->IsJSGlobalProxy()) { | 1362 if (holder->IsJSGlobalProxy()) { |
| 1168 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1363 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 1169 }; | 1364 } |
| 1170 | 1365 |
| 1171 // If we've skipped any global objects, it's not enough to verify | 1366 // If we've skipped any global objects, it's not enough to verify |
| 1172 // that their maps haven't changed. We also need to check that the | 1367 // that their maps haven't changed. We also need to check that the |
| 1173 // property cell for the property is still empty. | 1368 // property cell for the property is still empty. |
| 1174 | 1369 |
| 1175 MaybeObject* result = GenerateCheckPropertyCells(masm(), | 1370 MaybeObject* result = TryGenerateCheckPropertyCells(masm(), |
| 1176 object, | 1371 object, |
| 1177 holder, | 1372 holder, |
| 1178 name, | 1373 name, |
| 1179 scratch1, | 1374 scratch1, |
| 1180 miss); | 1375 miss); |
| 1181 if (result->IsFailure()) set_failure(Failure::cast(result)); | 1376 if (result->IsFailure()) set_failure(Failure::cast(result)); |
| 1182 | 1377 |
| 1183 // Return the register containing the holder. | 1378 // Return the register containing the holder. |
| 1184 return reg; | 1379 return reg; |
| 1185 } | 1380 } |
| 1186 | 1381 |
| 1187 | 1382 |
| 1188 void StubCompiler::GenerateLoadField(JSObject* object, | 1383 void StubCompiler::GenerateLoadField(Handle<JSObject> object, |
| 1189 JSObject* holder, | 1384 Handle<JSObject> holder, |
| 1190 Register receiver, | 1385 Register receiver, |
| 1191 Register scratch1, | 1386 Register scratch1, |
| 1192 Register scratch2, | 1387 Register scratch2, |
| 1193 Register scratch3, | 1388 Register scratch3, |
| 1194 int index, | 1389 int index, |
| 1195 String* name, | 1390 Handle<String> name, |
| 1196 Label* miss) { | 1391 Label* miss) { |
| 1197 // Check that the receiver isn't a smi. | 1392 // Check that the receiver isn't a smi. |
| 1198 __ And(scratch1, receiver, Operand(kSmiTagMask)); | 1393 __ And(scratch1, receiver, Operand(kSmiTagMask)); |
| 1199 __ Branch(miss, eq, scratch1, Operand(zero_reg)); | 1394 __ Branch(miss, eq, scratch1, Operand(zero_reg)); |
| 1200 | 1395 |
| 1201 // Check that the maps haven't changed. | 1396 // Check that the maps haven't changed. |
| 1202 Register reg = | 1397 Register reg = CheckPrototypes( |
| 1203 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, | 1398 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); |
| 1204 name, miss); | |
| 1205 GenerateFastPropertyLoad(masm(), v0, reg, holder, index); | 1399 GenerateFastPropertyLoad(masm(), v0, reg, holder, index); |
| 1206 __ Ret(); | 1400 __ Ret(); |
| 1207 } | 1401 } |
| 1208 | 1402 |
| 1209 | 1403 |
| 1210 void StubCompiler::GenerateLoadConstant(JSObject* object, | 1404 void StubCompiler::GenerateLoadConstant(Handle<JSObject> object, |
| 1211 JSObject* holder, | 1405 Handle<JSObject> holder, |
| 1212 Register receiver, | 1406 Register receiver, |
| 1213 Register scratch1, | 1407 Register scratch1, |
| 1214 Register scratch2, | 1408 Register scratch2, |
| 1215 Register scratch3, | 1409 Register scratch3, |
| 1216 Object* value, | 1410 Handle<Object> value, |
| 1217 String* name, | 1411 Handle<String> name, |
| 1218 Label* miss) { | 1412 Label* miss) { |
| 1219 // Check that the receiver isn't a smi. | 1413 // Check that the receiver isn't a smi. |
| 1220 __ JumpIfSmi(receiver, miss, scratch1); | 1414 __ JumpIfSmi(receiver, miss, scratch1); |
| 1221 | 1415 |
| 1222 // Check that the maps haven't changed. | 1416 // Check that the maps haven't changed. |
| 1223 Register reg = | 1417 Register reg = |
| 1224 CheckPrototypes(object, receiver, holder, | 1418 CheckPrototypes(object, receiver, holder, |
| 1225 scratch1, scratch2, scratch3, name, miss); | 1419 scratch1, scratch2, scratch3, name, miss); |
| 1226 | 1420 |
| 1227 // Return the constant value. | 1421 // Return the constant value. |
| 1228 __ li(v0, Operand(Handle<Object>(value))); | 1422 __ li(v0, Operand(value)); |
| 1229 __ Ret(); | 1423 __ Ret(); |
| 1230 } | 1424 } |
| 1231 | 1425 |
| 1232 | 1426 |
| 1233 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, | 1427 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, |
| 1234 JSObject* holder, | 1428 JSObject* holder, |
| 1235 Register receiver, | 1429 Register receiver, |
| 1236 Register name_reg, | 1430 Register name_reg, |
| 1237 Register scratch1, | 1431 Register scratch1, |
| 1238 Register scratch2, | 1432 Register scratch2, |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1383 scratch2, | 1577 scratch2, |
| 1384 scratch3, | 1578 scratch3, |
| 1385 name, | 1579 name, |
| 1386 miss); | 1580 miss); |
| 1387 } | 1581 } |
| 1388 | 1582 |
| 1389 if (lookup->type() == FIELD) { | 1583 if (lookup->type() == FIELD) { |
| 1390 // We found FIELD property in prototype chain of interceptor's holder. | 1584 // We found FIELD property in prototype chain of interceptor's holder. |
| 1391 // Retrieve a field from field's holder. | 1585 // Retrieve a field from field's holder. |
| 1392 GenerateFastPropertyLoad(masm(), v0, holder_reg, | 1586 GenerateFastPropertyLoad(masm(), v0, holder_reg, |
| 1393 lookup->holder(), lookup->GetFieldIndex()); | 1587 Handle<JSObject>(lookup->holder()), |
| 1588 lookup->GetFieldIndex()); |
| 1394 __ Ret(); | 1589 __ Ret(); |
| 1395 } else { | 1590 } else { |
| 1396 // We found CALLBACKS property in prototype chain of interceptor's | 1591 // We found CALLBACKS property in prototype chain of interceptor's |
| 1397 // holder. | 1592 // holder. |
| 1398 ASSERT(lookup->type() == CALLBACKS); | 1593 ASSERT(lookup->type() == CALLBACKS); |
| 1399 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); | 1594 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); |
| 1400 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 1595 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); |
| 1401 ASSERT(callback != NULL); | 1596 ASSERT(callback != NULL); |
| 1402 ASSERT(callback->getter() != NULL); | 1597 ASSERT(callback->getter() != NULL); |
| 1403 | 1598 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1433 PushInterceptorArguments(masm(), receiver, holder_reg, | 1628 PushInterceptorArguments(masm(), receiver, holder_reg, |
| 1434 name_reg, interceptor_holder); | 1629 name_reg, interceptor_holder); |
| 1435 | 1630 |
| 1436 ExternalReference ref = ExternalReference( | 1631 ExternalReference ref = ExternalReference( |
| 1437 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), masm()->isolate()); | 1632 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), masm()->isolate()); |
| 1438 __ TailCallExternalReference(ref, 5, 1); | 1633 __ TailCallExternalReference(ref, 5, 1); |
| 1439 } | 1634 } |
| 1440 } | 1635 } |
| 1441 | 1636 |
| 1442 | 1637 |
| 1443 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { | 1638 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { |
| 1444 if (kind_ == Code::KEYED_CALL_IC) { | 1639 if (kind_ == Code::KEYED_CALL_IC) { |
| 1445 __ Branch(miss, ne, a2, Operand(Handle<String>(name))); | 1640 __ Branch(miss, ne, a2, Operand(name)); |
| 1446 } | 1641 } |
| 1447 } | 1642 } |
| 1448 | 1643 |
| 1449 | 1644 |
| 1450 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, | 1645 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, |
| 1451 JSObject* holder, | 1646 JSObject* holder, |
| 1452 String* name, | 1647 String* name, |
| 1453 Label* miss) { | 1648 Label* miss) { |
| 1454 ASSERT(holder->IsGlobalObject()); | 1649 ASSERT(holder->IsGlobalObject()); |
| 1455 | 1650 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1492 // Check the shared function info. Make sure it hasn't changed. | 1687 // Check the shared function info. Make sure it hasn't changed. |
| 1493 __ li(a3, Handle<SharedFunctionInfo>(function->shared())); | 1688 __ li(a3, Handle<SharedFunctionInfo>(function->shared())); |
| 1494 __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | 1689 __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
| 1495 __ Branch(miss, ne, t0, Operand(a3)); | 1690 __ Branch(miss, ne, t0, Operand(a3)); |
| 1496 } else { | 1691 } else { |
| 1497 __ Branch(miss, ne, a1, Operand(Handle<JSFunction>(function))); | 1692 __ Branch(miss, ne, a1, Operand(Handle<JSFunction>(function))); |
| 1498 } | 1693 } |
| 1499 } | 1694 } |
| 1500 | 1695 |
| 1501 | 1696 |
| 1502 MaybeObject* CallStubCompiler::GenerateMissBranch() { | 1697 void CallStubCompiler::GenerateMissBranch() { |
| 1503 MaybeObject* maybe_obj = | 1698 Handle<Code> code = |
| 1504 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1699 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
| 1505 kind_, | 1700 kind_, |
| 1506 extra_ic_state_); | 1701 extra_state_); |
| 1702 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1703 } |
| 1704 |
| 1705 |
| 1706 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 1707 // handlified. |
| 1708 MaybeObject* CallStubCompiler::TryGenerateMissBranch() { |
| 1709 MaybeObject* maybe_obj = |
| 1710 isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(), |
| 1711 kind_, |
| 1712 extra_state_); |
| 1507 Object* obj; | 1713 Object* obj; |
| 1508 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1714 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 1509 __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | 1715 __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); |
| 1510 return obj; | 1716 return obj; |
| 1511 } | 1717 } |
| 1512 | 1718 |
| 1513 | 1719 |
| 1514 MaybeObject* CallStubCompiler::CompileCallField(JSObject* object, | 1720 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| 1515 JSObject* holder, | 1721 Handle<JSObject> holder, |
| 1516 int index, | 1722 int index, |
| 1517 String* name) { | 1723 Handle<String> name) { |
| 1518 // ----------- S t a t e ------------- | 1724 // ----------- S t a t e ------------- |
| 1519 // -- a2 : name | 1725 // -- a2 : name |
| 1520 // -- ra : return address | 1726 // -- ra : return address |
| 1521 // ----------------------------------- | 1727 // ----------------------------------- |
| 1522 Label miss; | 1728 Label miss; |
| 1523 | 1729 |
| 1524 GenerateNameCheck(name, &miss); | 1730 GenerateNameCheck(name, &miss); |
| 1525 | 1731 |
| 1526 const int argc = arguments().immediate(); | 1732 const int argc = arguments().immediate(); |
| 1527 | 1733 |
| 1528 // Get the receiver of the function from the stack into a0. | 1734 // Get the receiver of the function from the stack into a0. |
| 1529 __ lw(a0, MemOperand(sp, argc * kPointerSize)); | 1735 __ lw(a0, MemOperand(sp, argc * kPointerSize)); |
| 1530 // Check that the receiver isn't a smi. | 1736 // Check that the receiver isn't a smi. |
| 1531 __ JumpIfSmi(a0, &miss, t0); | 1737 __ JumpIfSmi(a0, &miss, t0); |
| 1532 | 1738 |
| 1533 // Do the right check and compute the holder register. | 1739 // Do the right check and compute the holder register. |
| 1534 Register reg = CheckPrototypes(object, a0, holder, a1, a3, t0, name, &miss); | 1740 Register reg = CheckPrototypes(object, a0, holder, a1, a3, t0, name, &miss); |
| 1535 GenerateFastPropertyLoad(masm(), a1, reg, holder, index); | 1741 GenerateFastPropertyLoad(masm(), a1, reg, holder, index); |
| 1536 | 1742 |
| 1537 GenerateCallFunction(masm(), object, arguments(), &miss, extra_ic_state_); | 1743 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); |
| 1538 | 1744 |
| 1539 // Handle call cache miss. | 1745 // Handle call cache miss. |
| 1540 __ bind(&miss); | 1746 __ bind(&miss); |
| 1541 MaybeObject* maybe_result = GenerateMissBranch(); | 1747 GenerateMissBranch(); |
| 1542 if (maybe_result->IsFailure()) return maybe_result; | |
| 1543 | 1748 |
| 1544 // Return the generated code. | 1749 // Return the generated code. |
| 1545 return GetCode(FIELD, name); | 1750 return GetCode(FIELD, name); |
| 1546 } | 1751 } |
| 1547 | 1752 |
| 1548 | 1753 |
| 1549 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, | 1754 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, |
| 1550 JSObject* holder, | 1755 JSObject* holder, |
| 1551 JSGlobalPropertyCell* cell, | 1756 JSGlobalPropertyCell* cell, |
| 1552 JSFunction* function, | 1757 JSFunction* function, |
| 1553 String* name) { | 1758 String* name) { |
| 1554 // ----------- S t a t e ------------- | 1759 // ----------- S t a t e ------------- |
| 1555 // -- a2 : name | 1760 // -- a2 : name |
| 1556 // -- ra : return address | 1761 // -- ra : return address |
| 1557 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1762 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 1558 // -- ... | 1763 // -- ... |
| 1559 // -- sp[argc * 4] : receiver | 1764 // -- sp[argc * 4] : receiver |
| 1560 // ----------------------------------- | 1765 // ----------------------------------- |
| 1561 | 1766 |
| 1562 // If object is not an array, bail out to regular call. | 1767 // If object is not an array, bail out to regular call. |
| 1563 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); | 1768 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); |
| 1564 | 1769 |
| 1565 Label miss; | 1770 Label miss; |
| 1566 | 1771 |
| 1567 GenerateNameCheck(name, &miss); | 1772 GenerateNameCheck(Handle<String>(name), &miss); |
| 1568 | 1773 |
| 1569 Register receiver = a1; | 1774 Register receiver = a1; |
| 1570 | 1775 |
| 1571 // Get the receiver from the stack. | 1776 // Get the receiver from the stack. |
| 1572 const int argc = arguments().immediate(); | 1777 const int argc = arguments().immediate(); |
| 1573 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | 1778 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); |
| 1574 | 1779 |
| 1575 // Check that the receiver isn't a smi. | 1780 // Check that the receiver isn't a smi. |
| 1576 __ JumpIfSmi(receiver, &miss); | 1781 __ JumpIfSmi(receiver, &miss); |
| 1577 | 1782 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1633 __ Addu(end_elements, end_elements, kEndElementsOffset); | 1838 __ Addu(end_elements, end_elements, kEndElementsOffset); |
| 1634 __ sw(t0, MemOperand(end_elements)); | 1839 __ sw(t0, MemOperand(end_elements)); |
| 1635 | 1840 |
| 1636 // Check for a smi. | 1841 // Check for a smi. |
| 1637 __ Drop(argc + 1); | 1842 __ Drop(argc + 1); |
| 1638 __ Ret(); | 1843 __ Ret(); |
| 1639 | 1844 |
| 1640 __ bind(&with_write_barrier); | 1845 __ bind(&with_write_barrier); |
| 1641 | 1846 |
| 1642 __ lw(t2, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 1847 __ lw(t2, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 1643 __ CheckFastSmiOnlyElements(t2, t2, &call_builtin); | 1848 __ CheckFastObjectElements(t2, t2, &call_builtin); |
| 1644 | 1849 |
| 1645 // Save new length. | 1850 // Save new length. |
| 1646 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1851 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1647 | 1852 |
| 1648 // Push the element. | 1853 // Push the element. |
| 1649 // We may need a register containing the address end_elements below, | 1854 // We may need a register containing the address end_elements below, |
| 1650 // so write back the value in end_elements. | 1855 // so write back the value in end_elements. |
| 1651 __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); | 1856 __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); |
| 1652 __ Addu(end_elements, elements, end_elements); | 1857 __ Addu(end_elements, elements, end_elements); |
| 1653 __ Addu(end_elements, end_elements, kEndElementsOffset); | 1858 __ Addu(end_elements, end_elements, kEndElementsOffset); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1723 } | 1928 } |
| 1724 __ bind(&call_builtin); | 1929 __ bind(&call_builtin); |
| 1725 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, | 1930 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, |
| 1726 masm()->isolate()), | 1931 masm()->isolate()), |
| 1727 argc + 1, | 1932 argc + 1, |
| 1728 1); | 1933 1); |
| 1729 } | 1934 } |
| 1730 | 1935 |
| 1731 // Handle call cache miss. | 1936 // Handle call cache miss. |
| 1732 __ bind(&miss); | 1937 __ bind(&miss); |
| 1733 MaybeObject* maybe_result = GenerateMissBranch(); | 1938 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1734 if (maybe_result->IsFailure()) return maybe_result; | 1939 if (maybe_result->IsFailure()) return maybe_result; |
| 1735 | 1940 |
| 1736 // Return the generated code. | 1941 // Return the generated code. |
| 1737 return GetCode(function); | 1942 return TryGetCode(function); |
| 1738 } | 1943 } |
| 1739 | 1944 |
| 1740 | 1945 |
| 1741 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, | 1946 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, |
| 1742 JSObject* holder, | 1947 JSObject* holder, |
| 1743 JSGlobalPropertyCell* cell, | 1948 JSGlobalPropertyCell* cell, |
| 1744 JSFunction* function, | 1949 JSFunction* function, |
| 1745 String* name) { | 1950 String* name) { |
| 1746 // ----------- S t a t e ------------- | 1951 // ----------- S t a t e ------------- |
| 1747 // -- a2 : name | 1952 // -- a2 : name |
| 1748 // -- ra : return address | 1953 // -- ra : return address |
| 1749 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1954 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 1750 // -- ... | 1955 // -- ... |
| 1751 // -- sp[argc * 4] : receiver | 1956 // -- sp[argc * 4] : receiver |
| 1752 // ----------------------------------- | 1957 // ----------------------------------- |
| 1753 | 1958 |
| 1754 // If object is not an array, bail out to regular call. | 1959 // If object is not an array, bail out to regular call. |
| 1755 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); | 1960 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); |
| 1756 | 1961 |
| 1757 Label miss, return_undefined, call_builtin; | 1962 Label miss, return_undefined, call_builtin; |
| 1758 | 1963 |
| 1759 Register receiver = a1; | 1964 Register receiver = a1; |
| 1760 Register elements = a3; | 1965 Register elements = a3; |
| 1761 | 1966 |
| 1762 GenerateNameCheck(name, &miss); | 1967 GenerateNameCheck(Handle<String>(name), &miss); |
| 1763 | 1968 |
| 1764 // Get the receiver from the stack. | 1969 // Get the receiver from the stack. |
| 1765 const int argc = arguments().immediate(); | 1970 const int argc = arguments().immediate(); |
| 1766 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | 1971 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); |
| 1767 | 1972 |
| 1768 // Check that the receiver isn't a smi. | 1973 // Check that the receiver isn't a smi. |
| 1769 __ JumpIfSmi(receiver, &miss); | 1974 __ JumpIfSmi(receiver, &miss); |
| 1770 | 1975 |
| 1771 // Check that the maps haven't changed. | 1976 // Check that the maps haven't changed. |
| 1772 CheckPrototypes(JSObject::cast(object), | 1977 CheckPrototypes(JSObject::cast(object), |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1812 __ Ret(); | 2017 __ Ret(); |
| 1813 | 2018 |
| 1814 __ bind(&call_builtin); | 2019 __ bind(&call_builtin); |
| 1815 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop, | 2020 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop, |
| 1816 masm()->isolate()), | 2021 masm()->isolate()), |
| 1817 argc + 1, | 2022 argc + 1, |
| 1818 1); | 2023 1); |
| 1819 | 2024 |
| 1820 // Handle call cache miss. | 2025 // Handle call cache miss. |
| 1821 __ bind(&miss); | 2026 __ bind(&miss); |
| 1822 MaybeObject* maybe_result = GenerateMissBranch(); | 2027 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1823 if (maybe_result->IsFailure()) return maybe_result; | 2028 if (maybe_result->IsFailure()) return maybe_result; |
| 1824 | 2029 |
| 1825 // Return the generated code. | 2030 // Return the generated code. |
| 1826 return GetCode(function); | 2031 return TryGetCode(function); |
| 1827 } | 2032 } |
| 1828 | 2033 |
| 1829 | 2034 |
| 1830 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( | 2035 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( |
| 1831 Object* object, | 2036 Object* object, |
| 1832 JSObject* holder, | 2037 JSObject* holder, |
| 1833 JSGlobalPropertyCell* cell, | 2038 JSGlobalPropertyCell* cell, |
| 1834 JSFunction* function, | 2039 JSFunction* function, |
| 1835 String* name) { | 2040 String* name) { |
| 1836 // ----------- S t a t e ------------- | 2041 // ----------- S t a t e ------------- |
| 1837 // -- a2 : function name | 2042 // -- a2 : function name |
| 1838 // -- ra : return address | 2043 // -- ra : return address |
| 1839 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 2044 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 1840 // -- ... | 2045 // -- ... |
| 1841 // -- sp[argc * 4] : receiver | 2046 // -- sp[argc * 4] : receiver |
| 1842 // ----------------------------------- | 2047 // ----------------------------------- |
| 1843 | 2048 |
| 1844 // If object is not a string, bail out to regular call. | 2049 // If object is not a string, bail out to regular call. |
| 1845 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); | 2050 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); |
| 1846 | 2051 |
| 1847 const int argc = arguments().immediate(); | 2052 const int argc = arguments().immediate(); |
| 1848 | 2053 |
| 1849 Label miss; | 2054 Label miss; |
| 1850 Label name_miss; | 2055 Label name_miss; |
| 1851 Label index_out_of_range; | 2056 Label index_out_of_range; |
| 1852 | 2057 |
| 1853 Label* index_out_of_range_label = &index_out_of_range; | 2058 Label* index_out_of_range_label = &index_out_of_range; |
| 1854 | 2059 |
| 1855 if (kind_ == Code::CALL_IC && | 2060 if (kind_ == Code::CALL_IC && |
| 1856 (CallICBase::StringStubState::decode(extra_ic_state_) == | 2061 (CallICBase::StringStubState::decode(extra_state_) == |
| 1857 DEFAULT_STRING_STUB)) { | 2062 DEFAULT_STRING_STUB)) { |
| 1858 index_out_of_range_label = &miss; | 2063 index_out_of_range_label = &miss; |
| 1859 } | 2064 } |
| 1860 | 2065 |
| 1861 GenerateNameCheck(name, &name_miss); | 2066 GenerateNameCheck(Handle<String>(name), &name_miss); |
| 1862 | 2067 |
| 1863 // Check that the maps starting from the prototype haven't changed. | 2068 // Check that the maps starting from the prototype haven't changed. |
| 1864 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 2069 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 1865 Context::STRING_FUNCTION_INDEX, | 2070 Context::STRING_FUNCTION_INDEX, |
| 1866 v0, | 2071 v0, |
| 1867 &miss); | 2072 &miss); |
| 1868 ASSERT(object != holder); | 2073 ASSERT(object != holder); |
| 1869 CheckPrototypes(JSObject::cast(object->GetPrototype()), v0, holder, | 2074 CheckPrototypes(JSObject::cast(object->GetPrototype()), v0, holder, |
| 1870 a1, a3, t0, name, &miss); | 2075 a1, a3, t0, name, &miss); |
| 1871 | 2076 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1899 __ bind(&index_out_of_range); | 2104 __ bind(&index_out_of_range); |
| 1900 __ LoadRoot(v0, Heap::kNanValueRootIndex); | 2105 __ LoadRoot(v0, Heap::kNanValueRootIndex); |
| 1901 __ Drop(argc + 1); | 2106 __ Drop(argc + 1); |
| 1902 __ Ret(); | 2107 __ Ret(); |
| 1903 } | 2108 } |
| 1904 | 2109 |
| 1905 __ bind(&miss); | 2110 __ bind(&miss); |
| 1906 // Restore function name in a2. | 2111 // Restore function name in a2. |
| 1907 __ li(a2, Handle<String>(name)); | 2112 __ li(a2, Handle<String>(name)); |
| 1908 __ bind(&name_miss); | 2113 __ bind(&name_miss); |
| 1909 MaybeObject* maybe_result = GenerateMissBranch(); | 2114 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1910 if (maybe_result->IsFailure()) return maybe_result; | 2115 if (maybe_result->IsFailure()) return maybe_result; |
| 1911 | 2116 |
| 1912 // Return the generated code. | 2117 // Return the generated code. |
| 1913 return GetCode(function); | 2118 return TryGetCode(function); |
| 1914 } | 2119 } |
| 1915 | 2120 |
| 1916 | 2121 |
| 1917 MaybeObject* CallStubCompiler::CompileStringCharAtCall( | 2122 MaybeObject* CallStubCompiler::CompileStringCharAtCall( |
| 1918 Object* object, | 2123 Object* object, |
| 1919 JSObject* holder, | 2124 JSObject* holder, |
| 1920 JSGlobalPropertyCell* cell, | 2125 JSGlobalPropertyCell* cell, |
| 1921 JSFunction* function, | 2126 JSFunction* function, |
| 1922 String* name) { | 2127 String* name) { |
| 1923 // ----------- S t a t e ------------- | 2128 // ----------- S t a t e ------------- |
| 1924 // -- a2 : function name | 2129 // -- a2 : function name |
| 1925 // -- ra : return address | 2130 // -- ra : return address |
| 1926 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 2131 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 1927 // -- ... | 2132 // -- ... |
| 1928 // -- sp[argc * 4] : receiver | 2133 // -- sp[argc * 4] : receiver |
| 1929 // ----------------------------------- | 2134 // ----------------------------------- |
| 1930 | 2135 |
| 1931 // If object is not a string, bail out to regular call. | 2136 // If object is not a string, bail out to regular call. |
| 1932 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); | 2137 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); |
| 1933 | 2138 |
| 1934 const int argc = arguments().immediate(); | 2139 const int argc = arguments().immediate(); |
| 1935 | 2140 |
| 1936 Label miss; | 2141 Label miss; |
| 1937 Label name_miss; | 2142 Label name_miss; |
| 1938 Label index_out_of_range; | 2143 Label index_out_of_range; |
| 1939 Label* index_out_of_range_label = &index_out_of_range; | 2144 Label* index_out_of_range_label = &index_out_of_range; |
| 1940 | 2145 |
| 1941 if (kind_ == Code::CALL_IC && | 2146 if (kind_ == Code::CALL_IC && |
| 1942 (CallICBase::StringStubState::decode(extra_ic_state_) == | 2147 (CallICBase::StringStubState::decode(extra_state_) == |
| 1943 DEFAULT_STRING_STUB)) { | 2148 DEFAULT_STRING_STUB)) { |
| 1944 index_out_of_range_label = &miss; | 2149 index_out_of_range_label = &miss; |
| 1945 } | 2150 } |
| 1946 | 2151 |
| 1947 GenerateNameCheck(name, &name_miss); | 2152 GenerateNameCheck(Handle<String>(name), &name_miss); |
| 1948 | 2153 |
| 1949 // Check that the maps starting from the prototype haven't changed. | 2154 // Check that the maps starting from the prototype haven't changed. |
| 1950 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 2155 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 1951 Context::STRING_FUNCTION_INDEX, | 2156 Context::STRING_FUNCTION_INDEX, |
| 1952 v0, | 2157 v0, |
| 1953 &miss); | 2158 &miss); |
| 1954 ASSERT(object != holder); | 2159 ASSERT(object != holder); |
| 1955 CheckPrototypes(JSObject::cast(object->GetPrototype()), v0, holder, | 2160 CheckPrototypes(JSObject::cast(object->GetPrototype()), v0, holder, |
| 1956 a1, a3, t0, name, &miss); | 2161 a1, a3, t0, name, &miss); |
| 1957 | 2162 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1987 __ bind(&index_out_of_range); | 2192 __ bind(&index_out_of_range); |
| 1988 __ LoadRoot(v0, Heap::kEmptyStringRootIndex); | 2193 __ LoadRoot(v0, Heap::kEmptyStringRootIndex); |
| 1989 __ Drop(argc + 1); | 2194 __ Drop(argc + 1); |
| 1990 __ Ret(); | 2195 __ Ret(); |
| 1991 } | 2196 } |
| 1992 | 2197 |
| 1993 __ bind(&miss); | 2198 __ bind(&miss); |
| 1994 // Restore function name in a2. | 2199 // Restore function name in a2. |
| 1995 __ li(a2, Handle<String>(name)); | 2200 __ li(a2, Handle<String>(name)); |
| 1996 __ bind(&name_miss); | 2201 __ bind(&name_miss); |
| 1997 MaybeObject* maybe_result = GenerateMissBranch(); | 2202 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1998 if (maybe_result->IsFailure()) return maybe_result; | 2203 if (maybe_result->IsFailure()) return maybe_result; |
| 1999 | 2204 |
| 2000 // Return the generated code. | 2205 // Return the generated code. |
| 2001 return GetCode(function); | 2206 return TryGetCode(function); |
| 2002 } | 2207 } |
| 2003 | 2208 |
| 2004 | 2209 |
| 2005 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( | 2210 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( |
| 2006 Object* object, | 2211 Object* object, |
| 2007 JSObject* holder, | 2212 JSObject* holder, |
| 2008 JSGlobalPropertyCell* cell, | 2213 JSGlobalPropertyCell* cell, |
| 2009 JSFunction* function, | 2214 JSFunction* function, |
| 2010 String* name) { | 2215 String* name) { |
| 2011 // ----------- S t a t e ------------- | 2216 // ----------- S t a t e ------------- |
| 2012 // -- a2 : function name | 2217 // -- a2 : function name |
| 2013 // -- ra : return address | 2218 // -- ra : return address |
| 2014 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 2219 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 2015 // -- ... | 2220 // -- ... |
| 2016 // -- sp[argc * 4] : receiver | 2221 // -- sp[argc * 4] : receiver |
| 2017 // ----------------------------------- | 2222 // ----------------------------------- |
| 2018 | 2223 |
| 2019 const int argc = arguments().immediate(); | 2224 const int argc = arguments().immediate(); |
| 2020 | 2225 |
| 2021 // If the object is not a JSObject or we got an unexpected number of | 2226 // If the object is not a JSObject or we got an unexpected number of |
| 2022 // arguments, bail out to the regular call. | 2227 // arguments, bail out to the regular call. |
| 2023 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 2228 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); |
| 2024 | 2229 |
| 2025 Label miss; | 2230 Label miss; |
| 2026 GenerateNameCheck(name, &miss); | 2231 GenerateNameCheck(Handle<String>(name), &miss); |
| 2027 | 2232 |
| 2028 if (cell == NULL) { | 2233 if (cell == NULL) { |
| 2029 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); | 2234 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); |
| 2030 | 2235 |
| 2031 STATIC_ASSERT(kSmiTag == 0); | 2236 STATIC_ASSERT(kSmiTag == 0); |
| 2032 __ JumpIfSmi(a1, &miss); | 2237 __ JumpIfSmi(a1, &miss); |
| 2033 | 2238 |
| 2034 CheckPrototypes(JSObject::cast(object), a1, holder, v0, a3, t0, name, | 2239 CheckPrototypes(JSObject::cast(object), a1, holder, v0, a3, t0, name, |
| 2035 &miss); | 2240 &miss); |
| 2036 } else { | 2241 } else { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2059 StubRuntimeCallHelper call_helper; | 2264 StubRuntimeCallHelper call_helper; |
| 2060 char_from_code_generator.GenerateSlow(masm(), call_helper); | 2265 char_from_code_generator.GenerateSlow(masm(), call_helper); |
| 2061 | 2266 |
| 2062 // Tail call the full function. We do not have to patch the receiver | 2267 // Tail call the full function. We do not have to patch the receiver |
| 2063 // because the function makes no use of it. | 2268 // because the function makes no use of it. |
| 2064 __ bind(&slow); | 2269 __ bind(&slow); |
| 2065 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); | 2270 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); |
| 2066 | 2271 |
| 2067 __ bind(&miss); | 2272 __ bind(&miss); |
| 2068 // a2: function name. | 2273 // a2: function name. |
| 2069 MaybeObject* maybe_result = GenerateMissBranch(); | 2274 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2070 if (maybe_result->IsFailure()) return maybe_result; | 2275 if (maybe_result->IsFailure()) return maybe_result; |
| 2071 | 2276 |
| 2072 // Return the generated code. | 2277 // Return the generated code. |
| 2073 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2278 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
| 2074 } | 2279 } |
| 2075 | 2280 |
| 2076 | 2281 |
| 2077 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, | 2282 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, |
| 2078 JSObject* holder, | 2283 JSObject* holder, |
| 2079 JSGlobalPropertyCell* cell, | 2284 JSGlobalPropertyCell* cell, |
| 2080 JSFunction* function, | 2285 JSFunction* function, |
| 2081 String* name) { | 2286 String* name) { |
| 2082 // ----------- S t a t e ------------- | 2287 // ----------- S t a t e ------------- |
| 2083 // -- a2 : function name | 2288 // -- a2 : function name |
| 2084 // -- ra : return address | 2289 // -- ra : return address |
| 2085 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 2290 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 2086 // -- ... | 2291 // -- ... |
| 2087 // -- sp[argc * 4] : receiver | 2292 // -- sp[argc * 4] : receiver |
| 2088 // ----------------------------------- | 2293 // ----------------------------------- |
| 2089 | 2294 |
| 2090 if (!CpuFeatures::IsSupported(FPU)) | 2295 if (!CpuFeatures::IsSupported(FPU)) |
| 2091 return heap()->undefined_value(); | 2296 return heap()->undefined_value(); |
| 2092 CpuFeatures::Scope scope_fpu(FPU); | 2297 CpuFeatures::Scope scope_fpu(FPU); |
| 2093 | 2298 |
| 2094 const int argc = arguments().immediate(); | 2299 const int argc = arguments().immediate(); |
| 2095 | 2300 |
| 2096 // If the object is not a JSObject or we got an unexpected number of | 2301 // If the object is not a JSObject or we got an unexpected number of |
| 2097 // arguments, bail out to the regular call. | 2302 // arguments, bail out to the regular call. |
| 2098 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 2303 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); |
| 2099 | 2304 |
| 2100 Label miss, slow; | 2305 Label miss, slow; |
| 2101 GenerateNameCheck(name, &miss); | 2306 GenerateNameCheck(Handle<String>(name), &miss); |
| 2102 | 2307 |
| 2103 if (cell == NULL) { | 2308 if (cell == NULL) { |
| 2104 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); | 2309 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); |
| 2105 | 2310 |
| 2106 STATIC_ASSERT(kSmiTag == 0); | 2311 STATIC_ASSERT(kSmiTag == 0); |
| 2107 __ JumpIfSmi(a1, &miss); | 2312 __ JumpIfSmi(a1, &miss); |
| 2108 | 2313 |
| 2109 CheckPrototypes(JSObject::cast(object), a1, holder, a0, a3, t0, name, | 2314 CheckPrototypes(JSObject::cast(object), a1, holder, a0, a3, t0, name, |
| 2110 &miss); | 2315 &miss); |
| 2111 } else { | 2316 } else { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2193 // Restore FCSR and fall to slow case. | 2398 // Restore FCSR and fall to slow case. |
| 2194 __ ctc1(a3, FCSR); | 2399 __ ctc1(a3, FCSR); |
| 2195 | 2400 |
| 2196 __ bind(&slow); | 2401 __ bind(&slow); |
| 2197 // Tail call the full function. We do not have to patch the receiver | 2402 // Tail call the full function. We do not have to patch the receiver |
| 2198 // because the function makes no use of it. | 2403 // because the function makes no use of it. |
| 2199 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); | 2404 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); |
| 2200 | 2405 |
| 2201 __ bind(&miss); | 2406 __ bind(&miss); |
| 2202 // a2: function name. | 2407 // a2: function name. |
| 2203 MaybeObject* obj = GenerateMissBranch(); | 2408 MaybeObject* obj = TryGenerateMissBranch(); |
| 2204 if (obj->IsFailure()) return obj; | 2409 if (obj->IsFailure()) return obj; |
| 2205 | 2410 |
| 2206 // Return the generated code. | 2411 // Return the generated code. |
| 2207 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2412 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
| 2208 } | 2413 } |
| 2209 | 2414 |
| 2210 | 2415 |
| 2211 MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, | 2416 MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, |
| 2212 JSObject* holder, | 2417 JSObject* holder, |
| 2213 JSGlobalPropertyCell* cell, | 2418 JSGlobalPropertyCell* cell, |
| 2214 JSFunction* function, | 2419 JSFunction* function, |
| 2215 String* name) { | 2420 String* name) { |
| 2216 // ----------- S t a t e ------------- | 2421 // ----------- S t a t e ------------- |
| 2217 // -- a2 : function name | 2422 // -- a2 : function name |
| 2218 // -- ra : return address | 2423 // -- ra : return address |
| 2219 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 2424 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 2220 // -- ... | 2425 // -- ... |
| 2221 // -- sp[argc * 4] : receiver | 2426 // -- sp[argc * 4] : receiver |
| 2222 // ----------------------------------- | 2427 // ----------------------------------- |
| 2223 | 2428 |
| 2224 const int argc = arguments().immediate(); | 2429 const int argc = arguments().immediate(); |
| 2225 | 2430 |
| 2226 // If the object is not a JSObject or we got an unexpected number of | 2431 // If the object is not a JSObject or we got an unexpected number of |
| 2227 // arguments, bail out to the regular call. | 2432 // arguments, bail out to the regular call. |
| 2228 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 2433 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); |
| 2229 | 2434 |
| 2230 Label miss; | 2435 Label miss; |
| 2231 GenerateNameCheck(name, &miss); | 2436 GenerateNameCheck(Handle<String>(name), &miss); |
| 2232 | 2437 |
| 2233 if (cell == NULL) { | 2438 if (cell == NULL) { |
| 2234 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); | 2439 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); |
| 2235 | 2440 |
| 2236 STATIC_ASSERT(kSmiTag == 0); | 2441 STATIC_ASSERT(kSmiTag == 0); |
| 2237 __ JumpIfSmi(a1, &miss); | 2442 __ JumpIfSmi(a1, &miss); |
| 2238 | 2443 |
| 2239 CheckPrototypes(JSObject::cast(object), a1, holder, v0, a3, t0, name, | 2444 CheckPrototypes(JSObject::cast(object), a1, holder, v0, a3, t0, name, |
| 2240 &miss); | 2445 &miss); |
| 2241 } else { | 2446 } else { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2295 __ Drop(argc + 1); | 2500 __ Drop(argc + 1); |
| 2296 __ Ret(); | 2501 __ Ret(); |
| 2297 | 2502 |
| 2298 // Tail call the full function. We do not have to patch the receiver | 2503 // Tail call the full function. We do not have to patch the receiver |
| 2299 // because the function makes no use of it. | 2504 // because the function makes no use of it. |
| 2300 __ bind(&slow); | 2505 __ bind(&slow); |
| 2301 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); | 2506 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); |
| 2302 | 2507 |
| 2303 __ bind(&miss); | 2508 __ bind(&miss); |
| 2304 // a2: function name. | 2509 // a2: function name. |
| 2305 MaybeObject* maybe_result = GenerateMissBranch(); | 2510 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2306 if (maybe_result->IsFailure()) return maybe_result; | 2511 if (maybe_result->IsFailure()) return maybe_result; |
| 2307 | 2512 |
| 2308 // Return the generated code. | 2513 // Return the generated code. |
| 2309 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2514 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
| 2310 } | 2515 } |
| 2311 | 2516 |
| 2312 | 2517 |
| 2313 MaybeObject* CallStubCompiler::CompileFastApiCall( | 2518 MaybeObject* CallStubCompiler::CompileFastApiCall( |
| 2314 const CallOptimization& optimization, | 2519 const CallOptimization& optimization, |
| 2315 Object* object, | 2520 Object* object, |
| 2316 JSObject* holder, | 2521 JSObject* holder, |
| 2317 JSGlobalPropertyCell* cell, | 2522 JSGlobalPropertyCell* cell, |
| 2318 JSFunction* function, | 2523 JSFunction* function, |
| 2319 String* name) { | 2524 String* name) { |
| 2320 | 2525 |
| 2321 Counters* counters = isolate()->counters(); | 2526 Counters* counters = isolate()->counters(); |
| 2322 | 2527 |
| 2323 ASSERT(optimization.is_simple_api_call()); | 2528 ASSERT(optimization.is_simple_api_call()); |
| 2324 // Bail out if object is a global object as we don't want to | 2529 // Bail out if object is a global object as we don't want to |
| 2325 // repatch it to global receiver. | 2530 // repatch it to global receiver. |
| 2326 if (object->IsGlobalObject()) return heap()->undefined_value(); | 2531 if (object->IsGlobalObject()) return heap()->undefined_value(); |
| 2327 if (cell != NULL) return heap()->undefined_value(); | 2532 if (cell != NULL) return heap()->undefined_value(); |
| 2328 if (!object->IsJSObject()) return heap()->undefined_value(); | 2533 if (!object->IsJSObject()) return heap()->undefined_value(); |
| 2329 int depth = optimization.GetPrototypeDepthOfExpectedType( | 2534 int depth = optimization.GetPrototypeDepthOfExpectedType( |
| 2330 JSObject::cast(object), holder); | 2535 JSObject::cast(object), holder); |
| 2331 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); | 2536 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); |
| 2332 | 2537 |
| 2333 Label miss, miss_before_stack_reserved; | 2538 Label miss, miss_before_stack_reserved; |
| 2334 | 2539 |
| 2335 GenerateNameCheck(name, &miss_before_stack_reserved); | 2540 GenerateNameCheck(Handle<String>(name), &miss_before_stack_reserved); |
| 2336 | 2541 |
| 2337 // Get the receiver from the stack. | 2542 // Get the receiver from the stack. |
| 2338 const int argc = arguments().immediate(); | 2543 const int argc = arguments().immediate(); |
| 2339 __ lw(a1, MemOperand(sp, argc * kPointerSize)); | 2544 __ lw(a1, MemOperand(sp, argc * kPointerSize)); |
| 2340 | 2545 |
| 2341 // Check that the receiver isn't a smi. | 2546 // Check that the receiver isn't a smi. |
| 2342 __ JumpIfSmi(a1, &miss_before_stack_reserved); | 2547 __ JumpIfSmi(a1, &miss_before_stack_reserved); |
| 2343 | 2548 |
| 2344 __ IncrementCounter(counters->call_const(), 1, a0, a3); | 2549 __ IncrementCounter(counters->call_const(), 1, a0, a3); |
| 2345 __ IncrementCounter(counters->call_const_fast_api(), 1, a0, a3); | 2550 __ IncrementCounter(counters->call_const_fast_api(), 1, a0, a3); |
| 2346 | 2551 |
| 2347 ReserveSpaceForFastApiCall(masm(), a0); | 2552 ReserveSpaceForFastApiCall(masm(), a0); |
| 2348 | 2553 |
| 2349 // Check that the maps haven't changed and find a Holder as a side effect. | 2554 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2350 CheckPrototypes(JSObject::cast(object), a1, holder, a0, a3, t0, name, | 2555 CheckPrototypes(JSObject::cast(object), a1, holder, a0, a3, t0, name, |
| 2351 depth, &miss); | 2556 depth, &miss); |
| 2352 | 2557 |
| 2353 MaybeObject* result = GenerateFastApiDirectCall(masm(), optimization, argc); | 2558 MaybeObject* result = GenerateFastApiDirectCall(masm(), optimization, argc); |
| 2354 if (result->IsFailure()) return result; | 2559 if (result->IsFailure()) return result; |
| 2355 | 2560 |
| 2356 __ bind(&miss); | 2561 __ bind(&miss); |
| 2357 FreeSpaceForFastApiCall(masm()); | 2562 FreeSpaceForFastApiCall(masm()); |
| 2358 | 2563 |
| 2359 __ bind(&miss_before_stack_reserved); | 2564 __ bind(&miss_before_stack_reserved); |
| 2360 MaybeObject* maybe_result = GenerateMissBranch(); | 2565 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2361 if (maybe_result->IsFailure()) return maybe_result; | 2566 if (maybe_result->IsFailure()) return maybe_result; |
| 2362 | 2567 |
| 2363 // Return the generated code. | 2568 // Return the generated code. |
| 2364 return GetCode(function); | 2569 return TryGetCode(function); |
| 2365 } | 2570 } |
| 2366 | 2571 |
| 2367 | 2572 |
| 2368 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, | 2573 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, |
| 2369 JSObject* holder, | 2574 JSObject* holder, |
| 2370 JSFunction* function, | 2575 JSFunction* function, |
| 2371 String* name, | 2576 String* name, |
| 2372 CheckType check) { | 2577 CheckType check) { |
| 2373 // ----------- S t a t e ------------- | 2578 // ----------- S t a t e ------------- |
| 2374 // -- a2 : name | 2579 // -- a2 : name |
| 2375 // -- ra : return address | 2580 // -- ra : return address |
| 2376 // ----------------------------------- | 2581 // ----------------------------------- |
| 2377 if (HasCustomCallGenerator(function)) { | 2582 if (HasCustomCallGenerator(function)) { |
| 2378 MaybeObject* maybe_result = CompileCustomCall( | 2583 MaybeObject* maybe_result = CompileCustomCall( |
| 2379 object, holder, NULL, function, name); | 2584 object, holder, NULL, function, name); |
| 2380 Object* result; | 2585 Object* result; |
| 2381 if (!maybe_result->ToObject(&result)) return maybe_result; | 2586 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2382 // Undefined means bail out to regular compiler. | 2587 // Undefined means bail out to regular compiler. |
| 2383 if (!result->IsUndefined()) return result; | 2588 if (!result->IsUndefined()) return result; |
| 2384 } | 2589 } |
| 2385 | 2590 |
| 2386 Label miss; | 2591 Label miss; |
| 2387 | 2592 |
| 2388 GenerateNameCheck(name, &miss); | 2593 GenerateNameCheck(Handle<String>(name), &miss); |
| 2389 | 2594 |
| 2390 // Get the receiver from the stack. | 2595 // Get the receiver from the stack. |
| 2391 const int argc = arguments().immediate(); | 2596 const int argc = arguments().immediate(); |
| 2392 __ lw(a1, MemOperand(sp, argc * kPointerSize)); | 2597 __ lw(a1, MemOperand(sp, argc * kPointerSize)); |
| 2393 | 2598 |
| 2394 // Check that the receiver isn't a smi. | 2599 // Check that the receiver isn't a smi. |
| 2395 if (check != NUMBER_CHECK) { | 2600 if (check != NUMBER_CHECK) { |
| 2396 __ And(t1, a1, Operand(kSmiTagMask)); | 2601 __ And(t1, a1, Operand(kSmiTagMask)); |
| 2397 __ Branch(&miss, eq, t1, Operand(zero_reg)); | 2602 __ Branch(&miss, eq, t1, Operand(zero_reg)); |
| 2398 } | 2603 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2477 CheckPrototypes(JSObject::cast(object->GetPrototype()), a0, holder, a3, | 2682 CheckPrototypes(JSObject::cast(object->GetPrototype()), a0, holder, a3, |
| 2478 a1, t0, name, &miss); | 2683 a1, t0, name, &miss); |
| 2479 } | 2684 } |
| 2480 break; | 2685 break; |
| 2481 } | 2686 } |
| 2482 | 2687 |
| 2483 default: | 2688 default: |
| 2484 UNREACHABLE(); | 2689 UNREACHABLE(); |
| 2485 } | 2690 } |
| 2486 | 2691 |
| 2487 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 2692 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2488 ? CALL_AS_FUNCTION | 2693 ? CALL_AS_FUNCTION |
| 2489 : CALL_AS_METHOD; | 2694 : CALL_AS_METHOD; |
| 2490 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind); | 2695 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind); |
| 2491 | 2696 |
| 2492 // Handle call cache miss. | 2697 // Handle call cache miss. |
| 2493 __ bind(&miss); | 2698 __ bind(&miss); |
| 2494 | 2699 |
| 2495 MaybeObject* maybe_result = GenerateMissBranch(); | 2700 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2496 if (maybe_result->IsFailure()) return maybe_result; | 2701 if (maybe_result->IsFailure()) return maybe_result; |
| 2497 | 2702 |
| 2498 // Return the generated code. | 2703 // Return the generated code. |
| 2499 return GetCode(function); | 2704 return TryGetCode(function); |
| 2500 } | 2705 } |
| 2501 | 2706 |
| 2502 | 2707 |
| 2503 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, | 2708 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, |
| 2504 JSObject* holder, | 2709 JSObject* holder, |
| 2505 String* name) { | 2710 String* name) { |
| 2506 // ----------- S t a t e ------------- | 2711 // ----------- S t a t e ------------- |
| 2507 // -- a2 : name | 2712 // -- a2 : name |
| 2508 // -- ra : return address | 2713 // -- ra : return address |
| 2509 // ----------------------------------- | 2714 // ----------------------------------- |
| 2510 | 2715 |
| 2511 Label miss; | 2716 Label miss; |
| 2512 | 2717 |
| 2513 GenerateNameCheck(name, &miss); | 2718 GenerateNameCheck(Handle<String>(name), &miss); |
| 2514 | 2719 |
| 2515 // Get the number of arguments. | 2720 // Get the number of arguments. |
| 2516 const int argc = arguments().immediate(); | 2721 const int argc = arguments().immediate(); |
| 2517 | 2722 |
| 2518 LookupResult lookup; | 2723 LookupResult lookup(isolate()); |
| 2519 LookupPostInterceptor(holder, name, &lookup); | 2724 LookupPostInterceptor(holder, name, &lookup); |
| 2520 | 2725 |
| 2521 // Get the receiver from the stack. | 2726 // Get the receiver from the stack. |
| 2522 __ lw(a1, MemOperand(sp, argc * kPointerSize)); | 2727 __ lw(a1, MemOperand(sp, argc * kPointerSize)); |
| 2523 | 2728 |
| 2524 CallInterceptorCompiler compiler(this, arguments(), a2, extra_ic_state_); | 2729 CallInterceptorCompiler compiler(this, arguments(), a2, extra_state_); |
| 2525 MaybeObject* result = compiler.Compile(masm(), | 2730 MaybeObject* result = compiler.Compile(masm(), |
| 2526 object, | 2731 object, |
| 2527 holder, | 2732 holder, |
| 2528 name, | 2733 name, |
| 2529 &lookup, | 2734 &lookup, |
| 2530 a1, | 2735 a1, |
| 2531 a3, | 2736 a3, |
| 2532 t0, | 2737 t0, |
| 2533 a0, | 2738 a0, |
| 2534 &miss); | 2739 &miss); |
| 2535 if (result->IsFailure()) { | 2740 if (result->IsFailure()) { |
| 2536 return result; | 2741 return result; |
| 2537 } | 2742 } |
| 2538 | 2743 |
| 2539 // Move returned value, the function to call, to a1. | 2744 // Move returned value, the function to call, to a1. |
| 2540 __ mov(a1, v0); | 2745 __ mov(a1, v0); |
| 2541 // Restore receiver. | 2746 // Restore receiver. |
| 2542 __ lw(a0, MemOperand(sp, argc * kPointerSize)); | 2747 __ lw(a0, MemOperand(sp, argc * kPointerSize)); |
| 2543 | 2748 |
| 2544 GenerateCallFunction(masm(), object, arguments(), &miss, extra_ic_state_); | 2749 GenerateCallFunction(masm(), Handle<Object>(object), arguments(), &miss, |
| 2750 extra_state_); |
| 2545 | 2751 |
| 2546 // Handle call cache miss. | 2752 // Handle call cache miss. |
| 2547 __ bind(&miss); | 2753 __ bind(&miss); |
| 2548 MaybeObject* maybe_result = GenerateMissBranch(); | 2754 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2549 if (maybe_result->IsFailure()) return maybe_result; | 2755 if (maybe_result->IsFailure()) return maybe_result; |
| 2550 | 2756 |
| 2551 // Return the generated code. | 2757 // Return the generated code. |
| 2552 return GetCode(INTERCEPTOR, name); | 2758 return TryGetCode(INTERCEPTOR, name); |
| 2553 } | 2759 } |
| 2554 | 2760 |
| 2555 | 2761 |
| 2556 MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, | 2762 MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, |
| 2557 GlobalObject* holder, | 2763 GlobalObject* holder, |
| 2558 JSGlobalPropertyCell* cell, | 2764 JSGlobalPropertyCell* cell, |
| 2559 JSFunction* function, | 2765 JSFunction* function, |
| 2560 String* name) { | 2766 String* name) { |
| 2561 // ----------- S t a t e ------------- | 2767 // ----------- S t a t e ------------- |
| 2562 // -- a2 : name | 2768 // -- a2 : name |
| 2563 // -- ra : return address | 2769 // -- ra : return address |
| 2564 // ----------------------------------- | 2770 // ----------------------------------- |
| 2565 | 2771 |
| 2566 if (HasCustomCallGenerator(function)) { | 2772 if (HasCustomCallGenerator(function)) { |
| 2567 MaybeObject* maybe_result = CompileCustomCall( | 2773 MaybeObject* maybe_result = CompileCustomCall( |
| 2568 object, holder, cell, function, name); | 2774 object, holder, cell, function, name); |
| 2569 Object* result; | 2775 Object* result; |
| 2570 if (!maybe_result->ToObject(&result)) return maybe_result; | 2776 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2571 // Undefined means bail out to regular compiler. | 2777 // Undefined means bail out to regular compiler. |
| 2572 if (!result->IsUndefined()) return result; | 2778 if (!result->IsUndefined()) return result; |
| 2573 } | 2779 } |
| 2574 | 2780 |
| 2575 Label miss; | 2781 Label miss; |
| 2576 | 2782 |
| 2577 GenerateNameCheck(name, &miss); | 2783 GenerateNameCheck(Handle<String>(name), &miss); |
| 2578 | 2784 |
| 2579 // Get the number of arguments. | 2785 // Get the number of arguments. |
| 2580 const int argc = arguments().immediate(); | 2786 const int argc = arguments().immediate(); |
| 2581 | 2787 |
| 2582 GenerateGlobalReceiverCheck(object, holder, name, &miss); | 2788 GenerateGlobalReceiverCheck(object, holder, name, &miss); |
| 2583 GenerateLoadFunctionFromCell(cell, function, &miss); | 2789 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2584 | 2790 |
| 2585 // Patch the receiver on the stack with the global proxy if | 2791 // Patch the receiver on the stack with the global proxy if |
| 2586 // necessary. | 2792 // necessary. |
| 2587 if (object->IsGlobalObject()) { | 2793 if (object->IsGlobalObject()) { |
| 2588 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); | 2794 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); |
| 2589 __ sw(a3, MemOperand(sp, argc * kPointerSize)); | 2795 __ sw(a3, MemOperand(sp, argc * kPointerSize)); |
| 2590 } | 2796 } |
| 2591 | 2797 |
| 2592 // Setup the context (function already in r1). | 2798 // Setup the context (function already in r1). |
| 2593 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 2799 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
| 2594 | 2800 |
| 2595 // Jump to the cached code (tail call). | 2801 // Jump to the cached code (tail call). |
| 2596 Counters* counters = masm()->isolate()->counters(); | 2802 Counters* counters = masm()->isolate()->counters(); |
| 2597 __ IncrementCounter(counters->call_global_inline(), 1, a3, t0); | 2803 __ IncrementCounter(counters->call_global_inline(), 1, a3, t0); |
| 2598 ASSERT(function->is_compiled()); | |
| 2599 Handle<Code> code(function->code()); | 2804 Handle<Code> code(function->code()); |
| 2600 ParameterCount expected(function->shared()->formal_parameter_count()); | 2805 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2601 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 2806 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2602 ? CALL_AS_FUNCTION | 2807 ? CALL_AS_FUNCTION |
| 2603 : CALL_AS_METHOD; | 2808 : CALL_AS_METHOD; |
| 2604 if (V8::UseCrankshaft()) { | 2809 // We call indirectly through the code field in the function to |
| 2605 // TODO(kasperl): For now, we always call indirectly through the | 2810 // allow recompilation to take effect without changing any of the |
| 2606 // code field in the function to allow recompilation to take effect | 2811 // call sites. |
| 2607 // without changing any of the call sites. | 2812 __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
| 2608 __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | 2813 __ InvokeCode(a3, expected, arguments(), JUMP_FUNCTION, |
| 2609 __ InvokeCode(a3, expected, arguments(), JUMP_FUNCTION, | 2814 NullCallWrapper(), call_kind); |
| 2610 NullCallWrapper(), call_kind); | |
| 2611 } else { | |
| 2612 __ InvokeCode(code, expected, arguments(), RelocInfo::CODE_TARGET, | |
| 2613 JUMP_FUNCTION, call_kind); | |
| 2614 } | |
| 2615 | 2815 |
| 2616 // Handle call cache miss. | 2816 // Handle call cache miss. |
| 2617 __ bind(&miss); | 2817 __ bind(&miss); |
| 2618 __ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3); | 2818 __ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3); |
| 2619 MaybeObject* maybe_result = GenerateMissBranch(); | 2819 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2620 if (maybe_result->IsFailure()) return maybe_result; | 2820 if (maybe_result->IsFailure()) return maybe_result; |
| 2621 | 2821 |
| 2622 // Return the generated code. | 2822 // Return the generated code. |
| 2623 return GetCode(NORMAL, name); | 2823 return TryGetCode(NORMAL, name); |
| 2624 } | 2824 } |
| 2625 | 2825 |
| 2626 | 2826 |
| 2627 MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, | 2827 MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, |
| 2628 int index, | 2828 int index, |
| 2629 Map* transition, | 2829 Map* transition, |
| 2630 String* name) { | 2830 String* name) { |
| 2631 // ----------- S t a t e ------------- | 2831 // ----------- S t a t e ------------- |
| 2632 // -- a0 : value | 2832 // -- a0 : value |
| 2633 // -- a1 : receiver | 2833 // -- a1 : receiver |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2792 __ bind(&miss); | 2992 __ bind(&miss); |
| 2793 __ IncrementCounter(counters->named_store_global_inline_miss(), 1, a1, a3); | 2993 __ IncrementCounter(counters->named_store_global_inline_miss(), 1, a1, a3); |
| 2794 Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); | 2994 Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); |
| 2795 __ Jump(ic, RelocInfo::CODE_TARGET); | 2995 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 2796 | 2996 |
| 2797 // Return the generated code. | 2997 // Return the generated code. |
| 2798 return GetCode(NORMAL, name); | 2998 return GetCode(NORMAL, name); |
| 2799 } | 2999 } |
| 2800 | 3000 |
| 2801 | 3001 |
| 2802 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, | 3002 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, |
| 2803 JSObject* object, | 3003 Handle<JSObject> object, |
| 2804 JSObject* last) { | 3004 Handle<JSObject> last) { |
| 2805 // ----------- S t a t e ------------- | 3005 // ----------- S t a t e ------------- |
| 2806 // -- a0 : receiver | 3006 // -- a0 : receiver |
| 2807 // -- ra : return address | 3007 // -- ra : return address |
| 2808 // ----------------------------------- | 3008 // ----------------------------------- |
| 2809 Label miss; | 3009 Label miss; |
| 2810 | 3010 |
| 2811 // Check that the receiver is not a smi. | 3011 // Check that the receiver is not a smi. |
| 2812 __ JumpIfSmi(a0, &miss); | 3012 __ JumpIfSmi(a0, &miss); |
| 2813 | 3013 |
| 2814 // Check the maps of the full prototype chain. | 3014 // Check the maps of the full prototype chain. |
| 2815 CheckPrototypes(object, a0, last, a3, a1, t0, name, &miss); | 3015 CheckPrototypes(object, a0, last, a3, a1, t0, name, &miss); |
| 2816 | 3016 |
| 2817 // If the last object in the prototype chain is a global object, | 3017 // If the last object in the prototype chain is a global object, |
| 2818 // check that the global property cell is empty. | 3018 // check that the global property cell is empty. |
| 2819 if (last->IsGlobalObject()) { | 3019 if (last->IsGlobalObject()) { |
| 2820 MaybeObject* cell = GenerateCheckPropertyCell(masm(), | 3020 GenerateCheckPropertyCell( |
| 2821 GlobalObject::cast(last), | 3021 masm(), Handle<GlobalObject>::cast(last), name, a1, &miss); |
| 2822 name, | |
| 2823 a1, | |
| 2824 &miss); | |
| 2825 if (cell->IsFailure()) { | |
| 2826 miss.Unuse(); | |
| 2827 return cell; | |
| 2828 } | |
| 2829 } | 3022 } |
| 2830 | 3023 |
| 2831 // Return undefined if maps of the full prototype chain is still the same. | 3024 // Return undefined if maps of the full prototype chain is still the same. |
| 2832 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 3025 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
| 2833 __ Ret(); | 3026 __ Ret(); |
| 2834 | 3027 |
| 2835 __ bind(&miss); | 3028 __ bind(&miss); |
| 2836 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3029 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2837 | 3030 |
| 2838 // Return the generated code. | 3031 // Return the generated code. |
| 2839 return GetCode(NONEXISTENT, heap()->empty_string()); | 3032 return GetCode(NONEXISTENT, factory()->empty_string()); |
| 2840 } | 3033 } |
| 2841 | 3034 |
| 2842 | 3035 |
| 2843 MaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object, | 3036 Handle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object, |
| 2844 JSObject* holder, | 3037 Handle<JSObject> holder, |
| 2845 int index, | 3038 int index, |
| 2846 String* name) { | 3039 Handle<String> name) { |
| 2847 // ----------- S t a t e ------------- | 3040 // ----------- S t a t e ------------- |
| 2848 // -- a0 : receiver | 3041 // -- a0 : receiver |
| 2849 // -- a2 : name | 3042 // -- a2 : name |
| 2850 // -- ra : return address | 3043 // -- ra : return address |
| 2851 // ----------------------------------- | 3044 // ----------------------------------- |
| 2852 Label miss; | 3045 Label miss; |
| 2853 | 3046 |
| 2854 __ mov(v0, a0); | 3047 __ mov(v0, a0); |
| 2855 | 3048 |
| 2856 GenerateLoadField(object, holder, v0, a3, a1, t0, index, name, &miss); | 3049 GenerateLoadField(object, holder, v0, a3, a1, t0, index, name, &miss); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2877 callback, name, &miss); | 3070 callback, name, &miss); |
| 2878 if (result->IsFailure()) { | 3071 if (result->IsFailure()) { |
| 2879 miss.Unuse(); | 3072 miss.Unuse(); |
| 2880 return result; | 3073 return result; |
| 2881 } | 3074 } |
| 2882 | 3075 |
| 2883 __ bind(&miss); | 3076 __ bind(&miss); |
| 2884 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3077 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2885 | 3078 |
| 2886 // Return the generated code. | 3079 // Return the generated code. |
| 2887 return GetCode(CALLBACKS, name); | 3080 return TryGetCode(CALLBACKS, name); |
| 2888 } | 3081 } |
| 2889 | 3082 |
| 2890 | 3083 |
| 2891 MaybeObject* LoadStubCompiler::CompileLoadConstant(JSObject* object, | 3084 Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, |
| 2892 JSObject* holder, | 3085 Handle<JSObject> holder, |
| 2893 Object* value, | 3086 Handle<Object> value, |
| 2894 String* name) { | 3087 Handle<String> name) { |
| 2895 // ----------- S t a t e ------------- | 3088 // ----------- S t a t e ------------- |
| 2896 // -- a0 : receiver | 3089 // -- a0 : receiver |
| 2897 // -- a2 : name | 3090 // -- a2 : name |
| 2898 // -- ra : return address | 3091 // -- ra : return address |
| 2899 // ----------------------------------- | 3092 // ----------------------------------- |
| 2900 Label miss; | 3093 Label miss; |
| 2901 | 3094 |
| 2902 GenerateLoadConstant(object, holder, a0, a3, a1, t0, value, name, &miss); | 3095 GenerateLoadConstant(object, holder, a0, a3, a1, t0, value, name, &miss); |
| 2903 __ bind(&miss); | 3096 __ bind(&miss); |
| 2904 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3097 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2905 | 3098 |
| 2906 // Return the generated code. | 3099 // Return the generated code. |
| 2907 return GetCode(CONSTANT_FUNCTION, name); | 3100 return GetCode(CONSTANT_FUNCTION, name); |
| 2908 } | 3101 } |
| 2909 | 3102 |
| 2910 | 3103 |
| 2911 MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* object, | 3104 MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* object, |
| 2912 JSObject* holder, | 3105 JSObject* holder, |
| 2913 String* name) { | 3106 String* name) { |
| 2914 // ----------- S t a t e ------------- | 3107 // ----------- S t a t e ------------- |
| 2915 // -- a0 : receiver | 3108 // -- a0 : receiver |
| 2916 // -- a2 : name | 3109 // -- a2 : name |
| 2917 // -- ra : return address | 3110 // -- ra : return address |
| 2918 // -- [sp] : receiver | 3111 // -- [sp] : receiver |
| 2919 // ----------------------------------- | 3112 // ----------------------------------- |
| 2920 Label miss; | 3113 Label miss; |
| 2921 | 3114 |
| 2922 LookupResult lookup; | 3115 LookupResult lookup(isolate()); |
| 2923 LookupPostInterceptor(holder, name, &lookup); | 3116 LookupPostInterceptor(holder, name, &lookup); |
| 2924 GenerateLoadInterceptor(object, | 3117 GenerateLoadInterceptor(object, |
| 2925 holder, | 3118 holder, |
| 2926 &lookup, | 3119 &lookup, |
| 2927 a0, | 3120 a0, |
| 2928 a2, | 3121 a2, |
| 2929 a3, | 3122 a3, |
| 2930 a1, | 3123 a1, |
| 2931 t0, | 3124 t0, |
| 2932 name, | 3125 name, |
| 2933 &miss); | 3126 &miss); |
| 2934 __ bind(&miss); | 3127 __ bind(&miss); |
| 2935 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3128 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2936 | 3129 |
| 2937 // Return the generated code. | 3130 // Return the generated code. |
| 2938 return GetCode(INTERCEPTOR, name); | 3131 return TryGetCode(INTERCEPTOR, name); |
| 2939 } | 3132 } |
| 2940 | 3133 |
| 2941 | 3134 |
| 2942 MaybeObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object, | 3135 MaybeObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object, |
| 2943 GlobalObject* holder, | 3136 GlobalObject* holder, |
| 2944 JSGlobalPropertyCell* cell, | 3137 JSGlobalPropertyCell* cell, |
| 2945 String* name, | 3138 String* name, |
| 2946 bool is_dont_delete) { | 3139 bool is_dont_delete) { |
| 2947 // ----------- S t a t e ------------- | 3140 // ----------- S t a t e ------------- |
| 2948 // -- a0 : receiver | 3141 // -- a0 : receiver |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2975 __ mov(v0, t0); | 3168 __ mov(v0, t0); |
| 2976 Counters* counters = masm()->isolate()->counters(); | 3169 Counters* counters = masm()->isolate()->counters(); |
| 2977 __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3); | 3170 __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3); |
| 2978 __ Ret(); | 3171 __ Ret(); |
| 2979 | 3172 |
| 2980 __ bind(&miss); | 3173 __ bind(&miss); |
| 2981 __ IncrementCounter(counters->named_load_global_stub_miss(), 1, a1, a3); | 3174 __ IncrementCounter(counters->named_load_global_stub_miss(), 1, a1, a3); |
| 2982 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3175 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2983 | 3176 |
| 2984 // Return the generated code. | 3177 // Return the generated code. |
| 2985 return GetCode(NORMAL, name); | 3178 return TryGetCode(NORMAL, name); |
| 2986 } | 3179 } |
| 2987 | 3180 |
| 2988 | 3181 |
| 2989 MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name, | 3182 Handle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name, |
| 2990 JSObject* receiver, | 3183 Handle<JSObject> receiver, |
| 2991 JSObject* holder, | 3184 Handle<JSObject> holder, |
| 2992 int index) { | 3185 int index) { |
| 2993 // ----------- S t a t e ------------- | 3186 // ----------- S t a t e ------------- |
| 2994 // -- ra : return address | 3187 // -- ra : return address |
| 2995 // -- a0 : key | 3188 // -- a0 : key |
| 2996 // -- a1 : receiver | 3189 // -- a1 : receiver |
| 2997 // ----------------------------------- | 3190 // ----------------------------------- |
| 2998 Label miss; | 3191 Label miss; |
| 2999 | 3192 |
| 3000 // Check the key is the cached one. | 3193 // Check the key is the cached one. |
| 3001 __ Branch(&miss, ne, a0, Operand(Handle<String>(name))); | 3194 __ Branch(&miss, ne, a0, Operand(name)); |
| 3002 | 3195 |
| 3003 GenerateLoadField(receiver, holder, a1, a2, a3, t0, index, name, &miss); | 3196 GenerateLoadField(receiver, holder, a1, a2, a3, t0, index, name, &miss); |
| 3004 __ bind(&miss); | 3197 __ bind(&miss); |
| 3005 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3198 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3006 | 3199 |
| 3007 return GetCode(FIELD, name); | 3200 return GetCode(FIELD, name); |
| 3008 } | 3201 } |
| 3009 | 3202 |
| 3010 | 3203 |
| 3011 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( | 3204 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3026 MaybeObject* result = GenerateLoadCallback(receiver, holder, a1, a0, a2, a3, | 3219 MaybeObject* result = GenerateLoadCallback(receiver, holder, a1, a0, a2, a3, |
| 3027 t0, callback, name, &miss); | 3220 t0, callback, name, &miss); |
| 3028 if (result->IsFailure()) { | 3221 if (result->IsFailure()) { |
| 3029 miss.Unuse(); | 3222 miss.Unuse(); |
| 3030 return result; | 3223 return result; |
| 3031 } | 3224 } |
| 3032 | 3225 |
| 3033 __ bind(&miss); | 3226 __ bind(&miss); |
| 3034 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3227 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3035 | 3228 |
| 3036 return GetCode(CALLBACKS, name); | 3229 return TryGetCode(CALLBACKS, name); |
| 3037 } | 3230 } |
| 3038 | 3231 |
| 3039 | 3232 |
| 3040 MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name, | 3233 Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant( |
| 3041 JSObject* receiver, | 3234 Handle<String> name, |
| 3042 JSObject* holder, | 3235 Handle<JSObject> receiver, |
| 3043 Object* value) { | 3236 Handle<JSObject> holder, |
| 3237 Handle<Object> value) { |
| 3044 // ----------- S t a t e ------------- | 3238 // ----------- S t a t e ------------- |
| 3045 // -- ra : return address | 3239 // -- ra : return address |
| 3046 // -- a0 : key | 3240 // -- a0 : key |
| 3047 // -- a1 : receiver | 3241 // -- a1 : receiver |
| 3048 // ----------------------------------- | 3242 // ----------------------------------- |
| 3049 Label miss; | 3243 Label miss; |
| 3050 | 3244 |
| 3051 // Check the key is the cached one. | 3245 // Check the key is the cached one. |
| 3052 __ Branch(&miss, ne, a0, Operand(Handle<String>(name))); | 3246 __ Branch(&miss, ne, a0, Operand(name)); |
| 3053 | 3247 |
| 3054 GenerateLoadConstant(receiver, holder, a1, a2, a3, t0, value, name, &miss); | 3248 GenerateLoadConstant(receiver, holder, a1, a2, a3, t0, value, name, &miss); |
| 3055 __ bind(&miss); | 3249 __ bind(&miss); |
| 3056 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3250 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3057 | 3251 |
| 3058 // Return the generated code. | 3252 // Return the generated code. |
| 3059 return GetCode(CONSTANT_FUNCTION, name); | 3253 return GetCode(CONSTANT_FUNCTION, name); |
| 3060 } | 3254 } |
| 3061 | 3255 |
| 3062 | 3256 |
| 3063 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 3257 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
| 3064 JSObject* holder, | 3258 JSObject* holder, |
| 3065 String* name) { | 3259 String* name) { |
| 3066 // ----------- S t a t e ------------- | 3260 // ----------- S t a t e ------------- |
| 3067 // -- ra : return address | 3261 // -- ra : return address |
| 3068 // -- a0 : key | 3262 // -- a0 : key |
| 3069 // -- a1 : receiver | 3263 // -- a1 : receiver |
| 3070 // ----------------------------------- | 3264 // ----------------------------------- |
| 3071 Label miss; | 3265 Label miss; |
| 3072 | 3266 |
| 3073 // Check the key is the cached one. | 3267 // Check the key is the cached one. |
| 3074 __ Branch(&miss, ne, a0, Operand(Handle<String>(name))); | 3268 __ Branch(&miss, ne, a0, Operand(Handle<String>(name))); |
| 3075 | 3269 |
| 3076 LookupResult lookup; | 3270 LookupResult lookup(isolate()); |
| 3077 LookupPostInterceptor(holder, name, &lookup); | 3271 LookupPostInterceptor(holder, name, &lookup); |
| 3078 GenerateLoadInterceptor(receiver, | 3272 GenerateLoadInterceptor(receiver, |
| 3079 holder, | 3273 holder, |
| 3080 &lookup, | 3274 &lookup, |
| 3081 a1, | 3275 a1, |
| 3082 a0, | 3276 a0, |
| 3083 a2, | 3277 a2, |
| 3084 a3, | 3278 a3, |
| 3085 t0, | 3279 t0, |
| 3086 name, | 3280 name, |
| 3087 &miss); | 3281 &miss); |
| 3088 __ bind(&miss); | 3282 __ bind(&miss); |
| 3089 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3283 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3090 | 3284 |
| 3091 return GetCode(INTERCEPTOR, name); | 3285 return TryGetCode(INTERCEPTOR, name); |
| 3092 } | 3286 } |
| 3093 | 3287 |
| 3094 | 3288 |
| 3095 MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { | 3289 Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( |
| 3290 Handle<String> name) { |
| 3096 // ----------- S t a t e ------------- | 3291 // ----------- S t a t e ------------- |
| 3097 // -- ra : return address | 3292 // -- ra : return address |
| 3098 // -- a0 : key | 3293 // -- a0 : key |
| 3099 // -- a1 : receiver | 3294 // -- a1 : receiver |
| 3100 // ----------------------------------- | 3295 // ----------------------------------- |
| 3101 Label miss; | 3296 Label miss; |
| 3102 | 3297 |
| 3103 // Check the key is the cached one. | 3298 // Check the key is the cached one. |
| 3104 __ Branch(&miss, ne, a0, Operand(Handle<String>(name))); | 3299 __ Branch(&miss, ne, a0, Operand(name)); |
| 3105 | 3300 |
| 3106 GenerateLoadArrayLength(masm(), a1, a2, &miss); | 3301 GenerateLoadArrayLength(masm(), a1, a2, &miss); |
| 3107 __ bind(&miss); | 3302 __ bind(&miss); |
| 3108 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3303 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3109 | 3304 |
| 3110 return GetCode(CALLBACKS, name); | 3305 return GetCode(CALLBACKS, name); |
| 3111 } | 3306 } |
| 3112 | 3307 |
| 3113 | 3308 |
| 3114 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { | 3309 Handle<Code> KeyedLoadStubCompiler::CompileLoadStringLength( |
| 3310 Handle<String> name) { |
| 3115 // ----------- S t a t e ------------- | 3311 // ----------- S t a t e ------------- |
| 3116 // -- ra : return address | 3312 // -- ra : return address |
| 3117 // -- a0 : key | 3313 // -- a0 : key |
| 3118 // -- a1 : receiver | 3314 // -- a1 : receiver |
| 3119 // ----------------------------------- | 3315 // ----------------------------------- |
| 3120 Label miss; | 3316 Label miss; |
| 3121 | 3317 |
| 3122 Counters* counters = masm()->isolate()->counters(); | 3318 Counters* counters = masm()->isolate()->counters(); |
| 3123 __ IncrementCounter(counters->keyed_load_string_length(), 1, a2, a3); | 3319 __ IncrementCounter(counters->keyed_load_string_length(), 1, a2, a3); |
| 3124 | 3320 |
| 3125 // Check the key is the cached one. | 3321 // Check the key is the cached one. |
| 3126 __ Branch(&miss, ne, a0, Operand(Handle<String>(name))); | 3322 __ Branch(&miss, ne, a0, Operand(name)); |
| 3127 | 3323 |
| 3128 GenerateLoadStringLength(masm(), a1, a2, a3, &miss, true); | 3324 GenerateLoadStringLength(masm(), a1, a2, a3, &miss, true); |
| 3129 __ bind(&miss); | 3325 __ bind(&miss); |
| 3130 __ DecrementCounter(counters->keyed_load_string_length(), 1, a2, a3); | 3326 __ DecrementCounter(counters->keyed_load_string_length(), 1, a2, a3); |
| 3131 | 3327 |
| 3132 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3328 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3133 | 3329 |
| 3134 return GetCode(CALLBACKS, name); | 3330 return GetCode(CALLBACKS, name); |
| 3135 } | 3331 } |
| 3136 | 3332 |
| 3137 | 3333 |
| 3138 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { | 3334 Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype( |
| 3335 Handle<String> name) { |
| 3139 // ----------- S t a t e ------------- | 3336 // ----------- S t a t e ------------- |
| 3140 // -- ra : return address | 3337 // -- ra : return address |
| 3141 // -- a0 : key | 3338 // -- a0 : key |
| 3142 // -- a1 : receiver | 3339 // -- a1 : receiver |
| 3143 // ----------------------------------- | 3340 // ----------------------------------- |
| 3144 Label miss; | 3341 Label miss; |
| 3145 | 3342 |
| 3146 Counters* counters = masm()->isolate()->counters(); | 3343 Counters* counters = masm()->isolate()->counters(); |
| 3147 __ IncrementCounter(counters->keyed_load_function_prototype(), 1, a2, a3); | 3344 __ IncrementCounter(counters->keyed_load_function_prototype(), 1, a2, a3); |
| 3148 | 3345 |
| 3149 // Check the name hasn't changed. | 3346 // Check the name hasn't changed. |
| 3150 __ Branch(&miss, ne, a0, Operand(Handle<String>(name))); | 3347 __ Branch(&miss, ne, a0, Operand(name)); |
| 3151 | 3348 |
| 3152 GenerateLoadFunctionPrototype(masm(), a1, a2, a3, &miss); | 3349 GenerateLoadFunctionPrototype(masm(), a1, a2, a3, &miss); |
| 3153 __ bind(&miss); | 3350 __ bind(&miss); |
| 3154 __ DecrementCounter(counters->keyed_load_function_prototype(), 1, a2, a3); | 3351 __ DecrementCounter(counters->keyed_load_function_prototype(), 1, a2, a3); |
| 3155 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3352 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3156 | 3353 |
| 3157 return GetCode(CALLBACKS, name); | 3354 return GetCode(CALLBACKS, name); |
| 3158 } | 3355 } |
| 3159 | 3356 |
| 3160 | 3357 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3171 __ DispatchMap(a1, | 3368 __ DispatchMap(a1, |
| 3172 a2, | 3369 a2, |
| 3173 Handle<Map>(receiver_map), | 3370 Handle<Map>(receiver_map), |
| 3174 Handle<Code>(stub), | 3371 Handle<Code>(stub), |
| 3175 DO_SMI_CHECK); | 3372 DO_SMI_CHECK); |
| 3176 | 3373 |
| 3177 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); | 3374 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); |
| 3178 __ Jump(ic, RelocInfo::CODE_TARGET); | 3375 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 3179 | 3376 |
| 3180 // Return the generated code. | 3377 // Return the generated code. |
| 3181 return GetCode(NORMAL, NULL); | 3378 return TryGetCode(NORMAL, NULL); |
| 3182 } | 3379 } |
| 3183 | 3380 |
| 3184 | 3381 |
| 3185 MaybeObject* KeyedLoadStubCompiler::CompileLoadPolymorphic( | 3382 MaybeObject* KeyedLoadStubCompiler::CompileLoadPolymorphic( |
| 3186 MapList* receiver_maps, | 3383 MapList* receiver_maps, |
| 3187 CodeList* handler_ics) { | 3384 CodeList* handler_ics) { |
| 3188 // ----------- S t a t e ------------- | 3385 // ----------- S t a t e ------------- |
| 3189 // -- ra : return address | 3386 // -- ra : return address |
| 3190 // -- a0 : key | 3387 // -- a0 : key |
| 3191 // -- a1 : receiver | 3388 // -- a1 : receiver |
| 3192 // ----------------------------------- | 3389 // ----------------------------------- |
| 3193 Label miss; | 3390 Label miss; |
| 3194 __ JumpIfSmi(a1, &miss); | 3391 __ JumpIfSmi(a1, &miss); |
| 3195 | 3392 |
| 3196 int receiver_count = receiver_maps->length(); | 3393 int receiver_count = receiver_maps->length(); |
| 3197 __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset)); | 3394 __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset)); |
| 3198 for (int current = 0; current < receiver_count; ++current) { | 3395 for (int current = 0; current < receiver_count; ++current) { |
| 3199 Handle<Map> map(receiver_maps->at(current)); | 3396 Handle<Map> map(receiver_maps->at(current)); |
| 3200 Handle<Code> code(handler_ics->at(current)); | 3397 Handle<Code> code(handler_ics->at(current)); |
| 3201 __ Jump(code, RelocInfo::CODE_TARGET, eq, a2, Operand(map)); | 3398 __ Jump(code, RelocInfo::CODE_TARGET, eq, a2, Operand(map)); |
| 3202 } | 3399 } |
| 3203 | 3400 |
| 3204 __ bind(&miss); | 3401 __ bind(&miss); |
| 3205 Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss(); | 3402 Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss(); |
| 3206 __ Jump(miss_ic, RelocInfo::CODE_TARGET); | 3403 __ Jump(miss_ic, RelocInfo::CODE_TARGET); |
| 3207 | 3404 |
| 3208 // Return the generated code. | 3405 // Return the generated code. |
| 3209 return GetCode(NORMAL, NULL, MEGAMORPHIC); | 3406 return TryGetCode(NORMAL, NULL, MEGAMORPHIC); |
| 3210 } | 3407 } |
| 3211 | 3408 |
| 3212 | 3409 |
| 3213 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, | 3410 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, |
| 3214 int index, | 3411 int index, |
| 3215 Map* transition, | 3412 Map* transition, |
| 3216 String* name) { | 3413 String* name) { |
| 3217 // ----------- S t a t e ------------- | 3414 // ----------- S t a t e ------------- |
| 3218 // -- a0 : value | 3415 // -- a0 : value |
| 3219 // -- a1 : key | 3416 // -- a1 : key |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3292 | 3489 |
| 3293 int receiver_count = receiver_maps->length(); | 3490 int receiver_count = receiver_maps->length(); |
| 3294 __ lw(a3, FieldMemOperand(a2, HeapObject::kMapOffset)); | 3491 __ lw(a3, FieldMemOperand(a2, HeapObject::kMapOffset)); |
| 3295 for (int i = 0; i < receiver_count; ++i) { | 3492 for (int i = 0; i < receiver_count; ++i) { |
| 3296 Handle<Map> map(receiver_maps->at(i)); | 3493 Handle<Map> map(receiver_maps->at(i)); |
| 3297 Handle<Code> code(handler_stubs->at(i)); | 3494 Handle<Code> code(handler_stubs->at(i)); |
| 3298 if (transitioned_maps->at(i) == NULL) { | 3495 if (transitioned_maps->at(i) == NULL) { |
| 3299 __ Jump(code, RelocInfo::CODE_TARGET, eq, a3, Operand(map)); | 3496 __ Jump(code, RelocInfo::CODE_TARGET, eq, a3, Operand(map)); |
| 3300 } else { | 3497 } else { |
| 3301 Label next_map; | 3498 Label next_map; |
| 3302 __ Branch(&next_map, eq, a3, Operand(map)); | 3499 __ Branch(&next_map, ne, a3, Operand(map)); |
| 3303 __ li(t0, Operand(Handle<Map>(transitioned_maps->at(i)))); | 3500 __ li(a3, Operand(Handle<Map>(transitioned_maps->at(i)))); |
| 3304 __ Jump(code, RelocInfo::CODE_TARGET); | 3501 __ Jump(code, RelocInfo::CODE_TARGET); |
| 3305 __ bind(&next_map); | 3502 __ bind(&next_map); |
| 3306 } | 3503 } |
| 3307 } | 3504 } |
| 3308 | 3505 |
| 3309 __ bind(&miss); | 3506 __ bind(&miss); |
| 3310 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 3507 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3311 __ Jump(miss_ic, RelocInfo::CODE_TARGET); | 3508 __ Jump(miss_ic, RelocInfo::CODE_TARGET); |
| 3312 | 3509 |
| 3313 // Return the generated code. | 3510 // Return the generated code. |
| (...skipping 1216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4530 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 4727 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 4531 __ Jump(ic_miss, RelocInfo::CODE_TARGET); | 4728 __ Jump(ic_miss, RelocInfo::CODE_TARGET); |
| 4532 } | 4729 } |
| 4533 | 4730 |
| 4534 | 4731 |
| 4535 #undef __ | 4732 #undef __ |
| 4536 | 4733 |
| 4537 } } // namespace v8::internal | 4734 } } // namespace v8::internal |
| 4538 | 4735 |
| 4539 #endif // V8_TARGET_ARCH_MIPS | 4736 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |