| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 // Update primary cache. | 93 // Update primary cache. |
| 94 primary->key = name; | 94 primary->key = name; |
| 95 primary->value = code; | 95 primary->value = code; |
| 96 primary->map = map; | 96 primary->map = map; |
| 97 isolate()->counters()->megamorphic_stub_cache_updates()->Increment(); | 97 isolate()->counters()->megamorphic_stub_cache_updates()->Increment(); |
| 98 return code; | 98 return code; |
| 99 } | 99 } |
| 100 | 100 |
| 101 | 101 |
| 102 Handle<Code> StubCache::FindIC(Handle<Name> name, | 102 Handle<Code> StubCache::FindIC(Handle<Name> name, |
| 103 Handle<Map> stub_holder_map, | 103 Handle<Map> stub_holder, |
| 104 Code::Kind kind, | 104 Code::Kind kind, |
| 105 Code::ExtraICState extra_state, | 105 Code::ExtraICState extra_state, |
| 106 InlineCacheHolderFlag cache_holder) { | 106 InlineCacheHolderFlag cache_holder) { |
| 107 Code::Flags flags = Code::ComputeMonomorphicFlags( | 107 Code::Flags flags = Code::ComputeMonomorphicFlags( |
| 108 kind, extra_state, cache_holder); | 108 kind, extra_state, cache_holder); |
| 109 Handle<Object> probe(stub_holder_map->FindInCodeCache(*name, flags), | 109 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_); |
| 110 isolate_); | |
| 111 if (probe->IsCode()) return Handle<Code>::cast(probe); | 110 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 112 return Handle<Code>::null(); | 111 return Handle<Code>::null(); |
| 113 } | 112 } |
| 114 | 113 |
| 115 | 114 |
| 116 Handle<Code> StubCache::FindHandler(Handle<Name> name, | 115 Handle<Code> StubCache::FindHandler(Handle<Name> name, |
| 117 Handle<HeapObject> stub_holder, | 116 Handle<Map> stub_holder, |
| 118 Code::Kind kind, | 117 Code::Kind kind, |
| 119 InlineCacheHolderFlag cache_holder, | 118 InlineCacheHolderFlag cache_holder, |
| 120 StrictModeFlag strict_mode) { | 119 StrictModeFlag strict_mode) { |
| 121 Code::ExtraICState extra_ic_state = Code::kNoExtraICState; | 120 Code::ExtraICState extra_ic_state = Code::kNoExtraICState; |
| 122 if (kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC) { | 121 if (kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC) { |
| 123 extra_ic_state = Code::ComputeExtraICState( | 122 extra_ic_state = Code::ComputeExtraICState( |
| 124 STANDARD_STORE, strict_mode); | 123 STANDARD_STORE, strict_mode); |
| 125 } | 124 } |
| 126 Code::Flags flags = Code::ComputeMonomorphicFlags( | 125 Code::Flags flags = Code::ComputeMonomorphicFlags( |
| 127 Code::HANDLER, extra_ic_state, cache_holder, Code::NORMAL, kind); | 126 Code::HANDLER, extra_ic_state, cache_holder, Code::NORMAL, kind); |
| 128 | 127 |
| 129 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), | 128 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_); |
| 130 isolate_); | |
| 131 if (probe->IsCode()) return Handle<Code>::cast(probe); | 129 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 132 return Handle<Code>::null(); | 130 return Handle<Code>::null(); |
| 133 } | 131 } |
| 134 | 132 |
| 135 | 133 |
| 136 Handle<Code> StubCache::ComputeMonomorphicIC(Handle<Name> name, | 134 Handle<Code> StubCache::ComputeMonomorphicIC(Handle<Name> name, |
| 137 Handle<Type> type, | 135 Handle<Type> type, |
| 138 Handle<Code> handler, | 136 Handle<Code> handler, |
| 139 StrictModeFlag strict_mode) { | 137 StrictModeFlag strict_mode) { |
| 140 Code::Kind kind = handler->handler_kind(); | 138 Code::Kind kind = handler->handler_kind(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 166 KeyedStoreStubCompiler ic_compiler(isolate(), strict_mode, STANDARD_STORE); | 164 KeyedStoreStubCompiler ic_compiler(isolate(), strict_mode, STANDARD_STORE); |
| 167 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); | 165 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); |
| 168 } | 166 } |
| 169 | 167 |
| 170 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic); | 168 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic); |
| 171 return ic; | 169 return ic; |
| 172 } | 170 } |
| 173 | 171 |
| 174 | 172 |
| 175 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, | 173 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, |
| 176 Handle<Object> object) { | 174 Handle<Type> type) { |
| 177 InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object); | 175 InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type); |
| 178 Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder( | 176 Handle<Map> stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate()); |
| 179 isolate(), *object, cache_holder)); | 177 // If no dictionary mode objects are present in the prototype chain, the load |
| 180 // If no global objects are present in the prototype chain, the load | 178 // nonexistent IC stub can be shared for all names for a given map and we use |
| 181 // nonexistent IC stub can be shared for all names for a given map | 179 // the empty string for the map cache in that case. If there are dictionary |
| 182 // and we use the empty string for the map cache in that case. If | 180 // mode objects involved, we need to do negative lookups in the stub and |
| 183 // there are global objects involved, we need to check global | 181 // therefore the stub will be specific to the name. |
| 184 // property cells in the stub and therefore the stub will be | 182 Handle<Map> current_map = stub_holder; |
| 185 // specific to the name. | 183 Handle<Name> cache_name = current_map->is_dictionary_map() |
| 186 Handle<Name> cache_name = factory()->empty_string(); | 184 ? name : Handle<Name>::cast(isolate()->factory()->empty_string()); |
| 187 Handle<JSObject> current; | 185 Handle<Object> next(current_map->prototype(), isolate()); |
| 188 Handle<Object> next = stub_holder; | 186 Handle<JSObject> last = Handle<JSObject>::null(); |
| 189 Handle<JSGlobalObject> global; | 187 while (!next->IsNull()) { |
| 190 do { | 188 last = Handle<JSObject>::cast(next); |
| 191 current = Handle<JSObject>::cast(next); | 189 next = handle(current_map->prototype(), isolate()); |
| 192 next = Handle<Object>(current->GetPrototype(), isolate_); | 190 current_map = handle(Handle<HeapObject>::cast(next)->map()); |
| 193 if (current->IsJSGlobalObject()) { | 191 if (current_map->is_dictionary_map()) cache_name = name; |
| 194 global = Handle<JSGlobalObject>::cast(current); | 192 } |
| 195 cache_name = name; | |
| 196 } else if (!current->HasFastProperties()) { | |
| 197 cache_name = name; | |
| 198 } | |
| 199 } while (!next->IsNull()); | |
| 200 | 193 |
| 201 // Compile the stub that is either shared for all names or | 194 // Compile the stub that is either shared for all names or |
| 202 // name specific if there are global objects involved. | 195 // name specific if there are global objects involved. |
| 203 Handle<Code> handler = FindHandler( | 196 Handle<Code> handler = FindHandler( |
| 204 cache_name, stub_holder, Code::LOAD_IC, cache_holder); | 197 cache_name, stub_holder, Code::LOAD_IC, flag); |
| 205 if (!handler.is_null()) return handler; | 198 if (!handler.is_null()) return handler; |
| 206 | 199 |
| 207 LoadStubCompiler compiler(isolate_, cache_holder); | 200 LoadStubCompiler compiler(isolate_, flag); |
| 208 handler = | 201 handler = compiler.CompileLoadNonexistent(type, last, cache_name); |
| 209 compiler.CompileLoadNonexistent(object, current, cache_name, global); | 202 Map::UpdateCodeCache(stub_holder, cache_name, handler); |
| 210 HeapObject::UpdateMapCodeCache(stub_holder, cache_name, handler); | |
| 211 return handler; | 203 return handler; |
| 212 } | 204 } |
| 213 | 205 |
| 214 | 206 |
| 215 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { | 207 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { |
| 216 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); | 208 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); |
| 217 Handle<Name> name = | 209 Handle<Name> name = |
| 218 isolate()->factory()->KeyedLoadElementMonomorphic_string(); | 210 isolate()->factory()->KeyedLoadElementMonomorphic_string(); |
| 219 | 211 |
| 220 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); | 212 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); |
| (...skipping 907 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1128 if (lookup->IsFound()) return; | 1120 if (lookup->IsFound()) return; |
| 1129 if (holder->GetPrototype()->IsNull()) return; | 1121 if (holder->GetPrototype()->IsNull()) return; |
| 1130 holder->GetPrototype()->Lookup(*name, lookup); | 1122 holder->GetPrototype()->Lookup(*name, lookup); |
| 1131 } | 1123 } |
| 1132 | 1124 |
| 1133 | 1125 |
| 1134 #define __ ACCESS_MASM(masm()) | 1126 #define __ ACCESS_MASM(masm()) |
| 1135 | 1127 |
| 1136 | 1128 |
| 1137 Register LoadStubCompiler::HandlerFrontendHeader( | 1129 Register LoadStubCompiler::HandlerFrontendHeader( |
| 1138 Handle<Object> object, | 1130 Handle<Type> type, |
| 1139 Register object_reg, | 1131 Register object_reg, |
| 1140 Handle<JSObject> holder, | 1132 Handle<JSObject> holder, |
| 1141 Handle<Name> name, | 1133 Handle<Name> name, |
| 1142 Label* miss) { | 1134 Label* miss) { |
| 1143 Handle<JSObject> receiver; | |
| 1144 PrototypeCheckType check_type = CHECK_ALL_MAPS; | 1135 PrototypeCheckType check_type = CHECK_ALL_MAPS; |
| 1145 int function_index = -1; | 1136 int function_index = -1; |
| 1146 if (object->IsJSObject()) { | 1137 if (type->Is(Type::String())) { |
| 1147 receiver = Handle<JSObject>::cast(object); | 1138 function_index = Context::STRING_FUNCTION_INDEX; |
| 1139 } else if (type->Is(Type::Symbol())) { |
| 1140 function_index = Context::SYMBOL_FUNCTION_INDEX; |
| 1141 } else if (type->Is(Type::Number())) { |
| 1142 function_index = Context::NUMBER_FUNCTION_INDEX; |
| 1143 } else if (type->Is(Type::Boolean())) { |
| 1144 // Booleans use the generic oddball map, so an additional check is needed to |
| 1145 // ensure the receiver is really a boolean. |
| 1146 GenerateBooleanCheck(object_reg, miss); |
| 1147 function_index = Context::BOOLEAN_FUNCTION_INDEX; |
| 1148 } else { |
| 1148 check_type = SKIP_RECEIVER; | 1149 check_type = SKIP_RECEIVER; |
| 1149 } else { | 1150 } |
| 1150 if (object->IsString()) { | |
| 1151 function_index = Context::STRING_FUNCTION_INDEX; | |
| 1152 } else if (object->IsSymbol()) { | |
| 1153 function_index = Context::SYMBOL_FUNCTION_INDEX; | |
| 1154 } else if (object->IsNumber()) { | |
| 1155 function_index = Context::NUMBER_FUNCTION_INDEX; | |
| 1156 } else { | |
| 1157 ASSERT(object->IsBoolean()); | |
| 1158 // Booleans use the generic oddball map, so an additional check is | |
| 1159 // needed to ensure the receiver is really a boolean. | |
| 1160 GenerateBooleanCheck(object_reg, miss); | |
| 1161 function_index = Context::BOOLEAN_FUNCTION_INDEX; | |
| 1162 } | |
| 1163 | 1151 |
| 1152 if (check_type == CHECK_ALL_MAPS) { |
| 1164 GenerateDirectLoadGlobalFunctionPrototype( | 1153 GenerateDirectLoadGlobalFunctionPrototype( |
| 1165 masm(), function_index, scratch1(), miss); | 1154 masm(), function_index, scratch1(), miss); |
| 1166 receiver = handle(JSObject::cast(object->GetPrototype(isolate()))); | 1155 Object* function = isolate()->native_context()->get(function_index); |
| 1156 Object* prototype = JSFunction::cast(function)->instance_prototype(); |
| 1157 type = IC::CurrentTypeOf(handle(prototype, isolate()), isolate()); |
| 1167 object_reg = scratch1(); | 1158 object_reg = scratch1(); |
| 1168 } | 1159 } |
| 1169 | 1160 |
| 1170 // Check that the maps starting from the prototype haven't changed. | 1161 // Check that the maps starting from the prototype haven't changed. |
| 1171 return CheckPrototypes( | 1162 return CheckPrototypes( |
| 1172 IC::CurrentTypeOf(receiver, isolate()), object_reg, holder, | 1163 type, object_reg, holder, scratch1(), scratch2(), scratch3(), |
| 1173 scratch1(), scratch2(), scratch3(), name, miss, check_type); | 1164 name, miss, check_type); |
| 1174 } | 1165 } |
| 1175 | 1166 |
| 1176 | 1167 |
| 1177 // HandlerFrontend for store uses the name register. It has to be restored | 1168 // HandlerFrontend for store uses the name register. It has to be restored |
| 1178 // before a miss. | 1169 // before a miss. |
| 1179 Register StoreStubCompiler::HandlerFrontendHeader( | 1170 Register StoreStubCompiler::HandlerFrontendHeader( |
| 1180 Handle<Object> object, | 1171 Handle<Type> type, |
| 1181 Register object_reg, | 1172 Register object_reg, |
| 1182 Handle<JSObject> holder, | 1173 Handle<JSObject> holder, |
| 1183 Handle<Name> name, | 1174 Handle<Name> name, |
| 1184 Label* miss) { | 1175 Label* miss) { |
| 1185 return CheckPrototypes( | 1176 return CheckPrototypes(type, object_reg, holder, this->name(), |
| 1186 IC::CurrentTypeOf(object, isolate()), object_reg, holder, this->name(), | 1177 scratch1(), scratch2(), name, miss, SKIP_RECEIVER); |
| 1187 scratch1(), scratch2(), name, miss, SKIP_RECEIVER); | |
| 1188 } | 1178 } |
| 1189 | 1179 |
| 1190 | 1180 |
| 1191 bool BaseLoadStoreStubCompiler::IncludesNumberType(TypeHandleList* types) { | 1181 bool BaseLoadStoreStubCompiler::IncludesNumberType(TypeHandleList* types) { |
| 1192 for (int i = 0; i < types->length(); ++i) { | 1182 for (int i = 0; i < types->length(); ++i) { |
| 1193 if (types->at(i)->Is(Type::Number())) return true; | 1183 if (types->at(i)->Is(Type::Number())) return true; |
| 1194 } | 1184 } |
| 1195 return false; | 1185 return false; |
| 1196 } | 1186 } |
| 1197 | 1187 |
| 1198 | 1188 |
| 1199 Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<Object> object, | 1189 Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<Type> type, |
| 1200 Register object_reg, | 1190 Register object_reg, |
| 1201 Handle<JSObject> holder, | 1191 Handle<JSObject> holder, |
| 1202 Handle<Name> name) { | 1192 Handle<Name> name) { |
| 1203 Label miss; | 1193 Label miss; |
| 1204 | 1194 |
| 1205 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); | 1195 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); |
| 1206 | 1196 |
| 1207 HandlerFrontendFooter(name, &miss); | 1197 HandlerFrontendFooter(name, &miss); |
| 1208 | 1198 |
| 1209 return reg; | 1199 return reg; |
| 1210 } | 1200 } |
| 1211 | 1201 |
| 1212 | 1202 |
| 1213 void LoadStubCompiler::NonexistentHandlerFrontend( | 1203 void LoadStubCompiler::NonexistentHandlerFrontend(Handle<Type> type, |
| 1214 Handle<Object> object, | 1204 Handle<JSObject> last, |
| 1215 Handle<JSObject> last, | 1205 Handle<Name> name) { |
| 1216 Handle<Name> name, | |
| 1217 Handle<JSGlobalObject> global) { | |
| 1218 Label miss; | 1206 Label miss; |
| 1219 | 1207 |
| 1220 Register holder = HandlerFrontendHeader( | 1208 Register holder; |
| 1221 object, receiver(), last, name, &miss); | 1209 Handle<Map> last_map; |
| 1210 if (last.is_null()) { |
| 1211 holder = receiver(); |
| 1212 last_map = IC::TypeToMap(*type, isolate()); |
| 1213 // If |type| has null as its prototype, |last| is Handle<JSObject>::null(). |
| 1214 ASSERT(last_map->prototype() == isolate()->heap()->null_value()); |
| 1215 } else { |
| 1216 holder = HandlerFrontendHeader(type, receiver(), last, name, &miss); |
| 1217 last_map = handle(last->map()); |
| 1218 } |
| 1222 | 1219 |
| 1223 if (!last->HasFastProperties() && | 1220 if (last_map->is_dictionary_map() && |
| 1224 !last->IsJSGlobalObject() && | 1221 !last_map->IsJSGlobalObjectMap() && |
| 1225 !last->IsJSGlobalProxy()) { | 1222 !last_map->IsJSGlobalProxyMap()) { |
| 1226 if (!name->IsUniqueName()) { | 1223 if (!name->IsUniqueName()) { |
| 1227 ASSERT(name->IsString()); | 1224 ASSERT(name->IsString()); |
| 1228 name = factory()->InternalizeString(Handle<String>::cast(name)); | 1225 name = factory()->InternalizeString(Handle<String>::cast(name)); |
| 1229 } | 1226 } |
| 1230 ASSERT(last->property_dictionary()->FindEntry(*name) == | 1227 ASSERT(last.is_null() || |
| 1231 NameDictionary::kNotFound); | 1228 last->property_dictionary()->FindEntry(*name) == |
| 1229 NameDictionary::kNotFound); |
| 1232 GenerateDictionaryNegativeLookup(masm(), &miss, holder, name, | 1230 GenerateDictionaryNegativeLookup(masm(), &miss, holder, name, |
| 1233 scratch2(), scratch3()); | 1231 scratch2(), scratch3()); |
| 1234 } | 1232 } |
| 1235 | 1233 |
| 1236 // If the last object in the prototype chain is a global object, | 1234 // If the last object in the prototype chain is a global object, |
| 1237 // check that the global property cell is empty. | 1235 // check that the global property cell is empty. |
| 1238 if (!global.is_null()) { | 1236 if (last_map->IsJSGlobalObjectMap()) { |
| 1237 Handle<JSGlobalObject> global = last.is_null() |
| 1238 ? Handle<JSGlobalObject>::cast(type->AsConstant()) |
| 1239 : Handle<JSGlobalObject>::cast(last); |
| 1239 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); | 1240 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
| 1240 } | 1241 } |
| 1241 | 1242 |
| 1242 HandlerFrontendFooter(name, &miss); | 1243 HandlerFrontendFooter(name, &miss); |
| 1243 } | 1244 } |
| 1244 | 1245 |
| 1245 | 1246 |
| 1246 Handle<Code> LoadStubCompiler::CompileLoadField( | 1247 Handle<Code> LoadStubCompiler::CompileLoadField( |
| 1247 Handle<Object> object, | 1248 Handle<Type> type, |
| 1248 Handle<JSObject> holder, | 1249 Handle<JSObject> holder, |
| 1249 Handle<Name> name, | 1250 Handle<Name> name, |
| 1250 PropertyIndex field, | 1251 PropertyIndex field, |
| 1251 Representation representation) { | 1252 Representation representation) { |
| 1252 Label miss; | 1253 Label miss; |
| 1253 | 1254 |
| 1254 Register reg = HandlerFrontendHeader(object, receiver(), holder, name, &miss); | 1255 Register reg = HandlerFrontendHeader(type, receiver(), holder, name, &miss); |
| 1255 | 1256 |
| 1256 GenerateLoadField(reg, holder, field, representation); | 1257 GenerateLoadField(reg, holder, field, representation); |
| 1257 | 1258 |
| 1258 __ bind(&miss); | 1259 __ bind(&miss); |
| 1259 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1260 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1260 | 1261 |
| 1261 // Return the generated code. | 1262 // Return the generated code. |
| 1262 return GetCode(kind(), Code::FAST, name); | 1263 return GetCode(kind(), Code::FAST, name); |
| 1263 } | 1264 } |
| 1264 | 1265 |
| 1265 | 1266 |
| 1266 Handle<Code> LoadStubCompiler::CompileLoadConstant( | 1267 Handle<Code> LoadStubCompiler::CompileLoadConstant( |
| 1267 Handle<Object> object, | 1268 Handle<Type> type, |
| 1268 Handle<JSObject> holder, | 1269 Handle<JSObject> holder, |
| 1269 Handle<Name> name, | 1270 Handle<Name> name, |
| 1270 Handle<Object> value) { | 1271 Handle<Object> value) { |
| 1271 HandlerFrontend(object, receiver(), holder, name); | 1272 HandlerFrontend(type, receiver(), holder, name); |
| 1272 GenerateLoadConstant(value); | 1273 GenerateLoadConstant(value); |
| 1273 | 1274 |
| 1274 // Return the generated code. | 1275 // Return the generated code. |
| 1275 return GetCode(kind(), Code::FAST, name); | 1276 return GetCode(kind(), Code::FAST, name); |
| 1276 } | 1277 } |
| 1277 | 1278 |
| 1278 | 1279 |
| 1279 Handle<Code> LoadStubCompiler::CompileLoadCallback( | 1280 Handle<Code> LoadStubCompiler::CompileLoadCallback( |
| 1280 Handle<Object> object, | 1281 Handle<Type> type, |
| 1281 Handle<JSObject> holder, | 1282 Handle<JSObject> holder, |
| 1282 Handle<Name> name, | 1283 Handle<Name> name, |
| 1283 Handle<ExecutableAccessorInfo> callback) { | 1284 Handle<ExecutableAccessorInfo> callback) { |
| 1284 Register reg = CallbackHandlerFrontend( | 1285 Register reg = CallbackHandlerFrontend( |
| 1285 object, receiver(), holder, name, callback); | 1286 type, receiver(), holder, name, callback); |
| 1286 GenerateLoadCallback(reg, callback); | 1287 GenerateLoadCallback(reg, callback); |
| 1287 | 1288 |
| 1288 // Return the generated code. | 1289 // Return the generated code. |
| 1289 return GetCode(kind(), Code::FAST, name); | 1290 return GetCode(kind(), Code::FAST, name); |
| 1290 } | 1291 } |
| 1291 | 1292 |
| 1292 | 1293 |
| 1293 Handle<Code> LoadStubCompiler::CompileLoadCallback( | 1294 Handle<Code> LoadStubCompiler::CompileLoadCallback( |
| 1294 Handle<Object> object, | 1295 Handle<Type> type, |
| 1295 Handle<JSObject> holder, | 1296 Handle<JSObject> holder, |
| 1296 Handle<Name> name, | 1297 Handle<Name> name, |
| 1297 const CallOptimization& call_optimization) { | 1298 const CallOptimization& call_optimization) { |
| 1298 ASSERT(call_optimization.is_simple_api_call()); | 1299 ASSERT(call_optimization.is_simple_api_call()); |
| 1299 Handle<JSFunction> callback = call_optimization.constant_function(); | 1300 Handle<JSFunction> callback = call_optimization.constant_function(); |
| 1300 CallbackHandlerFrontend(object, receiver(), holder, name, callback); | 1301 CallbackHandlerFrontend(type, receiver(), holder, name, callback); |
| 1301 GenerateLoadCallback(call_optimization); | 1302 GenerateLoadCallback(call_optimization); |
| 1302 | 1303 |
| 1303 // Return the generated code. | 1304 // Return the generated code. |
| 1304 return GetCode(kind(), Code::FAST, name); | 1305 return GetCode(kind(), Code::FAST, name); |
| 1305 } | 1306 } |
| 1306 | 1307 |
| 1307 | 1308 |
| 1308 Handle<Code> LoadStubCompiler::CompileLoadInterceptor( | 1309 Handle<Code> LoadStubCompiler::CompileLoadInterceptor( |
| 1309 Handle<Object> object, | 1310 Handle<Type> type, |
| 1310 Handle<JSObject> holder, | 1311 Handle<JSObject> holder, |
| 1311 Handle<Name> name) { | 1312 Handle<Name> name) { |
| 1312 LookupResult lookup(isolate()); | 1313 LookupResult lookup(isolate()); |
| 1313 LookupPostInterceptor(holder, name, &lookup); | 1314 LookupPostInterceptor(holder, name, &lookup); |
| 1314 | 1315 |
| 1315 Register reg = HandlerFrontend(object, receiver(), holder, name); | 1316 Register reg = HandlerFrontend(type, receiver(), holder, name); |
| 1316 // TODO(368): Compile in the whole chain: all the interceptors in | 1317 // TODO(368): Compile in the whole chain: all the interceptors in |
| 1317 // prototypes and ultimate answer. | 1318 // prototypes and ultimate answer. |
| 1318 GenerateLoadInterceptor(reg, object, holder, &lookup, name); | 1319 GenerateLoadInterceptor(reg, type, holder, &lookup, name); |
| 1319 | 1320 |
| 1320 // Return the generated code. | 1321 // Return the generated code. |
| 1321 return GetCode(kind(), Code::FAST, name); | 1322 return GetCode(kind(), Code::FAST, name); |
| 1322 } | 1323 } |
| 1323 | 1324 |
| 1324 | 1325 |
| 1325 void LoadStubCompiler::GenerateLoadPostInterceptor( | 1326 void LoadStubCompiler::GenerateLoadPostInterceptor( |
| 1326 Register interceptor_reg, | 1327 Register interceptor_reg, |
| 1327 Handle<JSObject> interceptor_holder, | 1328 Handle<JSObject> interceptor_holder, |
| 1328 Handle<Name> name, | 1329 Handle<Name> name, |
| 1329 LookupResult* lookup) { | 1330 LookupResult* lookup) { |
| 1330 Handle<JSObject> holder(lookup->holder()); | 1331 Handle<JSObject> holder(lookup->holder()); |
| 1331 if (lookup->IsField()) { | 1332 if (lookup->IsField()) { |
| 1332 PropertyIndex field = lookup->GetFieldIndex(); | 1333 PropertyIndex field = lookup->GetFieldIndex(); |
| 1333 if (interceptor_holder.is_identical_to(holder)) { | 1334 if (interceptor_holder.is_identical_to(holder)) { |
| 1334 GenerateLoadField( | 1335 GenerateLoadField( |
| 1335 interceptor_reg, holder, field, lookup->representation()); | 1336 interceptor_reg, holder, field, lookup->representation()); |
| 1336 } else { | 1337 } else { |
| 1337 // We found FIELD property in prototype chain of interceptor's holder. | 1338 // We found FIELD property in prototype chain of interceptor's holder. |
| 1338 // Retrieve a field from field's holder. | 1339 // Retrieve a field from field's holder. |
| 1339 Register reg = HandlerFrontend( | 1340 Register reg = HandlerFrontend( |
| 1340 interceptor_holder, interceptor_reg, holder, name); | 1341 IC::CurrentTypeOf(interceptor_holder, isolate()), |
| 1342 interceptor_reg, holder, name); |
| 1341 GenerateLoadField( | 1343 GenerateLoadField( |
| 1342 reg, holder, field, lookup->representation()); | 1344 reg, holder, field, lookup->representation()); |
| 1343 } | 1345 } |
| 1344 } else { | 1346 } else { |
| 1345 // We found CALLBACKS property in prototype chain of interceptor's | 1347 // We found CALLBACKS property in prototype chain of interceptor's |
| 1346 // holder. | 1348 // holder. |
| 1347 ASSERT(lookup->type() == CALLBACKS); | 1349 ASSERT(lookup->type() == CALLBACKS); |
| 1348 Handle<ExecutableAccessorInfo> callback( | 1350 Handle<ExecutableAccessorInfo> callback( |
| 1349 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 1351 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
| 1350 ASSERT(callback->getter() != NULL); | 1352 ASSERT(callback->getter() != NULL); |
| 1351 | 1353 |
| 1352 Register reg = CallbackHandlerFrontend( | 1354 Register reg = CallbackHandlerFrontend( |
| 1353 interceptor_holder, interceptor_reg, holder, name, callback); | 1355 IC::CurrentTypeOf(interceptor_holder, isolate()), |
| 1356 interceptor_reg, holder, name, callback); |
| 1354 GenerateLoadCallback(reg, callback); | 1357 GenerateLoadCallback(reg, callback); |
| 1355 } | 1358 } |
| 1356 } | 1359 } |
| 1357 | 1360 |
| 1358 | 1361 |
| 1359 Handle<Code> BaseLoadStoreStubCompiler::CompileMonomorphicIC( | 1362 Handle<Code> BaseLoadStoreStubCompiler::CompileMonomorphicIC( |
| 1360 Handle<Type> type, | 1363 Handle<Type> type, |
| 1361 Handle<Code> handler, | 1364 Handle<Code> handler, |
| 1362 Handle<Name> name) { | 1365 Handle<Name> name) { |
| 1363 TypeHandleList types(1); | 1366 TypeHandleList types(1); |
| 1364 CodeHandleList handlers(1); | 1367 CodeHandleList handlers(1); |
| 1365 types.Add(type); | 1368 types.Add(type); |
| 1366 handlers.Add(handler); | 1369 handlers.Add(handler); |
| 1367 Code::StubType stub_type = handler->type(); | 1370 Code::StubType stub_type = handler->type(); |
| 1368 return CompilePolymorphicIC(&types, &handlers, name, stub_type, PROPERTY); | 1371 return CompilePolymorphicIC(&types, &handlers, name, stub_type, PROPERTY); |
| 1369 } | 1372 } |
| 1370 | 1373 |
| 1371 | 1374 |
| 1372 Handle<Code> LoadStubCompiler::CompileLoadViaGetter( | 1375 Handle<Code> LoadStubCompiler::CompileLoadViaGetter( |
| 1373 Handle<Object> object, | 1376 Handle<Type> type, |
| 1374 Handle<JSObject> holder, | 1377 Handle<JSObject> holder, |
| 1375 Handle<Name> name, | 1378 Handle<Name> name, |
| 1376 Handle<JSFunction> getter) { | 1379 Handle<JSFunction> getter) { |
| 1377 HandlerFrontend(object, receiver(), holder, name); | 1380 HandlerFrontend(type, receiver(), holder, name); |
| 1378 GenerateLoadViaGetter(masm(), receiver(), getter); | 1381 GenerateLoadViaGetter(masm(), receiver(), getter); |
| 1379 | 1382 |
| 1380 // Return the generated code. | 1383 // Return the generated code. |
| 1381 return GetCode(kind(), Code::FAST, name); | 1384 return GetCode(kind(), Code::FAST, name); |
| 1382 } | 1385 } |
| 1383 | 1386 |
| 1384 | 1387 |
| 1385 Handle<Code> StoreStubCompiler::CompileStoreTransition( | 1388 Handle<Code> StoreStubCompiler::CompileStoreTransition( |
| 1386 Handle<JSObject> object, | 1389 Handle<JSObject> object, |
| 1387 LookupResult* lookup, | 1390 LookupResult* lookup, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1399 if (lookup->holder() != *object) { | 1402 if (lookup->holder() != *object) { |
| 1400 holder = Handle<JSObject>(lookup->holder()); | 1403 holder = Handle<JSObject>(lookup->holder()); |
| 1401 } else { | 1404 } else { |
| 1402 // Find the top object. | 1405 // Find the top object. |
| 1403 holder = object; | 1406 holder = object; |
| 1404 do { | 1407 do { |
| 1405 holder = Handle<JSObject>(JSObject::cast(holder->GetPrototype())); | 1408 holder = Handle<JSObject>(JSObject::cast(holder->GetPrototype())); |
| 1406 } while (holder->GetPrototype()->IsJSObject()); | 1409 } while (holder->GetPrototype()->IsJSObject()); |
| 1407 } | 1410 } |
| 1408 | 1411 |
| 1409 Register holder_reg = | 1412 Register holder_reg = HandlerFrontendHeader( |
| 1410 HandlerFrontendHeader(object, receiver(), holder, name, &miss); | 1413 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name, &miss); |
| 1411 | 1414 |
| 1412 // If no property was found, and the holder (the last object in the | 1415 // If no property was found, and the holder (the last object in the |
| 1413 // prototype chain) is in slow mode, we need to do a negative lookup on the | 1416 // prototype chain) is in slow mode, we need to do a negative lookup on the |
| 1414 // holder. | 1417 // holder. |
| 1415 if (lookup->holder() == *object) { | 1418 if (lookup->holder() == *object) { |
| 1416 GenerateNegativeHolderLookup(masm(), holder, holder_reg, name, &miss); | 1419 GenerateNegativeHolderLookup(masm(), holder, holder_reg, name, &miss); |
| 1417 } | 1420 } |
| 1418 } | 1421 } |
| 1419 | 1422 |
| 1420 GenerateStoreTransition(masm(), | 1423 GenerateStoreTransition(masm(), |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1437 // Return the generated code. | 1440 // Return the generated code. |
| 1438 return GetCode(kind(), Code::FAST, name); | 1441 return GetCode(kind(), Code::FAST, name); |
| 1439 } | 1442 } |
| 1440 | 1443 |
| 1441 | 1444 |
| 1442 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, | 1445 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, |
| 1443 LookupResult* lookup, | 1446 LookupResult* lookup, |
| 1444 Handle<Name> name) { | 1447 Handle<Name> name) { |
| 1445 Label miss; | 1448 Label miss; |
| 1446 | 1449 |
| 1447 HandlerFrontendHeader(object, receiver(), object, name, &miss); | 1450 HandlerFrontendHeader(IC::CurrentTypeOf(object, isolate()), |
| 1451 receiver(), object, name, &miss); |
| 1448 | 1452 |
| 1449 // Generate store field code. | 1453 // Generate store field code. |
| 1450 GenerateStoreField(masm(), | 1454 GenerateStoreField(masm(), |
| 1451 object, | 1455 object, |
| 1452 lookup, | 1456 lookup, |
| 1453 receiver(), this->name(), value(), scratch1(), scratch2(), | 1457 receiver(), this->name(), value(), scratch1(), scratch2(), |
| 1454 &miss); | 1458 &miss); |
| 1455 | 1459 |
| 1456 // Handle store cache miss. | 1460 // Handle store cache miss. |
| 1457 __ bind(&miss); | 1461 __ bind(&miss); |
| 1458 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1462 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1459 | 1463 |
| 1460 // Return the generated code. | 1464 // Return the generated code. |
| 1461 return GetCode(kind(), Code::FAST, name); | 1465 return GetCode(kind(), Code::FAST, name); |
| 1462 } | 1466 } |
| 1463 | 1467 |
| 1464 | 1468 |
| 1465 Handle<Code> StoreStubCompiler::CompileStoreViaSetter( | 1469 Handle<Code> StoreStubCompiler::CompileStoreViaSetter( |
| 1466 Handle<JSObject> object, | 1470 Handle<JSObject> object, |
| 1467 Handle<JSObject> holder, | 1471 Handle<JSObject> holder, |
| 1468 Handle<Name> name, | 1472 Handle<Name> name, |
| 1469 Handle<JSFunction> setter) { | 1473 Handle<JSFunction> setter) { |
| 1470 HandlerFrontend(object, receiver(), holder, name); | 1474 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), |
| 1475 receiver(), holder, name); |
| 1471 GenerateStoreViaSetter(masm(), setter); | 1476 GenerateStoreViaSetter(masm(), setter); |
| 1472 | 1477 |
| 1473 return GetCode(kind(), Code::FAST, name); | 1478 return GetCode(kind(), Code::FAST, name); |
| 1474 } | 1479 } |
| 1475 | 1480 |
| 1476 | 1481 |
| 1477 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( | 1482 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
| 1478 Handle<Map> receiver_map) { | 1483 Handle<Map> receiver_map) { |
| 1479 ElementsKind elements_kind = receiver_map->elements_kind(); | 1484 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 1480 if (receiver_map->has_fast_elements() || | 1485 if (receiver_map->has_fast_elements() || |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1828 Handle<FunctionTemplateInfo>( | 1833 Handle<FunctionTemplateInfo>( |
| 1829 FunctionTemplateInfo::cast(signature->receiver())); | 1834 FunctionTemplateInfo::cast(signature->receiver())); |
| 1830 } | 1835 } |
| 1831 } | 1836 } |
| 1832 | 1837 |
| 1833 is_simple_api_call_ = true; | 1838 is_simple_api_call_ = true; |
| 1834 } | 1839 } |
| 1835 | 1840 |
| 1836 | 1841 |
| 1837 } } // namespace v8::internal | 1842 } } // namespace v8::internal |
| OLD | NEW |