OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 UNREACHABLE(); | 56 UNREACHABLE(); |
57 return 0; | 57 return 0; |
58 } | 58 } |
59 | 59 |
60 void IC::TraceIC(const char* type, | 60 void IC::TraceIC(const char* type, |
61 Handle<String> name, | 61 Handle<String> name, |
62 State old_state, | 62 State old_state, |
63 Code* new_target, | 63 Code* new_target, |
64 const char* extra_info) { | 64 const char* extra_info) { |
65 if (FLAG_trace_ic) { | 65 if (FLAG_trace_ic) { |
66 State new_state = StateFrom(new_target, Heap::undefined_value()); | 66 State new_state = StateFrom(new_target, |
| 67 Heap::undefined_value(), |
| 68 Heap::undefined_value()); |
67 PrintF("[%s (%c->%c)%s", type, | 69 PrintF("[%s (%c->%c)%s", type, |
68 TransitionMarkFromState(old_state), | 70 TransitionMarkFromState(old_state), |
69 TransitionMarkFromState(new_state), | 71 TransitionMarkFromState(new_state), |
70 extra_info); | 72 extra_info); |
71 name->Print(); | 73 name->Print(); |
72 PrintF("]\n"); | 74 PrintF("]\n"); |
73 } | 75 } |
74 } | 76 } |
75 #endif | 77 #endif |
76 | 78 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 Address addr = pc() - Assembler::kCallTargetAddressOffset; | 127 Address addr = pc() - Assembler::kCallTargetAddressOffset; |
126 // Return the address in the original code. This is the place where | 128 // Return the address in the original code. This is the place where |
127 // the call which has been overwritten by the DebugBreakXXX resides | 129 // the call which has been overwritten by the DebugBreakXXX resides |
128 // and the place where the inline cache system should look. | 130 // and the place where the inline cache system should look. |
129 intptr_t delta = | 131 intptr_t delta = |
130 original_code->instruction_start() - code->instruction_start(); | 132 original_code->instruction_start() - code->instruction_start(); |
131 return addr + delta; | 133 return addr + delta; |
132 } | 134 } |
133 #endif | 135 #endif |
134 | 136 |
135 IC::State IC::StateFrom(Code* target, Object* receiver) { | 137 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) { |
136 IC::State state = target->ic_state(); | 138 IC::State state = target->ic_state(); |
137 | 139 |
138 if (state != MONOMORPHIC) return state; | 140 if (state != MONOMORPHIC) return state; |
139 if (receiver->IsUndefined() || receiver->IsNull()) return state; | 141 if (receiver->IsUndefined() || receiver->IsNull()) return state; |
140 | 142 |
141 Map* map = GetCodeCacheMapForObject(receiver); | 143 Map* map = GetCodeCacheMapForObject(receiver); |
142 | 144 |
143 // Decide whether the inline cache failed because of changes to the | 145 // Decide whether the inline cache failed because of changes to the |
144 // receiver itself or changes to one of its prototypes. | 146 // receiver itself or changes to one of its prototypes. |
145 // | 147 // |
146 // If there are changes to the receiver itself, the map of the | 148 // If there are changes to the receiver itself, the map of the |
147 // receiver will have changed and the current target will not be in | 149 // receiver will have changed and the current target will not be in |
148 // the receiver map's code cache. Therefore, if the current target | 150 // the receiver map's code cache. Therefore, if the current target |
149 // is in the receiver map's code cache, the inline cache failed due | 151 // is in the receiver map's code cache, the inline cache failed due |
150 // to prototype check failure. | 152 // to prototype check failure. |
151 int index = map->IndexInCodeCache(target); | 153 int index = map->IndexInCodeCache(String::cast(name), target); |
152 if (index >= 0) { | 154 if (index >= 0) { |
153 // For keyed load/store, the most likely cause of cache failure is | 155 // For keyed load/store, the most likely cause of cache failure is |
154 // that the key has changed. We do not distinguish between | 156 // that the key has changed. We do not distinguish between |
155 // prototype and non-prototype failures for keyed access. | 157 // prototype and non-prototype failures for keyed access. |
156 Code::Kind kind = target->kind(); | 158 Code::Kind kind = target->kind(); |
157 if (kind == Code::KEYED_LOAD_IC || kind == Code::KEYED_STORE_IC) { | 159 if (kind == Code::KEYED_LOAD_IC || kind == Code::KEYED_STORE_IC) { |
158 return MONOMORPHIC; | 160 return MONOMORPHIC; |
159 } | 161 } |
160 | 162 |
161 // Remove the target from the code cache to avoid hitting the same | 163 // Remove the target from the code cache to avoid hitting the same |
162 // invalid stub again. | 164 // invalid stub again. |
163 map->RemoveFromCodeCache(index); | 165 map->RemoveFromCodeCache(String::cast(name), target, index); |
164 | 166 |
165 return MONOMORPHIC_PROTOTYPE_FAILURE; | 167 return MONOMORPHIC_PROTOTYPE_FAILURE; |
166 } | 168 } |
167 | 169 |
168 // The builtins object is special. It only changes when JavaScript | 170 // The builtins object is special. It only changes when JavaScript |
169 // builtins are loaded lazily. It is important to keep inline | 171 // builtins are loaded lazily. It is important to keep inline |
170 // caches for the builtins object monomorphic. Therefore, if we get | 172 // caches for the builtins object monomorphic. Therefore, if we get |
171 // an inline cache miss for the builtins object after lazily loading | 173 // an inline cache miss for the builtins object after lazily loading |
172 // JavaScript builtins, we return uninitialized as the state to | 174 // JavaScript builtins, we return uninitialized as the state to |
173 // force the inline cache back to monomorphic state. | 175 // force the inline cache back to monomorphic state. |
(...skipping 1119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1293 | 1295 |
1294 // ---------------------------------------------------------------------------- | 1296 // ---------------------------------------------------------------------------- |
1295 // Static IC stub generators. | 1297 // Static IC stub generators. |
1296 // | 1298 // |
1297 | 1299 |
1298 // Used from ic_<arch>.cc. | 1300 // Used from ic_<arch>.cc. |
1299 Object* CallIC_Miss(Arguments args) { | 1301 Object* CallIC_Miss(Arguments args) { |
1300 NoHandleAllocation na; | 1302 NoHandleAllocation na; |
1301 ASSERT(args.length() == 2); | 1303 ASSERT(args.length() == 2); |
1302 CallIC ic; | 1304 CallIC ic; |
1303 IC::State state = IC::StateFrom(ic.target(), args[0]); | 1305 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1304 Object* result = | 1306 Object* result = |
1305 ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1)); | 1307 ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1)); |
1306 | 1308 |
1307 // The first time the inline cache is updated may be the first time the | 1309 // The first time the inline cache is updated may be the first time the |
1308 // function it references gets called. If the function was lazily compiled | 1310 // function it references gets called. If the function was lazily compiled |
1309 // then the first call will trigger a compilation. We check for this case | 1311 // then the first call will trigger a compilation. We check for this case |
1310 // and we do the compilation immediately, instead of waiting for the stub | 1312 // and we do the compilation immediately, instead of waiting for the stub |
1311 // currently attached to the JSFunction object to trigger compilation. We | 1313 // currently attached to the JSFunction object to trigger compilation. We |
1312 // do this in the case where we know that the inline cache is inside a loop, | 1314 // do this in the case where we know that the inline cache is inside a loop, |
1313 // because then we know that we want to optimize the function. | 1315 // because then we know that we want to optimize the function. |
(...skipping 12 matching lines...) Expand all Loading... |
1326 } | 1328 } |
1327 return *function; | 1329 return *function; |
1328 } | 1330 } |
1329 | 1331 |
1330 | 1332 |
1331 // Used from ic_<arch>.cc. | 1333 // Used from ic_<arch>.cc. |
1332 Object* LoadIC_Miss(Arguments args) { | 1334 Object* LoadIC_Miss(Arguments args) { |
1333 NoHandleAllocation na; | 1335 NoHandleAllocation na; |
1334 ASSERT(args.length() == 2); | 1336 ASSERT(args.length() == 2); |
1335 LoadIC ic; | 1337 LoadIC ic; |
1336 IC::State state = IC::StateFrom(ic.target(), args[0]); | 1338 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1337 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); | 1339 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); |
1338 } | 1340 } |
1339 | 1341 |
1340 | 1342 |
1341 // Used from ic_<arch>.cc | 1343 // Used from ic_<arch>.cc |
1342 Object* KeyedLoadIC_Miss(Arguments args) { | 1344 Object* KeyedLoadIC_Miss(Arguments args) { |
1343 NoHandleAllocation na; | 1345 NoHandleAllocation na; |
1344 ASSERT(args.length() == 2); | 1346 ASSERT(args.length() == 2); |
1345 KeyedLoadIC ic; | 1347 KeyedLoadIC ic; |
1346 IC::State state = IC::StateFrom(ic.target(), args[0]); | 1348 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1347 return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); | 1349 return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); |
1348 } | 1350 } |
1349 | 1351 |
1350 | 1352 |
1351 // Used from ic_<arch>.cc. | 1353 // Used from ic_<arch>.cc. |
1352 Object* StoreIC_Miss(Arguments args) { | 1354 Object* StoreIC_Miss(Arguments args) { |
1353 NoHandleAllocation na; | 1355 NoHandleAllocation na; |
1354 ASSERT(args.length() == 3); | 1356 ASSERT(args.length() == 3); |
1355 StoreIC ic; | 1357 StoreIC ic; |
1356 IC::State state = IC::StateFrom(ic.target(), args[0]); | 1358 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1357 return ic.Store(state, args.at<Object>(0), args.at<String>(1), | 1359 return ic.Store(state, args.at<Object>(0), args.at<String>(1), |
1358 args.at<Object>(2)); | 1360 args.at<Object>(2)); |
1359 } | 1361 } |
1360 | 1362 |
1361 | 1363 |
1362 Object* StoreIC_ArrayLength(Arguments args) { | 1364 Object* StoreIC_ArrayLength(Arguments args) { |
1363 NoHandleAllocation nha; | 1365 NoHandleAllocation nha; |
1364 | 1366 |
1365 ASSERT(args.length() == 2); | 1367 ASSERT(args.length() == 2); |
1366 JSObject* receiver = JSObject::cast(args[0]); | 1368 JSObject* receiver = JSObject::cast(args[0]); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1404 // Return the stored value. | 1406 // Return the stored value. |
1405 return value; | 1407 return value; |
1406 } | 1408 } |
1407 | 1409 |
1408 | 1410 |
1409 // Used from ic_<arch>.cc. | 1411 // Used from ic_<arch>.cc. |
1410 Object* KeyedStoreIC_Miss(Arguments args) { | 1412 Object* KeyedStoreIC_Miss(Arguments args) { |
1411 NoHandleAllocation na; | 1413 NoHandleAllocation na; |
1412 ASSERT(args.length() == 3); | 1414 ASSERT(args.length() == 3); |
1413 KeyedStoreIC ic; | 1415 KeyedStoreIC ic; |
1414 IC::State state = IC::StateFrom(ic.target(), args[0]); | 1416 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1415 return ic.Store(state, args.at<Object>(0), args.at<Object>(1), | 1417 return ic.Store(state, args.at<Object>(0), args.at<Object>(1), |
1416 args.at<Object>(2)); | 1418 args.at<Object>(2)); |
1417 } | 1419 } |
1418 | 1420 |
1419 | 1421 |
1420 void BinaryOpIC::patch(Code* code) { | 1422 void BinaryOpIC::patch(Code* code) { |
1421 set_target(code); | 1423 set_target(code); |
1422 } | 1424 } |
1423 | 1425 |
1424 | 1426 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1530 #undef ADDR | 1532 #undef ADDR |
1531 }; | 1533 }; |
1532 | 1534 |
1533 | 1535 |
1534 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 1536 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
1535 return IC_utilities[id]; | 1537 return IC_utilities[id]; |
1536 } | 1538 } |
1537 | 1539 |
1538 | 1540 |
1539 } } // namespace v8::internal | 1541 } } // namespace v8::internal |
OLD | NEW |