Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(146)

Side by Side Diff: src/ic.cc

Issue 844006: Merge changes up to V8 version 2.1.3 into the partial snapshots (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/jsregexp.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 217
216 // Don't clear debug break inline cache as it will remove the break point. 218 // Don't clear debug break inline cache as it will remove the break point.
217 if (target->ic_state() == DEBUG_BREAK) return; 219 if (target->ic_state() == DEBUG_BREAK) return;
218 220
219 switch (target->kind()) { 221 switch (target->kind()) {
220 case Code::LOAD_IC: return LoadIC::Clear(address, target); 222 case Code::LOAD_IC: return LoadIC::Clear(address, target);
221 case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target); 223 case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target);
222 case Code::STORE_IC: return StoreIC::Clear(address, target); 224 case Code::STORE_IC: return StoreIC::Clear(address, target);
223 case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target); 225 case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target);
224 case Code::CALL_IC: return CallIC::Clear(address, target); 226 case Code::CALL_IC: return CallIC::Clear(address, target);
227 case Code::BINARY_OP_IC: return BinaryOpIC::Clear(address, target);
225 default: UNREACHABLE(); 228 default: UNREACHABLE();
226 } 229 }
227 } 230 }
228 231
229 232
230 void CallIC::Clear(Address address, Code* target) { 233 void CallIC::Clear(Address address, Code* target) {
231 State state = target->ic_state(); 234 State state = target->ic_state();
232 InLoopFlag in_loop = target->ic_in_loop(); 235 InLoopFlag in_loop = target->ic_in_loop();
233 if (state == UNINITIALIZED) return; 236 if (state == UNINITIALIZED) return;
234 Code* code = 237 Code* code =
(...skipping 1048 matching lines...) Expand 10 before | Expand all | Expand 10 after
1283 1286
1284 // ---------------------------------------------------------------------------- 1287 // ----------------------------------------------------------------------------
1285 // Static IC stub generators. 1288 // Static IC stub generators.
1286 // 1289 //
1287 1290
1288 // Used from ic_<arch>.cc. 1291 // Used from ic_<arch>.cc.
1289 Object* CallIC_Miss(Arguments args) { 1292 Object* CallIC_Miss(Arguments args) {
1290 NoHandleAllocation na; 1293 NoHandleAllocation na;
1291 ASSERT(args.length() == 2); 1294 ASSERT(args.length() == 2);
1292 CallIC ic; 1295 CallIC ic;
1293 IC::State state = IC::StateFrom(ic.target(), args[0]); 1296 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1294 Object* result = 1297 Object* result =
1295 ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1)); 1298 ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
1296 1299
1297 // The first time the inline cache is updated may be the first time the 1300 // The first time the inline cache is updated may be the first time the
1298 // function it references gets called. If the function was lazily compiled 1301 // function it references gets called. If the function was lazily compiled
1299 // then the first call will trigger a compilation. We check for this case 1302 // then the first call will trigger a compilation. We check for this case
1300 // and we do the compilation immediately, instead of waiting for the stub 1303 // and we do the compilation immediately, instead of waiting for the stub
1301 // currently attached to the JSFunction object to trigger compilation. We 1304 // currently attached to the JSFunction object to trigger compilation. We
1302 // do this in the case where we know that the inline cache is inside a loop, 1305 // do this in the case where we know that the inline cache is inside a loop,
1303 // because then we know that we want to optimize the function. 1306 // because then we know that we want to optimize the function.
(...skipping 12 matching lines...) Expand all
1316 } 1319 }
1317 return *function; 1320 return *function;
1318 } 1321 }
1319 1322
1320 1323
1321 // Used from ic_<arch>.cc. 1324 // Used from ic_<arch>.cc.
1322 Object* LoadIC_Miss(Arguments args) { 1325 Object* LoadIC_Miss(Arguments args) {
1323 NoHandleAllocation na; 1326 NoHandleAllocation na;
1324 ASSERT(args.length() == 2); 1327 ASSERT(args.length() == 2);
1325 LoadIC ic; 1328 LoadIC ic;
1326 IC::State state = IC::StateFrom(ic.target(), args[0]); 1329 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1327 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); 1330 return ic.Load(state, args.at<Object>(0), args.at<String>(1));
1328 } 1331 }
1329 1332
1330 1333
1331 // Used from ic_<arch>.cc 1334 // Used from ic_<arch>.cc
1332 Object* KeyedLoadIC_Miss(Arguments args) { 1335 Object* KeyedLoadIC_Miss(Arguments args) {
1333 NoHandleAllocation na; 1336 NoHandleAllocation na;
1334 ASSERT(args.length() == 2); 1337 ASSERT(args.length() == 2);
1335 KeyedLoadIC ic; 1338 KeyedLoadIC ic;
1336 IC::State state = IC::StateFrom(ic.target(), args[0]); 1339 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1337 return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); 1340 return ic.Load(state, args.at<Object>(0), args.at<Object>(1));
1338 } 1341 }
1339 1342
1340 1343
1341 // Used from ic_<arch>.cc. 1344 // Used from ic_<arch>.cc.
1342 Object* StoreIC_Miss(Arguments args) { 1345 Object* StoreIC_Miss(Arguments args) {
1343 NoHandleAllocation na; 1346 NoHandleAllocation na;
1344 ASSERT(args.length() == 3); 1347 ASSERT(args.length() == 3);
1345 StoreIC ic; 1348 StoreIC ic;
1346 IC::State state = IC::StateFrom(ic.target(), args[0]); 1349 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1347 return ic.Store(state, args.at<Object>(0), args.at<String>(1), 1350 return ic.Store(state, args.at<Object>(0), args.at<String>(1),
1348 args.at<Object>(2)); 1351 args.at<Object>(2));
1349 } 1352 }
1350 1353
1351 1354
1352 Object* StoreIC_ArrayLength(Arguments args) { 1355 Object* StoreIC_ArrayLength(Arguments args) {
1353 NoHandleAllocation nha; 1356 NoHandleAllocation nha;
1354 1357
1355 ASSERT(args.length() == 2); 1358 ASSERT(args.length() == 2);
1356 JSObject* receiver = JSObject::cast(args[0]); 1359 JSObject* receiver = JSObject::cast(args[0]);
1357 Object* len = args[1]; 1360 Object* len = args[1];
1358 1361
1359 return receiver->SetElementsLength(len); 1362 Object* result = receiver->SetElementsLength(len);
1363 if (result->IsFailure()) return result;
1364 return len;
1360 } 1365 }
1361 1366
1362 1367
1363 // Extend storage is called in a store inline cache when 1368 // Extend storage is called in a store inline cache when
1364 // it is necessary to extend the properties array of a 1369 // it is necessary to extend the properties array of a
1365 // JSObject. 1370 // JSObject.
1366 Object* SharedStoreIC_ExtendStorage(Arguments args) { 1371 Object* SharedStoreIC_ExtendStorage(Arguments args) {
1367 NoHandleAllocation na; 1372 NoHandleAllocation na;
1368 ASSERT(args.length() == 3); 1373 ASSERT(args.length() == 3);
1369 1374
(...skipping 22 matching lines...) Expand all
1392 // Return the stored value. 1397 // Return the stored value.
1393 return value; 1398 return value;
1394 } 1399 }
1395 1400
1396 1401
1397 // Used from ic_<arch>.cc. 1402 // Used from ic_<arch>.cc.
1398 Object* KeyedStoreIC_Miss(Arguments args) { 1403 Object* KeyedStoreIC_Miss(Arguments args) {
1399 NoHandleAllocation na; 1404 NoHandleAllocation na;
1400 ASSERT(args.length() == 3); 1405 ASSERT(args.length() == 3);
1401 KeyedStoreIC ic; 1406 KeyedStoreIC ic;
1402 IC::State state = IC::StateFrom(ic.target(), args[0]); 1407 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1403 return ic.Store(state, args.at<Object>(0), args.at<Object>(1), 1408 return ic.Store(state, args.at<Object>(0), args.at<Object>(1),
1404 args.at<Object>(2)); 1409 args.at<Object>(2));
1405 } 1410 }
1406 1411
1407 1412
1413 void BinaryOpIC::patch(Code* code) {
1414 set_target(code);
1415 }
1416
1417
1418 void BinaryOpIC::Clear(Address address, Code* target) {
1419 if (target->ic_state() == UNINITIALIZED) return;
1420
1421 // At the end of a fast case stub there should be a reference to
1422 // a corresponding UNINITIALIZED stub, so look for the last reloc info item.
1423 RelocInfo* rinfo = NULL;
1424 for (RelocIterator it(target, RelocInfo::kCodeTargetMask);
1425 !it.done(); it.next()) {
1426 rinfo = it.rinfo();
1427 }
1428
1429 ASSERT(rinfo != NULL);
1430 Code* uninit_stub = Code::GetCodeFromTargetAddress(rinfo->target_address());
1431 ASSERT(uninit_stub->ic_state() == UNINITIALIZED &&
1432 uninit_stub->kind() == Code::BINARY_OP_IC);
1433 SetTargetAtAddress(address, uninit_stub);
1434 }
1435
1436
1437 const char* BinaryOpIC::GetName(TypeInfo type_info) {
1438 switch (type_info) {
1439 case DEFAULT: return "Default";
1440 case GENERIC: return "Generic";
1441 case HEAP_NUMBERS: return "HeapNumbers";
1442 case STRINGS: return "Strings";
1443 default: return "Invalid";
1444 }
1445 }
1446
1447
1448 BinaryOpIC::State BinaryOpIC::ToState(TypeInfo type_info) {
1449 switch (type_info) {
1450 // DEFAULT is mapped to UNINITIALIZED so that calls to DEFAULT stubs
1451 // are not cleared at GC.
1452 case DEFAULT: return UNINITIALIZED;
1453
1454 // Could have mapped GENERIC to MONOMORPHIC just as well but MEGAMORPHIC is
1455 // conceptually closer.
1456 case GENERIC: return MEGAMORPHIC;
1457
1458 default: return MONOMORPHIC;
1459 }
1460 }
1461
1462
1463 BinaryOpIC::TypeInfo BinaryOpIC::GetTypeInfo(Object* left,
1464 Object* right) {
1465 // Patching is never requested for the two smis.
1466 ASSERT(!left->IsSmi() || !right->IsSmi());
1467
1468 if (left->IsNumber() && right->IsNumber()) {
1469 return HEAP_NUMBERS;
1470 }
1471
1472 if (left->IsString() || right->IsString()) {
1473 // Patching for fast string ADD makes sense even if only one of the
1474 // arguments is a string.
1475 return STRINGS;
1476 }
1477
1478 return GENERIC;
1479 }
1480
1481
1482 // defined in codegen-<arch>.cc
1483 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info);
1484
1485
1486 Object* BinaryOp_Patch(Arguments args) {
1487 ASSERT(args.length() == 6);
1488
1489 Handle<Object> left = args.at<Object>(0);
1490 Handle<Object> right = args.at<Object>(1);
1491 Handle<Object> result = args.at<Object>(2);
1492 int key = Smi::cast(args[3])->value();
1493 #ifdef DEBUG
1494 Token::Value op = static_cast<Token::Value>(Smi::cast(args[4])->value());
1495 BinaryOpIC::TypeInfo prev_type_info =
1496 static_cast<BinaryOpIC::TypeInfo>(Smi::cast(args[5])->value());
1497 #endif // DEBUG
1498 { HandleScope scope;
1499 BinaryOpIC::TypeInfo type_info = BinaryOpIC::GetTypeInfo(*left, *right);
1500 Handle<Code> code = GetBinaryOpStub(key, type_info);
1501 if (!code.is_null()) {
1502 BinaryOpIC ic;
1503 ic.patch(*code);
1504 #ifdef DEBUG
1505 if (FLAG_trace_ic) {
1506 PrintF("[BinaryOpIC (%s->%s)#%s]\n",
1507 BinaryOpIC::GetName(prev_type_info),
1508 BinaryOpIC::GetName(type_info),
1509 Token::Name(op));
1510 }
1511 #endif // DEBUG
1512 }
1513 }
1514
1515 return *result;
1516 }
1517
1518
1408 static Address IC_utilities[] = { 1519 static Address IC_utilities[] = {
1409 #define ADDR(name) FUNCTION_ADDR(name), 1520 #define ADDR(name) FUNCTION_ADDR(name),
1410 IC_UTIL_LIST(ADDR) 1521 IC_UTIL_LIST(ADDR)
1411 NULL 1522 NULL
1412 #undef ADDR 1523 #undef ADDR
1413 }; 1524 };
1414 1525
1415 1526
1416 Address IC::AddressFromUtilityId(IC::UtilityId id) { 1527 Address IC::AddressFromUtilityId(IC::UtilityId id) {
1417 return IC_utilities[id]; 1528 return IC_utilities[id];
1418 } 1529 }
1419 1530
1420 1531
1421 } } // namespace v8::internal 1532 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/jsregexp.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698