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

Side by Side Diff: src/hydrogen-instructions.cc

Issue 10539110: Add negative lookups to polymorphic loads in Crankshaft. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 8 years, 6 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/arm/macro-assembler-arm.cc ('k') | src/ia32/lithium-codegen-ia32.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 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 1600 matching lines...) Expand 10 before | Expand all | Expand 10 after
1611 stream->Add("%u", index()); 1611 stream->Add("%u", index());
1612 } 1612 }
1613 1613
1614 1614
1615 void HLoadNamedField::PrintDataTo(StringStream* stream) { 1615 void HLoadNamedField::PrintDataTo(StringStream* stream) {
1616 object()->PrintNameTo(stream); 1616 object()->PrintNameTo(stream);
1617 stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : ""); 1617 stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
1618 } 1618 }
1619 1619
1620 1620
1621 // Returns true if an instance of this map can never find a property with this
1622 // name in its prototype chain. This means all prototypes up to the top are
1623 // fast and don't have the name in them. It would be good if we could optimize
1624 // polymorphic loads where the property is sometimes found in the prototype
1625 // chain.
1626 static bool PrototypeChainCanNeverResolve(
1627 Handle<Map> map, Handle<String> name) {
1628 Isolate* isolate = map->GetIsolate();
1629 Object* current = map->prototype();
1630 while (current != isolate->heap()->null_value()) {
1631 if (current->IsJSGlobalProxy() ||
1632 current->IsGlobalObject() ||
1633 !current->IsJSObject() ||
1634 JSObject::cast(current)->IsAccessCheckNeeded() ||
1635 !JSObject::cast(current)->HasFastProperties()) {
1636 return false;
1637 }
1638
1639 LookupResult lookup(isolate);
1640 JSObject::cast(current)->map()->LookupInDescriptors(NULL, *name, &lookup);
1641 if (lookup.IsFound()) {
1642 if (lookup.type() != MAP_TRANSITION) return false;
1643 } else if (!lookup.IsCacheable()) {
1644 return false;
1645 }
1646
1647 current = JSObject::cast(current)->GetPrototype();
1648 }
1649 return true;
1650 }
1651
1652
1621 HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context, 1653 HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
1622 HValue* object, 1654 HValue* object,
1623 SmallMapList* types, 1655 SmallMapList* types,
1624 Handle<String> name, 1656 Handle<String> name,
1625 Zone* zone) 1657 Zone* zone)
1626 : types_(Min(types->length(), kMaxLoadPolymorphism), zone), 1658 : types_(Min(types->length(), kMaxLoadPolymorphism), zone),
1627 name_(name), 1659 name_(name),
1628 need_generic_(false) { 1660 need_generic_(false) {
1629 SetOperandAt(0, context); 1661 SetOperandAt(0, context);
1630 SetOperandAt(1, object); 1662 SetOperandAt(1, object);
1631 set_representation(Representation::Tagged()); 1663 set_representation(Representation::Tagged());
1632 SetGVNFlag(kDependsOnMaps); 1664 SetGVNFlag(kDependsOnMaps);
1633 int map_transitions = 0; 1665 SmallMapList negative_lookups;
1634 for (int i = 0; 1666 for (int i = 0;
1635 i < types->length() && types_.length() < kMaxLoadPolymorphism; 1667 i < types->length() && types_.length() < kMaxLoadPolymorphism;
1636 ++i) { 1668 ++i) {
1637 Handle<Map> map = types->at(i); 1669 Handle<Map> map = types->at(i);
1638 LookupResult lookup(map->GetIsolate()); 1670 LookupResult lookup(map->GetIsolate());
1639 map->LookupInDescriptors(NULL, *name, &lookup); 1671 map->LookupInDescriptors(NULL, *name, &lookup);
1640 if (lookup.IsFound()) { 1672 if (lookup.IsFound()) {
1641 switch (lookup.type()) { 1673 switch (lookup.type()) {
1642 case FIELD: { 1674 case FIELD: {
1643 int index = lookup.GetLocalFieldIndexFromMap(*map); 1675 int index = lookup.GetLocalFieldIndexFromMap(*map);
1644 if (index < 0) { 1676 if (index < 0) {
1645 SetGVNFlag(kDependsOnInobjectFields); 1677 SetGVNFlag(kDependsOnInobjectFields);
1646 } else { 1678 } else {
1647 SetGVNFlag(kDependsOnBackingStoreFields); 1679 SetGVNFlag(kDependsOnBackingStoreFields);
1648 } 1680 }
1649 types_.Add(types->at(i), zone); 1681 types_.Add(types->at(i), zone);
1650 break; 1682 break;
1651 } 1683 }
1652 case CONSTANT_FUNCTION: 1684 case CONSTANT_FUNCTION:
1653 types_.Add(types->at(i), zone); 1685 types_.Add(types->at(i), zone);
1654 break; 1686 break;
1655 case MAP_TRANSITION: 1687 case MAP_TRANSITION:
1656 // We should just ignore these since they are not relevant to a load 1688 if (PrototypeChainCanNeverResolve(map, name)) {
1657 // operation. This means we will deopt if we actually see this map 1689 negative_lookups.Add(types->at(i), zone);
1658 // from optimized code. 1690 }
1659 map_transitions++;
1660 break; 1691 break;
1661 default: 1692 default:
1662 break; 1693 break;
1663 } 1694 }
1695 } else if (lookup.IsCacheable()) {
1696 if (PrototypeChainCanNeverResolve(map, name)) {
1697 negative_lookups.Add(types->at(i), zone);
1698 }
1664 } 1699 }
1665 } 1700 }
1666 1701
1667 if (types_.length() + map_transitions == types->length() && 1702 bool need_generic =
1668 FLAG_deoptimize_uncommon_cases) { 1703 (types->length() != negative_lookups.length() + types_.length());
1704 if (!need_generic && FLAG_deoptimize_uncommon_cases) {
1669 SetFlag(kUseGVN); 1705 SetFlag(kUseGVN);
1706 for (int i = 0; i < negative_lookups.length(); i++) {
1707 types_.Add(negative_lookups.at(i), zone);
1708 }
1670 } else { 1709 } else {
1710 // We don't have an easy way to handle both a call (to the generic stub) and
1711 // a deopt in the same hydrogen instruction, so in this case we don't add
1712 // the negative lookups which can deopt - just let the generic stub handle
1713 // them.
1671 SetAllSideEffects(); 1714 SetAllSideEffects();
1672 need_generic_ = true; 1715 need_generic_ = true;
1673 } 1716 }
1674 } 1717 }
1675 1718
1676 1719
1677 bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) { 1720 bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) {
1678 HLoadNamedFieldPolymorphic* other = HLoadNamedFieldPolymorphic::cast(value); 1721 HLoadNamedFieldPolymorphic* other = HLoadNamedFieldPolymorphic::cast(value);
1679 if (types_.length() != other->types()->length()) return false; 1722 if (types_.length() != other->types()->length()) return false;
1680 if (!name_.is_identical_to(other->name())) return false; 1723 if (!name_.is_identical_to(other->name())) return false;
(...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after
2477 2520
2478 2521
2479 void HCheckPrototypeMaps::Verify() { 2522 void HCheckPrototypeMaps::Verify() {
2480 HInstruction::Verify(); 2523 HInstruction::Verify();
2481 ASSERT(HasNoUses()); 2524 ASSERT(HasNoUses());
2482 } 2525 }
2483 2526
2484 #endif 2527 #endif
2485 2528
2486 } } // namespace v8::internal 2529 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/macro-assembler-arm.cc ('k') | src/ia32/lithium-codegen-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698