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 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 | 215 |
216 // Don't clear debug break inline cache as it will remove the break point. | 216 // Don't clear debug break inline cache as it will remove the break point. |
217 if (target->ic_state() == DEBUG_BREAK) return; | 217 if (target->ic_state() == DEBUG_BREAK) return; |
218 | 218 |
219 switch (target->kind()) { | 219 switch (target->kind()) { |
220 case Code::LOAD_IC: return LoadIC::Clear(address, target); | 220 case Code::LOAD_IC: return LoadIC::Clear(address, target); |
221 case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target); | 221 case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target); |
222 case Code::STORE_IC: return StoreIC::Clear(address, target); | 222 case Code::STORE_IC: return StoreIC::Clear(address, target); |
223 case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target); | 223 case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target); |
224 case Code::CALL_IC: return CallIC::Clear(address, target); | 224 case Code::CALL_IC: return CallIC::Clear(address, target); |
| 225 case Code::BINARY_OP_IC: return BinaryOpIC::Clear(address, target); |
225 default: UNREACHABLE(); | 226 default: UNREACHABLE(); |
226 } | 227 } |
227 } | 228 } |
228 | 229 |
229 | 230 |
230 void CallIC::Clear(Address address, Code* target) { | 231 void CallIC::Clear(Address address, Code* target) { |
231 State state = target->ic_state(); | 232 State state = target->ic_state(); |
232 InLoopFlag in_loop = target->ic_in_loop(); | 233 InLoopFlag in_loop = target->ic_in_loop(); |
233 if (state == UNINITIALIZED) return; | 234 if (state == UNINITIALIZED) return; |
234 Code* code = | 235 Code* code = |
(...skipping 1174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1409 Object* KeyedStoreIC_Miss(Arguments args) { | 1410 Object* KeyedStoreIC_Miss(Arguments args) { |
1410 NoHandleAllocation na; | 1411 NoHandleAllocation na; |
1411 ASSERT(args.length() == 3); | 1412 ASSERT(args.length() == 3); |
1412 KeyedStoreIC ic; | 1413 KeyedStoreIC ic; |
1413 IC::State state = IC::StateFrom(ic.target(), args[0]); | 1414 IC::State state = IC::StateFrom(ic.target(), args[0]); |
1414 return ic.Store(state, args.at<Object>(0), args.at<Object>(1), | 1415 return ic.Store(state, args.at<Object>(0), args.at<Object>(1), |
1415 args.at<Object>(2)); | 1416 args.at<Object>(2)); |
1416 } | 1417 } |
1417 | 1418 |
1418 | 1419 |
| 1420 void BinaryOpIC::patch(Code* code) { |
| 1421 set_target(code); |
| 1422 } |
| 1423 |
| 1424 |
| 1425 void BinaryOpIC::Clear(Address address, Code* target) { |
| 1426 if (target->ic_state() == UNINITIALIZED) return; |
| 1427 |
| 1428 // At the end of a fast case stub there should be a reference to |
| 1429 // a corresponding UNINITIALIZED stub, so look for the last reloc info item. |
| 1430 RelocInfo* rinfo = NULL; |
| 1431 for (RelocIterator it(target, RelocInfo::kCodeTargetMask); |
| 1432 !it.done(); it.next()) { |
| 1433 rinfo = it.rinfo(); |
| 1434 } |
| 1435 |
| 1436 ASSERT(rinfo != NULL); |
| 1437 Code* uninit_stub = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
| 1438 ASSERT(uninit_stub->ic_state() == UNINITIALIZED && |
| 1439 uninit_stub->kind() == Code::BINARY_OP_IC); |
| 1440 SetTargetAtAddress(address, uninit_stub); |
| 1441 } |
| 1442 |
| 1443 |
| 1444 const char* BinaryOpIC::GetName(TypeInfo type_info) { |
| 1445 switch (type_info) { |
| 1446 case DEFAULT: return "Default"; |
| 1447 case GENERIC: return "Generic"; |
| 1448 case HEAP_NUMBERS: return "HeapNumbers"; |
| 1449 case STRINGS: return "Strings"; |
| 1450 default: return "Invalid"; |
| 1451 } |
| 1452 } |
| 1453 |
| 1454 |
| 1455 BinaryOpIC::State BinaryOpIC::ToState(TypeInfo type_info) { |
| 1456 switch (type_info) { |
| 1457 // DEFAULT is mapped to UNINITIALIZED so that calls to DEFAULT stubs |
| 1458 // are not cleared at GC. |
| 1459 case DEFAULT: return UNINITIALIZED; |
| 1460 |
| 1461 // Could have mapped GENERIC to MONOMORPHIC just as well but MEGAMORPHIC is |
| 1462 // conceptually closer. |
| 1463 case GENERIC: return MEGAMORPHIC; |
| 1464 |
| 1465 default: return MONOMORPHIC; |
| 1466 } |
| 1467 } |
| 1468 |
| 1469 |
| 1470 BinaryOpIC::TypeInfo BinaryOpIC::GetTypeInfo(Object* left, |
| 1471 Object* right) { |
| 1472 // Patching is never requested for the two smis. |
| 1473 ASSERT(!left->IsSmi() || !right->IsSmi()); |
| 1474 |
| 1475 if (left->IsNumber() && right->IsNumber()) { |
| 1476 return HEAP_NUMBERS; |
| 1477 } |
| 1478 |
| 1479 if (left->IsString() || right->IsString()) { |
| 1480 // Patching for fast string ADD makes sense even if only one of the |
| 1481 // arguments is a string. |
| 1482 return STRINGS; |
| 1483 } |
| 1484 |
| 1485 return GENERIC; |
| 1486 } |
| 1487 |
| 1488 |
| 1489 // defined in codegen-<arch>.cc |
| 1490 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info); |
| 1491 |
| 1492 |
| 1493 Object* BinaryOp_Patch(Arguments args) { |
| 1494 ASSERT(args.length() == 6); |
| 1495 |
| 1496 HandleScope scope; |
| 1497 Handle<Object> left = args.at<Object>(0); |
| 1498 Handle<Object> right = args.at<Object>(1); |
| 1499 Handle<Object> result = args.at<Object>(2); |
| 1500 int key = Smi::cast(args[3])->value(); |
| 1501 #ifdef DEBUG |
| 1502 Token::Value op = static_cast<Token::Value>(Smi::cast(args[4])->value()); |
| 1503 BinaryOpIC::TypeInfo prev_type_info = |
| 1504 static_cast<BinaryOpIC::TypeInfo>(Smi::cast(args[5])->value()); |
| 1505 #endif // DEBUG |
| 1506 |
| 1507 BinaryOpIC::TypeInfo type_info = BinaryOpIC::GetTypeInfo(*left, *right); |
| 1508 Handle<Code> code = GetBinaryOpStub(key, type_info); |
| 1509 if (!code.is_null()) { |
| 1510 BinaryOpIC ic; |
| 1511 ic.patch(*code); |
| 1512 #ifdef DEBUG |
| 1513 if (FLAG_trace_ic) { |
| 1514 PrintF("[BinaryOpIC (%s->%s)#%s]\n", |
| 1515 BinaryOpIC::GetName(prev_type_info), |
| 1516 BinaryOpIC::GetName(type_info), |
| 1517 Token::Name(op)); |
| 1518 } |
| 1519 #endif // DEBUG |
| 1520 } |
| 1521 |
| 1522 return *result; |
| 1523 } |
| 1524 |
| 1525 |
1419 static Address IC_utilities[] = { | 1526 static Address IC_utilities[] = { |
1420 #define ADDR(name) FUNCTION_ADDR(name), | 1527 #define ADDR(name) FUNCTION_ADDR(name), |
1421 IC_UTIL_LIST(ADDR) | 1528 IC_UTIL_LIST(ADDR) |
1422 NULL | 1529 NULL |
1423 #undef ADDR | 1530 #undef ADDR |
1424 }; | 1531 }; |
1425 | 1532 |
1426 | 1533 |
1427 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 1534 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
1428 return IC_utilities[id]; | 1535 return IC_utilities[id]; |
1429 } | 1536 } |
1430 | 1537 |
1431 | 1538 |
1432 } } // namespace v8::internal | 1539 } } // namespace v8::internal |
OLD | NEW |