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 1353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1364 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false; | 1364 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false; |
1365 | 1365 |
1366 // If the property is read-only, we leave the IC in its current | 1366 // If the property is read-only, we leave the IC in its current |
1367 // state. | 1367 // state. |
1368 if (lookup->IsReadOnly()) return false; | 1368 if (lookup->IsReadOnly()) return false; |
1369 | 1369 |
1370 return true; | 1370 return true; |
1371 } | 1371 } |
1372 | 1372 |
1373 | 1373 |
1374 static bool LookupForWrite(JSObject* receiver, | 1374 static bool LookupForWrite(Handle<JSObject> receiver, |
1375 String* name, | 1375 Handle<String> name, |
1376 LookupResult* lookup) { | 1376 LookupResult* lookup) { |
1377 receiver->LocalLookup(name, lookup); | 1377 receiver->LocalLookup(*name, lookup); |
1378 if (!StoreICableLookup(lookup)) { | 1378 if (!StoreICableLookup(lookup)) { |
1379 return false; | 1379 return false; |
1380 } | 1380 } |
1381 | 1381 |
1382 if (lookup->type() == INTERCEPTOR && | 1382 if (lookup->type() == INTERCEPTOR && |
1383 receiver->GetNamedInterceptor()->setter()->IsUndefined()) { | 1383 receiver->GetNamedInterceptor()->setter()->IsUndefined()) { |
1384 receiver->LocalLookupRealNamedProperty(name, lookup); | 1384 receiver->LocalLookupRealNamedProperty(*name, lookup); |
1385 return StoreICableLookup(lookup); | 1385 return StoreICableLookup(lookup); |
1386 } | 1386 } |
1387 | 1387 |
1388 return true; | 1388 return true; |
1389 } | 1389 } |
1390 | 1390 |
1391 | 1391 |
1392 MaybeObject* StoreIC::Store(State state, | 1392 MaybeObject* StoreIC::Store(State state, |
1393 StrictModeFlag strict_mode, | 1393 StrictModeFlag strict_mode, |
1394 Handle<Object> object, | 1394 Handle<Object> object, |
(...skipping 20 matching lines...) Expand all Loading... |
1415 // Ignore other stores where the receiver is not a JSObject. | 1415 // Ignore other stores where the receiver is not a JSObject. |
1416 // TODO(1475): Must check prototype chains of object wrappers. | 1416 // TODO(1475): Must check prototype chains of object wrappers. |
1417 return *value; | 1417 return *value; |
1418 } | 1418 } |
1419 | 1419 |
1420 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1420 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1421 | 1421 |
1422 // Check if the given name is an array index. | 1422 // Check if the given name is an array index. |
1423 uint32_t index; | 1423 uint32_t index; |
1424 if (name->AsArrayIndex(&index)) { | 1424 if (name->AsArrayIndex(&index)) { |
1425 HandleScope scope(isolate()); | |
1426 Handle<Object> result = SetElement(receiver, index, value, strict_mode); | 1425 Handle<Object> result = SetElement(receiver, index, value, strict_mode); |
1427 if (result.is_null()) return Failure::Exception(); | 1426 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1428 return *value; | 1427 return *value; |
1429 } | 1428 } |
1430 | 1429 |
1431 // Use specialized code for setting the length of arrays. | 1430 // Use specialized code for setting the length of arrays. |
1432 if (receiver->IsJSArray() | 1431 if (receiver->IsJSArray() |
1433 && name->Equals(isolate()->heap()->length_symbol()) | 1432 && name->Equals(isolate()->heap()->length_symbol()) |
1434 && JSArray::cast(*receiver)->AllowsSetElementsLength()) { | 1433 && Handle<JSArray>::cast(receiver)->AllowsSetElementsLength()) { |
1435 #ifdef DEBUG | 1434 #ifdef DEBUG |
1436 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); | 1435 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); |
1437 #endif | 1436 #endif |
1438 Builtins::Name target = (strict_mode == kStrictMode) | 1437 Handle<Code> stub = (strict_mode == kStrictMode) |
1439 ? Builtins::kStoreIC_ArrayLength_Strict | 1438 ? isolate()->builtins()->StoreIC_ArrayLength_Strict() |
1440 : Builtins::kStoreIC_ArrayLength; | 1439 : isolate()->builtins()->StoreIC_ArrayLength(); |
1441 set_target(isolate()->builtins()->builtin(target)); | 1440 set_target(*stub); |
1442 return receiver->SetProperty(*name, *value, NONE, strict_mode); | 1441 return receiver->SetProperty(*name, *value, NONE, strict_mode); |
1443 } | 1442 } |
1444 | 1443 |
1445 // Lookup the property locally in the receiver. | 1444 // Lookup the property locally in the receiver. |
1446 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { | 1445 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { |
1447 LookupResult lookup(isolate()); | 1446 LookupResult lookup(isolate()); |
1448 if (LookupForWrite(*receiver, *name, &lookup)) { | 1447 |
| 1448 if (LookupForWrite(receiver, name, &lookup)) { |
1449 // Generate a stub for this store. | 1449 // Generate a stub for this store. |
1450 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); | 1450 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); |
1451 } else { | 1451 } else { |
1452 // Strict mode doesn't allow setting non-existent global property | 1452 // Strict mode doesn't allow setting non-existent global property |
1453 // or an assignment to a read only property. | 1453 // or an assignment to a read only property. |
1454 if (strict_mode == kStrictMode) { | 1454 if (strict_mode == kStrictMode) { |
1455 if (lookup.IsFound() && lookup.IsReadOnly()) { | 1455 if (lookup.IsFound() && lookup.IsReadOnly()) { |
1456 return TypeError("strict_read_only_property", object, name); | 1456 return TypeError("strict_read_only_property", object, name); |
1457 } else if (IsContextual(object)) { | 1457 } else if (IsContextual(object)) { |
1458 return ReferenceError("not_defined", name); | 1458 return ReferenceError("not_defined", name); |
1459 } | 1459 } |
1460 } | 1460 } |
1461 } | 1461 } |
1462 } | 1462 } |
1463 | 1463 |
1464 if (receiver->IsJSGlobalProxy()) { | 1464 if (receiver->IsJSGlobalProxy()) { |
| 1465 // TODO(ulan): find out why we patch this site even with --no-use-ic |
1465 // Generate a generic stub that goes to the runtime when we see a global | 1466 // Generate a generic stub that goes to the runtime when we see a global |
1466 // proxy as receiver. | 1467 // proxy as receiver. |
1467 Code* stub = (strict_mode == kStrictMode) | 1468 Handle<Code> stub = (strict_mode == kStrictMode) |
1468 ? global_proxy_stub_strict() | 1469 ? global_proxy_stub_strict() |
1469 : global_proxy_stub(); | 1470 : global_proxy_stub(); |
1470 if (target() != stub) { | 1471 if (target() != *stub) { |
1471 set_target(stub); | 1472 set_target(*stub); |
1472 #ifdef DEBUG | 1473 #ifdef DEBUG |
1473 TraceIC("StoreIC", name, state, target()); | 1474 TraceIC("StoreIC", name, state, target()); |
1474 #endif | 1475 #endif |
1475 } | 1476 } |
1476 } | 1477 } |
1477 | 1478 |
1478 // Set the property. | 1479 // Set the property. |
1479 return receiver->SetProperty(*name, *value, NONE, strict_mode); | 1480 return receiver->SetProperty(*name, *value, NONE, strict_mode); |
1480 } | 1481 } |
1481 | 1482 |
(...skipping 10 matching lines...) Expand all Loading... |
1492 ASSERT(StoreICableLookup(lookup)); | 1493 ASSERT(StoreICableLookup(lookup)); |
1493 | 1494 |
1494 // If the property has a non-field type allowing map transitions | 1495 // If the property has a non-field type allowing map transitions |
1495 // where there is extra room in the object, we leave the IC in its | 1496 // where there is extra room in the object, we leave the IC in its |
1496 // current state. | 1497 // current state. |
1497 PropertyType type = lookup->type(); | 1498 PropertyType type = lookup->type(); |
1498 | 1499 |
1499 // Compute the code stub for this store; used for rewriting to | 1500 // Compute the code stub for this store; used for rewriting to |
1500 // monomorphic state and making sure that the code stub is in the | 1501 // monomorphic state and making sure that the code stub is in the |
1501 // stub cache. | 1502 // stub cache. |
1502 MaybeObject* maybe_code = NULL; | 1503 Handle<Code> code; |
1503 Object* code = NULL; | |
1504 switch (type) { | 1504 switch (type) { |
1505 case FIELD: { | 1505 case FIELD: |
1506 maybe_code = isolate()->stub_cache()->ComputeStoreField( | 1506 code = isolate()->stub_cache()->ComputeStoreField(name, |
1507 *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode); | 1507 receiver, |
| 1508 lookup->GetFieldIndex(), |
| 1509 Handle<Map>::null(), |
| 1510 strict_mode); |
1508 break; | 1511 break; |
1509 } | |
1510 case MAP_TRANSITION: { | 1512 case MAP_TRANSITION: { |
1511 if (lookup->GetAttributes() != NONE) return; | 1513 if (lookup->GetAttributes() != NONE) return; |
1512 HandleScope scope(isolate()); | |
1513 ASSERT(type == MAP_TRANSITION); | 1514 ASSERT(type == MAP_TRANSITION); |
1514 Handle<Map> transition(lookup->GetTransitionMap()); | 1515 Handle<Map> transition(lookup->GetTransitionMap()); |
1515 int index = transition->PropertyIndexFor(*name); | 1516 int index = transition->PropertyIndexFor(*name); |
1516 maybe_code = isolate()->stub_cache()->ComputeStoreField( | 1517 code = isolate()->stub_cache()->ComputeStoreField( |
1517 *name, *receiver, index, *transition, strict_mode); | 1518 name, receiver, index, transition, strict_mode); |
1518 break; | 1519 break; |
1519 } | 1520 } |
1520 case NORMAL: { | 1521 case NORMAL: |
1521 if (receiver->IsGlobalObject()) { | 1522 if (receiver->IsGlobalObject()) { |
1522 // The stub generated for the global object picks the value directly | 1523 // The stub generated for the global object picks the value directly |
1523 // from the property cell. So the property must be directly on the | 1524 // from the property cell. So the property must be directly on the |
1524 // global object. | 1525 // global object. |
1525 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); | 1526 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); |
1526 JSGlobalPropertyCell* cell = | 1527 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup)); |
1527 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | 1528 code = isolate()->stub_cache()->ComputeStoreGlobal( |
1528 maybe_code = isolate()->stub_cache()->ComputeStoreGlobal( | 1529 name, global, cell, strict_mode); |
1529 *name, *global, cell, strict_mode); | |
1530 } else { | 1530 } else { |
1531 if (lookup->holder() != *receiver) return; | 1531 if (lookup->holder() != *receiver) return; |
1532 maybe_code = isolate()->stub_cache()->ComputeStoreNormal(strict_mode); | 1532 code = isolate()->stub_cache()->ComputeStoreNormal(strict_mode); |
1533 } | 1533 } |
1534 break; | 1534 break; |
1535 } | |
1536 case CALLBACKS: { | 1535 case CALLBACKS: { |
1537 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; | 1536 Handle<Object> callback_object(lookup->GetCallbackObject()); |
1538 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 1537 if (!callback_object->IsAccessorInfo()) return; |
| 1538 Handle<AccessorInfo> callback = |
| 1539 Handle<AccessorInfo>::cast(callback_object); |
1539 if (v8::ToCData<Address>(callback->setter()) == 0) return; | 1540 if (v8::ToCData<Address>(callback->setter()) == 0) return; |
1540 maybe_code = isolate()->stub_cache()->ComputeStoreCallback( | 1541 code = isolate()->stub_cache()->ComputeStoreCallback( |
1541 *name, *receiver, callback, strict_mode); | 1542 name, receiver, callback, strict_mode); |
1542 break; | 1543 break; |
1543 } | 1544 } |
1544 case INTERCEPTOR: { | 1545 case INTERCEPTOR: |
1545 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); | 1546 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); |
1546 maybe_code = isolate()->stub_cache()->ComputeStoreInterceptor( | 1547 code = isolate()->stub_cache()->ComputeStoreInterceptor( |
1547 *name, *receiver, strict_mode); | 1548 name, receiver, strict_mode); |
1548 break; | 1549 break; |
1549 } | |
1550 default: | 1550 default: |
1551 return; | 1551 return; |
1552 } | 1552 } |
1553 | 1553 |
1554 // If we're unable to compute the stub (not enough memory left), we | |
1555 // simply avoid updating the caches. | |
1556 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; | |
1557 | |
1558 // Patch the call site depending on the state of the cache. | 1554 // Patch the call site depending on the state of the cache. |
1559 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 1555 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { |
1560 set_target(Code::cast(code)); | 1556 set_target(*code); |
1561 } else if (state == MONOMORPHIC) { | 1557 } else if (state == MONOMORPHIC) { |
1562 // Only move to megamorphic if the target changes. | 1558 // Only move to megamorphic if the target changes. |
1563 if (target() != Code::cast(code)) { | 1559 if (target() != *code) { |
1564 set_target((strict_mode == kStrictMode) | 1560 set_target((strict_mode == kStrictMode) |
1565 ? megamorphic_stub_strict() | 1561 ? megamorphic_stub_strict() |
1566 : megamorphic_stub()); | 1562 : megamorphic_stub()); |
1567 } | 1563 } |
1568 } else if (state == MEGAMORPHIC) { | 1564 } else if (state == MEGAMORPHIC) { |
1569 // Update the stub cache. | 1565 // Update the stub cache. |
1570 isolate()->stub_cache()->Set(*name, | 1566 isolate()->stub_cache()->Set(*name, receiver->map(), *code); |
1571 receiver->map(), | |
1572 Code::cast(code)); | |
1573 } | 1567 } |
1574 | 1568 |
1575 #ifdef DEBUG | 1569 #ifdef DEBUG |
1576 TraceIC("StoreIC", name, state, target()); | 1570 TraceIC("StoreIC", name, state, target()); |
1577 #endif | 1571 #endif |
1578 } | 1572 } |
1579 | 1573 |
1580 | 1574 |
1581 static bool AddOneReceiverMapIfMissing(MapList* receiver_maps, | 1575 static bool AddOneReceiverMapIfMissing(MapList* receiver_maps, |
1582 Map* new_receiver_map) { | 1576 Map* new_receiver_map) { |
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2083 NoHandleAllocation na; | 2077 NoHandleAllocation na; |
2084 ASSERT(args.length() == 2); | 2078 ASSERT(args.length() == 2); |
2085 KeyedLoadIC ic(isolate); | 2079 KeyedLoadIC ic(isolate); |
2086 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2080 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
2087 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), true); | 2081 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), true); |
2088 } | 2082 } |
2089 | 2083 |
2090 | 2084 |
2091 // Used from ic-<arch>.cc. | 2085 // Used from ic-<arch>.cc. |
2092 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { | 2086 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { |
2093 NoHandleAllocation na; | 2087 HandleScope scope; |
2094 ASSERT(args.length() == 3); | 2088 ASSERT(args.length() == 3); |
2095 StoreIC ic(isolate); | 2089 StoreIC ic(isolate); |
2096 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2090 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
2097 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 2091 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
2098 return ic.Store(state, | 2092 return ic.Store(state, |
2099 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), | 2093 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), |
2100 args.at<Object>(0), | 2094 args.at<Object>(0), |
2101 args.at<String>(1), | 2095 args.at<String>(1), |
2102 args.at<Object>(2)); | 2096 args.at<Object>(2)); |
2103 } | 2097 } |
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2621 #undef ADDR | 2615 #undef ADDR |
2622 }; | 2616 }; |
2623 | 2617 |
2624 | 2618 |
2625 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2619 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2626 return IC_utilities[id]; | 2620 return IC_utilities[id]; |
2627 } | 2621 } |
2628 | 2622 |
2629 | 2623 |
2630 } } // namespace v8::internal | 2624 } } // namespace v8::internal |
OLD | NEW |