OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/hydrogen.h" | 5 #include "src/hydrogen.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 | 10 |
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 HConstant* HGraph::GetConstant1() { | 676 HConstant* HGraph::GetConstant1() { |
677 return GetConstant(&constant_1_, 1); | 677 return GetConstant(&constant_1_, 1); |
678 } | 678 } |
679 | 679 |
680 | 680 |
681 HConstant* HGraph::GetConstantMinus1() { | 681 HConstant* HGraph::GetConstantMinus1() { |
682 return GetConstant(&constant_minus1_, -1); | 682 return GetConstant(&constant_minus1_, -1); |
683 } | 683 } |
684 | 684 |
685 | 685 |
| 686 HConstant* HGraph::GetConstantBool(bool value) { |
| 687 return value ? GetConstantTrue() : GetConstantFalse(); |
| 688 } |
| 689 |
| 690 |
686 #define DEFINE_GET_CONSTANT(Name, name, type, htype, boolean_value) \ | 691 #define DEFINE_GET_CONSTANT(Name, name, type, htype, boolean_value) \ |
687 HConstant* HGraph::GetConstant##Name() { \ | 692 HConstant* HGraph::GetConstant##Name() { \ |
688 if (!constant_##name##_.is_set()) { \ | 693 if (!constant_##name##_.is_set()) { \ |
689 HConstant* constant = new(zone()) HConstant( \ | 694 HConstant* constant = new(zone()) HConstant( \ |
690 Unique<Object>::CreateImmovable(isolate()->factory()->name##_value()), \ | 695 Unique<Object>::CreateImmovable(isolate()->factory()->name##_value()), \ |
691 Unique<Map>::CreateImmovable(isolate()->factory()->type##_map()), \ | 696 Unique<Map>::CreateImmovable(isolate()->factory()->type##_map()), \ |
692 false, \ | 697 false, \ |
693 Representation::Tagged(), \ | 698 Representation::Tagged(), \ |
694 htype, \ | 699 htype, \ |
695 true, \ | 700 true, \ |
(...skipping 964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1660 // hash = hash * 2057; | 1665 // hash = hash * 2057; |
1661 hash = AddUncasted<HMul>(hash, Add<HConstant>(2057)); | 1666 hash = AddUncasted<HMul>(hash, Add<HConstant>(2057)); |
1662 hash->ClearFlag(HValue::kCanOverflow); | 1667 hash->ClearFlag(HValue::kCanOverflow); |
1663 | 1668 |
1664 // hash = hash ^ (hash >> 16); | 1669 // hash = hash ^ (hash >> 16); |
1665 shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(16)); | 1670 shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(16)); |
1666 return AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash); | 1671 return AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash); |
1667 } | 1672 } |
1668 | 1673 |
1669 | 1674 |
1670 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver, | 1675 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad( |
1671 HValue* elements, | 1676 HValue* receiver, HValue* elements, HValue* key, HValue* hash, |
1672 HValue* key, | 1677 LanguageMode language_mode) { |
1673 HValue* hash) { | |
1674 HValue* capacity = | 1678 HValue* capacity = |
1675 Add<HLoadKeyed>(elements, Add<HConstant>(NameDictionary::kCapacityIndex), | 1679 Add<HLoadKeyed>(elements, Add<HConstant>(NameDictionary::kCapacityIndex), |
1676 nullptr, FAST_ELEMENTS); | 1680 nullptr, FAST_ELEMENTS); |
1677 | 1681 |
1678 HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1()); | 1682 HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1()); |
1679 mask->ChangeRepresentation(Representation::Integer32()); | 1683 mask->ChangeRepresentation(Representation::Integer32()); |
1680 mask->ClearFlag(HValue::kCanOverflow); | 1684 mask->ClearFlag(HValue::kCanOverflow); |
1681 | 1685 |
1682 HValue* entry = hash; | 1686 HValue* entry = hash; |
1683 HValue* count = graph()->GetConstant1(); | 1687 HValue* count = graph()->GetConstant1(); |
(...skipping 22 matching lines...) Expand all Loading... |
1706 HValue* candidate_key = | 1710 HValue* candidate_key = |
1707 Add<HLoadKeyed>(elements, key_index, nullptr, FAST_ELEMENTS); | 1711 Add<HLoadKeyed>(elements, key_index, nullptr, FAST_ELEMENTS); |
1708 IfBuilder if_undefined(this); | 1712 IfBuilder if_undefined(this); |
1709 if_undefined.If<HCompareObjectEqAndBranch>(candidate_key, | 1713 if_undefined.If<HCompareObjectEqAndBranch>(candidate_key, |
1710 graph()->GetConstantUndefined()); | 1714 graph()->GetConstantUndefined()); |
1711 if_undefined.Then(); | 1715 if_undefined.Then(); |
1712 { | 1716 { |
1713 // element == undefined means "not found". Call the runtime. | 1717 // element == undefined means "not found". Call the runtime. |
1714 // TODO(jkummerow): walk the prototype chain instead. | 1718 // TODO(jkummerow): walk the prototype chain instead. |
1715 Add<HPushArguments>(receiver, key); | 1719 Add<HPushArguments>(receiver, key); |
1716 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(), | 1720 Push(Add<HCallRuntime>( |
1717 Runtime::FunctionForId(Runtime::kKeyedGetProperty), | 1721 isolate()->factory()->empty_string(), |
1718 2)); | 1722 Runtime::FunctionForId(is_strong(language_mode) |
| 1723 ? Runtime::kKeyedGetPropertyStrong |
| 1724 : Runtime::kKeyedGetProperty), |
| 1725 2)); |
1719 } | 1726 } |
1720 if_undefined.Else(); | 1727 if_undefined.Else(); |
1721 { | 1728 { |
1722 IfBuilder if_match(this); | 1729 IfBuilder if_match(this); |
1723 if_match.If<HCompareObjectEqAndBranch>(candidate_key, key); | 1730 if_match.If<HCompareObjectEqAndBranch>(candidate_key, key); |
1724 if_match.Then(); | 1731 if_match.Then(); |
1725 if_match.Else(); | 1732 if_match.Else(); |
1726 | 1733 |
1727 // Update non-internalized string in the dictionary with internalized key? | 1734 // Update non-internalized string in the dictionary with internalized key? |
1728 IfBuilder if_update_with_internalized(this); | 1735 IfBuilder if_update_with_internalized(this); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1766 IfBuilder details_compare(this); | 1773 IfBuilder details_compare(this); |
1767 details_compare.If<HCompareNumericAndBranch>( | 1774 details_compare.If<HCompareNumericAndBranch>( |
1768 details, graph()->GetConstant0(), Token::EQ); | 1775 details, graph()->GetConstant0(), Token::EQ); |
1769 details_compare.Then(); | 1776 details_compare.Then(); |
1770 HValue* result_index = | 1777 HValue* result_index = |
1771 AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 1)); | 1778 AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 1)); |
1772 result_index->ClearFlag(HValue::kCanOverflow); | 1779 result_index->ClearFlag(HValue::kCanOverflow); |
1773 Push(Add<HLoadKeyed>(elements, result_index, nullptr, FAST_ELEMENTS)); | 1780 Push(Add<HLoadKeyed>(elements, result_index, nullptr, FAST_ELEMENTS)); |
1774 details_compare.Else(); | 1781 details_compare.Else(); |
1775 Add<HPushArguments>(receiver, key); | 1782 Add<HPushArguments>(receiver, key); |
1776 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(), | 1783 Push(Add<HCallRuntime>( |
1777 Runtime::FunctionForId(Runtime::kKeyedGetProperty), | 1784 isolate()->factory()->empty_string(), |
1778 2)); | 1785 Runtime::FunctionForId(is_strong(language_mode) |
| 1786 ? Runtime::kKeyedGetPropertyStrong |
| 1787 : Runtime::kKeyedGetProperty), |
| 1788 2)); |
1779 details_compare.End(); | 1789 details_compare.End(); |
1780 | 1790 |
1781 found_key_match.Else(); | 1791 found_key_match.Else(); |
1782 found_key_match.JoinContinuation(&return_or_loop_continuation); | 1792 found_key_match.JoinContinuation(&return_or_loop_continuation); |
1783 } | 1793 } |
1784 if_undefined.JoinContinuation(&return_or_loop_continuation); | 1794 if_undefined.JoinContinuation(&return_or_loop_continuation); |
1785 | 1795 |
1786 IfBuilder return_or_loop(this, &return_or_loop_continuation); | 1796 IfBuilder return_or_loop(this, &return_or_loop_continuation); |
1787 return_or_loop.Then(); | 1797 return_or_loop.Then(); |
1788 probe_loop.Break(); | 1798 probe_loop.Break(); |
(...skipping 4452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6241 return false; | 6251 return false; |
6242 } | 6252 } |
6243 | 6253 |
6244 | 6254 |
6245 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic( | 6255 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic( |
6246 SmallMapList* maps) { | 6256 SmallMapList* maps) { |
6247 DCHECK(map_.is_identical_to(maps->first())); | 6257 DCHECK(map_.is_identical_to(maps->first())); |
6248 if (!CanAccessMonomorphic()) return false; | 6258 if (!CanAccessMonomorphic()) return false; |
6249 STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism); | 6259 STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism); |
6250 if (maps->length() > kMaxLoadPolymorphism) return false; | 6260 if (maps->length() > kMaxLoadPolymorphism) return false; |
6251 | |
6252 HObjectAccess access = HObjectAccess::ForMap(); // bogus default | 6261 HObjectAccess access = HObjectAccess::ForMap(); // bogus default |
6253 if (GetJSObjectFieldAccess(&access)) { | 6262 if (GetJSObjectFieldAccess(&access)) { |
6254 for (int i = 1; i < maps->length(); ++i) { | 6263 for (int i = 1; i < maps->length(); ++i) { |
6255 PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_); | 6264 PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_); |
6256 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default | 6265 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default |
6257 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false; | 6266 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false; |
6258 if (!access.Equals(test_access)) return false; | 6267 if (!access.Equals(test_access)) return false; |
6259 } | 6268 } |
6260 return true; | 6269 return true; |
6261 } | 6270 } |
6262 | |
6263 if (GetJSArrayBufferViewFieldAccess(&access)) { | 6271 if (GetJSArrayBufferViewFieldAccess(&access)) { |
6264 for (int i = 1; i < maps->length(); ++i) { | 6272 for (int i = 1; i < maps->length(); ++i) { |
6265 PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_); | 6273 PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_); |
6266 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default | 6274 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default |
6267 if (!test_info.GetJSArrayBufferViewFieldAccess(&test_access)) { | 6275 if (!test_info.GetJSArrayBufferViewFieldAccess(&test_access)) { |
6268 return false; | 6276 return false; |
6269 } | 6277 } |
6270 if (!access.Equals(test_access)) return false; | 6278 if (!access.Equals(test_access)) return false; |
6271 } | 6279 } |
6272 return true; | 6280 return true; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6334 } | 6342 } |
6335 | 6343 |
6336 HValue* checked_holder = checked_object; | 6344 HValue* checked_holder = checked_object; |
6337 if (info->has_holder()) { | 6345 if (info->has_holder()) { |
6338 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); | 6346 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); |
6339 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); | 6347 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); |
6340 } | 6348 } |
6341 | 6349 |
6342 if (!info->IsFound()) { | 6350 if (!info->IsFound()) { |
6343 DCHECK(info->IsLoad()); | 6351 DCHECK(info->IsLoad()); |
6344 return graph()->GetConstantUndefined(); | 6352 if (is_strong(function_language_mode())) { |
| 6353 return New<HCallRuntime>( |
| 6354 isolate()->factory()->empty_string(), |
| 6355 Runtime::FunctionForId(Runtime::kThrowStrongModeImplicitConversion), |
| 6356 0); |
| 6357 } else { |
| 6358 return graph()->GetConstantUndefined(); |
| 6359 } |
6345 } | 6360 } |
6346 | 6361 |
6347 if (info->IsData()) { | 6362 if (info->IsData()) { |
6348 if (info->IsLoad()) { | 6363 if (info->IsLoad()) { |
6349 return BuildLoadNamedField(info, checked_holder); | 6364 return BuildLoadNamedField(info, checked_holder); |
6350 } else { | 6365 } else { |
6351 return BuildStoreNamedField(info, checked_object, value); | 6366 return BuildStoreNamedField(info, checked_object, value); |
6352 } | 6367 } |
6353 } | 6368 } |
6354 | 6369 |
(...skipping 676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7031 Handle<TypeFeedbackVector> vector = | 7046 Handle<TypeFeedbackVector> vector = |
7032 handle(current_feedback_vector(), isolate()); | 7047 handle(current_feedback_vector(), isolate()); |
7033 FeedbackVectorICSlot slot = expr->AsProperty()->PropertyFeedbackSlot(); | 7048 FeedbackVectorICSlot slot = expr->AsProperty()->PropertyFeedbackSlot(); |
7034 | 7049 |
7035 if (!expr->AsProperty()->key()->IsPropertyName()) { | 7050 if (!expr->AsProperty()->key()->IsPropertyName()) { |
7036 // It's possible that a keyed load of a constant string was converted | 7051 // It's possible that a keyed load of a constant string was converted |
7037 // to a named load. Here, at the last minute, we need to make sure to | 7052 // to a named load. Here, at the last minute, we need to make sure to |
7038 // use a generic Keyed Load if we are using the type vector, because | 7053 // use a generic Keyed Load if we are using the type vector, because |
7039 // it has to share information with full code. | 7054 // it has to share information with full code. |
7040 HConstant* key = Add<HConstant>(name); | 7055 HConstant* key = Add<HConstant>(name); |
7041 HLoadKeyedGeneric* result = | 7056 HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>( |
7042 New<HLoadKeyedGeneric>(object, key, PREMONOMORPHIC); | 7057 object, key, function_language_mode(), PREMONOMORPHIC); |
7043 result->SetVectorAndSlot(vector, slot); | 7058 result->SetVectorAndSlot(vector, slot); |
7044 return result; | 7059 return result; |
7045 } | 7060 } |
7046 | 7061 |
7047 HLoadNamedGeneric* result = | 7062 HLoadNamedGeneric* result = New<HLoadNamedGeneric>( |
7048 New<HLoadNamedGeneric>(object, name, PREMONOMORPHIC); | 7063 object, name, function_language_mode(), PREMONOMORPHIC); |
7049 result->SetVectorAndSlot(vector, slot); | 7064 result->SetVectorAndSlot(vector, slot); |
7050 return result; | 7065 return result; |
7051 } else { | 7066 } else { |
7052 return New<HStoreNamedGeneric>(object, name, value, | 7067 return New<HStoreNamedGeneric>(object, name, value, |
7053 function_language_mode(), PREMONOMORPHIC); | 7068 function_language_mode(), PREMONOMORPHIC); |
7054 } | 7069 } |
7055 } | 7070 } |
7056 | 7071 |
7057 | 7072 |
7058 | 7073 |
7059 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric( | 7074 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric( |
7060 PropertyAccessType access_type, | 7075 PropertyAccessType access_type, |
7061 Expression* expr, | 7076 Expression* expr, |
7062 HValue* object, | 7077 HValue* object, |
7063 HValue* key, | 7078 HValue* key, |
7064 HValue* value) { | 7079 HValue* value) { |
7065 if (access_type == LOAD) { | 7080 if (access_type == LOAD) { |
7066 InlineCacheState initial_state = expr->AsProperty()->GetInlineCacheState(); | 7081 InlineCacheState initial_state = expr->AsProperty()->GetInlineCacheState(); |
7067 HLoadKeyedGeneric* result = | 7082 HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>( |
7068 New<HLoadKeyedGeneric>(object, key, initial_state); | 7083 object, key, function_language_mode(), initial_state); |
7069 // HLoadKeyedGeneric with vector ics benefits from being encoded as | 7084 // HLoadKeyedGeneric with vector ics benefits from being encoded as |
7070 // MEGAMORPHIC because the vector/slot combo becomes unnecessary. | 7085 // MEGAMORPHIC because the vector/slot combo becomes unnecessary. |
7071 if (initial_state != MEGAMORPHIC) { | 7086 if (initial_state != MEGAMORPHIC) { |
7072 // We need to pass vector information. | 7087 // We need to pass vector information. |
7073 Handle<TypeFeedbackVector> vector = | 7088 Handle<TypeFeedbackVector> vector = |
7074 handle(current_feedback_vector(), isolate()); | 7089 handle(current_feedback_vector(), isolate()); |
7075 FeedbackVectorICSlot slot = expr->AsProperty()->PropertyFeedbackSlot(); | 7090 FeedbackVectorICSlot slot = expr->AsProperty()->PropertyFeedbackSlot(); |
7076 result->SetVectorAndSlot(vector, slot); | 7091 result->SetVectorAndSlot(vector, slot); |
7077 } | 7092 } |
7078 return result; | 7093 return result; |
(...skipping 2270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9349 ComputeReceiverTypes(expr, receiver, &maps, zone()); | 9364 ComputeReceiverTypes(expr, receiver, &maps, zone()); |
9350 | 9365 |
9351 if (prop->key()->IsPropertyName() && maps->length() > 0) { | 9366 if (prop->key()->IsPropertyName() && maps->length() > 0) { |
9352 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 9367 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
9353 PropertyAccessInfo info(this, LOAD, maps->first(), name); | 9368 PropertyAccessInfo info(this, LOAD, maps->first(), name); |
9354 if (!info.CanAccessAsMonomorphic(maps)) { | 9369 if (!info.CanAccessAsMonomorphic(maps)) { |
9355 HandlePolymorphicCallNamed(expr, receiver, maps, name); | 9370 HandlePolymorphicCallNamed(expr, receiver, maps, name); |
9356 return; | 9371 return; |
9357 } | 9372 } |
9358 } | 9373 } |
9359 | |
9360 HValue* key = NULL; | 9374 HValue* key = NULL; |
9361 if (!prop->key()->IsPropertyName()) { | 9375 if (!prop->key()->IsPropertyName()) { |
9362 CHECK_ALIVE(VisitForValue(prop->key())); | 9376 CHECK_ALIVE(VisitForValue(prop->key())); |
9363 key = Pop(); | 9377 key = Pop(); |
9364 } | 9378 } |
9365 | 9379 |
9366 CHECK_ALIVE(PushLoad(prop, receiver, key)); | 9380 CHECK_ALIVE(PushLoad(prop, receiver, key)); |
9367 HValue* function = Pop(); | 9381 HValue* function = Pop(); |
9368 | 9382 |
9369 if (function->IsConstant() && | 9383 if (function->IsConstant() && |
(...skipping 3834 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13204 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13218 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13205 } | 13219 } |
13206 | 13220 |
13207 #ifdef DEBUG | 13221 #ifdef DEBUG |
13208 graph_->Verify(false); // No full verify. | 13222 graph_->Verify(false); // No full verify. |
13209 #endif | 13223 #endif |
13210 } | 13224 } |
13211 | 13225 |
13212 } // namespace internal | 13226 } // namespace internal |
13213 } // namespace v8 | 13227 } // namespace v8 |
OLD | NEW |