| OLD | NEW |
| 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 5664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5675 return false; | 5675 return false; |
| 5676 } | 5676 } |
| 5677 | 5677 |
| 5678 | 5678 |
| 5679 // Determines whether the given array or object literal boilerplate satisfies | 5679 // Determines whether the given array or object literal boilerplate satisfies |
| 5680 // all limits to be considered for fast deep-copying and computes the total | 5680 // all limits to be considered for fast deep-copying and computes the total |
| 5681 // size of all objects that are part of the graph. | 5681 // size of all objects that are part of the graph. |
| 5682 static bool IsFastLiteral(Handle<JSObject> boilerplate, | 5682 static bool IsFastLiteral(Handle<JSObject> boilerplate, |
| 5683 int max_depth, | 5683 int max_depth, |
| 5684 int* max_properties, | 5684 int* max_properties, |
| 5685 int* total_size) { | 5685 int* total_size, |
| 5686 int* allocation_sites_count, |
| 5687 AllocationSiteMode mode) { |
| 5686 ASSERT(max_depth >= 0 && *max_properties >= 0); | 5688 ASSERT(max_depth >= 0 && *max_properties >= 0); |
| 5687 if (max_depth == 0) return false; | 5689 if (max_depth == 0) return false; |
| 5688 | 5690 |
| 5689 Isolate* isolate = boilerplate->GetIsolate(); | 5691 Isolate* isolate = boilerplate->GetIsolate(); |
| 5692 if (mode == TRACK_ALLOCATION_SITE && |
| 5693 boilerplate->ShouldTrackAllocationInfo()) { |
| 5694 *total_size += AllocationSiteInfo::kSize; |
| 5695 *allocation_sites_count = *allocation_sites_count + 1; |
| 5696 } |
| 5697 |
| 5690 Handle<FixedArrayBase> elements(boilerplate->elements()); | 5698 Handle<FixedArrayBase> elements(boilerplate->elements()); |
| 5691 if (elements->length() > 0 && | 5699 if (elements->length() > 0 && |
| 5692 elements->map() != isolate->heap()->fixed_cow_array_map()) { | 5700 elements->map() != isolate->heap()->fixed_cow_array_map()) { |
| 5693 if (boilerplate->HasFastDoubleElements()) { | 5701 if (boilerplate->HasFastDoubleElements()) { |
| 5694 *total_size += FixedDoubleArray::SizeFor(elements->length()); | 5702 *total_size += FixedDoubleArray::SizeFor(elements->length()); |
| 5695 } else if (boilerplate->HasFastObjectElements()) { | 5703 } else if (boilerplate->HasFastObjectElements()) { |
| 5696 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); | 5704 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
| 5697 int length = elements->length(); | 5705 int length = elements->length(); |
| 5698 for (int i = 0; i < length; i++) { | 5706 for (int i = 0; i < length; i++) { |
| 5699 if ((*max_properties)-- == 0) return false; | 5707 if ((*max_properties)-- == 0) return false; |
| 5700 Handle<Object> value(fast_elements->get(i), isolate); | 5708 Handle<Object> value(fast_elements->get(i), isolate); |
| 5701 if (value->IsJSObject()) { | 5709 if (value->IsJSObject()) { |
| 5702 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 5710 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 5703 if (!IsFastLiteral(value_object, | 5711 if (!IsFastLiteral(value_object, |
| 5704 max_depth - 1, | 5712 max_depth - 1, |
| 5705 max_properties, | 5713 max_properties, |
| 5706 total_size)) { | 5714 total_size, |
| 5715 allocation_sites_count, |
| 5716 mode)) { |
| 5707 return false; | 5717 return false; |
| 5708 } | 5718 } |
| 5709 } | 5719 } |
| 5710 } | 5720 } |
| 5711 *total_size += FixedArray::SizeFor(length); | 5721 *total_size += FixedArray::SizeFor(length); |
| 5712 } else { | 5722 } else { |
| 5713 return false; | 5723 return false; |
| 5714 } | 5724 } |
| 5715 } | 5725 } |
| 5716 | 5726 |
| 5717 Handle<FixedArray> properties(boilerplate->properties()); | 5727 Handle<FixedArray> properties(boilerplate->properties()); |
| 5718 if (properties->length() > 0) { | 5728 if (properties->length() > 0) { |
| 5719 return false; | 5729 return false; |
| 5720 } else { | 5730 } else { |
| 5721 int nof = boilerplate->map()->inobject_properties(); | 5731 int nof = boilerplate->map()->inobject_properties(); |
| 5722 for (int i = 0; i < nof; i++) { | 5732 for (int i = 0; i < nof; i++) { |
| 5723 if ((*max_properties)-- == 0) return false; | 5733 if ((*max_properties)-- == 0) return false; |
| 5724 Handle<Object> value(boilerplate->InObjectPropertyAt(i), isolate); | 5734 Handle<Object> value(boilerplate->InObjectPropertyAt(i), isolate); |
| 5725 if (value->IsJSObject()) { | 5735 if (value->IsJSObject()) { |
| 5726 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 5736 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 5727 if (!IsFastLiteral(value_object, | 5737 if (!IsFastLiteral(value_object, |
| 5728 max_depth - 1, | 5738 max_depth - 1, |
| 5729 max_properties, | 5739 max_properties, |
| 5730 total_size)) { | 5740 total_size, |
| 5741 allocation_sites_count, |
| 5742 mode)) { |
| 5731 return false; | 5743 return false; |
| 5732 } | 5744 } |
| 5733 } | 5745 } |
| 5734 } | 5746 } |
| 5735 } | 5747 } |
| 5736 | 5748 |
| 5737 *total_size += boilerplate->map()->instance_size(); | 5749 *total_size += boilerplate->map()->instance_size(); |
| 5738 return true; | 5750 return true; |
| 5739 } | 5751 } |
| 5740 | 5752 |
| 5741 | 5753 |
| 5742 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 5754 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| 5743 ASSERT(!HasStackOverflow()); | 5755 ASSERT(!HasStackOverflow()); |
| 5744 ASSERT(current_block() != NULL); | 5756 ASSERT(current_block() != NULL); |
| 5745 ASSERT(current_block()->HasPredecessor()); | 5757 ASSERT(current_block()->HasPredecessor()); |
| 5746 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 5758 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
| 5747 HValue* context = environment()->LookupContext(); | 5759 HValue* context = environment()->LookupContext(); |
| 5748 HInstruction* literal; | 5760 HInstruction* literal; |
| 5749 | 5761 |
| 5762 // We don't want to use AllocationSiteInfo when the object literal is |
| 5763 // declared at global scope without a surrounding loop, that means it's |
| 5764 // literal arrays will never be re-created, and therefore don't benefit from |
| 5765 // site info. |
| 5766 AllocationSiteMode mode = FLAG_track_allocation_sites && !IsOneTimeCode() |
| 5767 ? TRACK_ALLOCATION_SITE |
| 5768 : DONT_TRACK_ALLOCATION_SITE; |
| 5769 |
| 5750 // Check whether to use fast or slow deep-copying for boilerplate. | 5770 // Check whether to use fast or slow deep-copying for boilerplate. |
| 5751 int total_size = 0; | 5771 int total_size = 0; |
| 5772 int allocation_sites_count = 0; |
| 5752 int max_properties = HFastLiteral::kMaxLiteralProperties; | 5773 int max_properties = HFastLiteral::kMaxLiteralProperties; |
| 5753 Handle<Object> boilerplate(closure->literals()->get(expr->literal_index()), | 5774 Handle<Object> original_boilerplate(closure->literals()->get( |
| 5754 isolate()); | 5775 expr->literal_index()), isolate()); |
| 5755 if (boilerplate->IsJSObject() && | 5776 if (original_boilerplate->IsJSObject() && |
| 5756 IsFastLiteral(Handle<JSObject>::cast(boilerplate), | 5777 IsFastLiteral(Handle<JSObject>::cast(original_boilerplate), |
| 5757 HFastLiteral::kMaxLiteralDepth, | 5778 HFastLiteral::kMaxLiteralDepth, |
| 5758 &max_properties, | 5779 &max_properties, |
| 5759 &total_size)) { | 5780 &total_size, |
| 5760 Handle<JSObject> boilerplate_object = Handle<JSObject>::cast(boilerplate); | 5781 &allocation_sites_count, |
| 5782 mode)) { |
| 5783 // Copy the boilerplate to prevent unsavory sharing between fullcodegen and |
| 5784 // crankshaft. |
| 5785 Handle<JSObject> original_boilerplate_object = |
| 5786 Handle<JSObject>::cast(original_boilerplate); |
| 5787 Handle<JSObject> boilerplate = DeepCopy(original_boilerplate_object); |
| 5788 int size_without_allocation_sites = total_size - |
| 5789 allocation_sites_count * AllocationSiteInfo::kSize; |
| 5761 literal = new(zone()) HFastLiteral(context, | 5790 literal = new(zone()) HFastLiteral(context, |
| 5762 boilerplate_object, | 5791 boilerplate, |
| 5792 original_boilerplate_object, |
| 5763 total_size, | 5793 total_size, |
| 5764 expr->literal_index(), | 5794 expr->literal_index(), |
| 5765 expr->depth(), | 5795 expr->depth(), |
| 5766 DONT_TRACK_ALLOCATION_SITE); | 5796 mode, |
| 5797 size_without_allocation_sites); |
| 5767 } else { | 5798 } else { |
| 5768 literal = new(zone()) HObjectLiteral(context, | 5799 literal = new(zone()) HObjectLiteral(context, |
| 5769 expr->constant_properties(), | 5800 expr->constant_properties(), |
| 5770 expr->fast_elements(), | 5801 expr->fast_elements(), |
| 5771 expr->literal_index(), | 5802 expr->literal_index(), |
| 5772 expr->depth(), | 5803 expr->depth(), |
| 5773 expr->has_function()); | 5804 expr->has_function(), |
| 5805 mode); |
| 5774 } | 5806 } |
| 5775 | 5807 |
| 5776 // The object is expected in the bailout environment during computation | 5808 // The object is expected in the bailout environment during computation |
| 5777 // of the property values and is the value of the entire expression. | 5809 // of the property values and is the value of the entire expression. |
| 5778 PushAndAdd(literal); | 5810 PushAndAdd(literal); |
| 5779 | 5811 |
| 5780 expr->CalculateEmitStore(zone()); | 5812 expr->CalculateEmitStore(zone()); |
| 5781 | 5813 |
| 5782 for (int i = 0; i < expr->properties()->length(); i++) { | 5814 for (int i = 0; i < expr->properties()->length(); i++) { |
| 5783 ObjectLiteral::Property* property = expr->properties()->at(i); | 5815 ObjectLiteral::Property* property = expr->properties()->at(i); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5848 | 5880 |
| 5849 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 5881 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| 5850 ASSERT(!HasStackOverflow()); | 5882 ASSERT(!HasStackOverflow()); |
| 5851 ASSERT(current_block() != NULL); | 5883 ASSERT(current_block() != NULL); |
| 5852 ASSERT(current_block()->HasPredecessor()); | 5884 ASSERT(current_block()->HasPredecessor()); |
| 5853 ZoneList<Expression*>* subexprs = expr->values(); | 5885 ZoneList<Expression*>* subexprs = expr->values(); |
| 5854 int length = subexprs->length(); | 5886 int length = subexprs->length(); |
| 5855 HValue* context = environment()->LookupContext(); | 5887 HValue* context = environment()->LookupContext(); |
| 5856 HInstruction* literal; | 5888 HInstruction* literal; |
| 5857 | 5889 |
| 5890 AllocationSiteMode mode = FLAG_track_allocation_sites && !IsOneTimeCode() |
| 5891 ? TRACK_ALLOCATION_SITE |
| 5892 : DONT_TRACK_ALLOCATION_SITE; |
| 5893 |
| 5858 Handle<FixedArray> literals(environment()->closure()->literals()); | 5894 Handle<FixedArray> literals(environment()->closure()->literals()); |
| 5859 Handle<Object> raw_boilerplate(literals->get(expr->literal_index()), | 5895 Handle<Object> raw_boilerplate(literals->get(expr->literal_index()), |
| 5860 isolate()); | 5896 isolate()); |
| 5861 | |
| 5862 if (raw_boilerplate->IsUndefined()) { | 5897 if (raw_boilerplate->IsUndefined()) { |
| 5863 raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( | 5898 raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( |
| 5864 isolate(), literals, expr->constant_elements()); | 5899 isolate(), literals, expr->constant_elements()); |
| 5865 if (raw_boilerplate.is_null()) { | 5900 if (raw_boilerplate.is_null()) { |
| 5866 return Bailout("array boilerplate creation failed"); | 5901 return Bailout("array boilerplate creation failed"); |
| 5867 } | 5902 } |
| 5868 literals->set(expr->literal_index(), *raw_boilerplate); | 5903 literals->set(expr->literal_index(), *raw_boilerplate); |
| 5869 if (JSObject::cast(*raw_boilerplate)->elements()->map() == | 5904 if (JSObject::cast(*raw_boilerplate)->elements()->map() == |
| 5870 isolate()->heap()->fixed_cow_array_map()) { | 5905 isolate()->heap()->fixed_cow_array_map()) { |
| 5871 isolate()->counters()->cow_arrays_created_runtime()->Increment(); | 5906 isolate()->counters()->cow_arrays_created_runtime()->Increment(); |
| 5872 } | 5907 } |
| 5873 } | 5908 } |
| 5874 | 5909 |
| 5875 Handle<JSObject> boilerplate = Handle<JSObject>::cast(raw_boilerplate); | 5910 Handle<JSObject> original_boilerplate = |
| 5911 Handle<JSObject>::cast(raw_boilerplate); |
| 5876 ElementsKind boilerplate_elements_kind = | 5912 ElementsKind boilerplate_elements_kind = |
| 5877 Handle<JSObject>::cast(boilerplate)->GetElementsKind(); | 5913 original_boilerplate->GetElementsKind(); |
| 5878 | |
| 5879 // TODO(mvstanton): This heuristic is only a temporary solution. In the | |
| 5880 // end, we want to quit creating allocation site info after a certain number | |
| 5881 // of GCs for a call site. | |
| 5882 AllocationSiteMode mode = AllocationSiteInfo::GetMode( | |
| 5883 boilerplate_elements_kind); | |
| 5884 | 5914 |
| 5885 // Check whether to use fast or slow deep-copying for boilerplate. | 5915 // Check whether to use fast or slow deep-copying for boilerplate. |
| 5886 int total_size = 0; | 5916 int total_size = 0; |
| 5917 int allocation_sites_count = 0; |
| 5887 int max_properties = HFastLiteral::kMaxLiteralProperties; | 5918 int max_properties = HFastLiteral::kMaxLiteralProperties; |
| 5888 if (IsFastLiteral(boilerplate, | 5919 if (IsFastLiteral(original_boilerplate, |
| 5889 HFastLiteral::kMaxLiteralDepth, | 5920 HFastLiteral::kMaxLiteralDepth, |
| 5890 &max_properties, | 5921 &max_properties, |
| 5891 &total_size)) { | 5922 &total_size, |
| 5892 if (mode == TRACK_ALLOCATION_SITE) { | 5923 &allocation_sites_count, |
| 5893 total_size += AllocationSiteInfo::kSize; | 5924 mode)) { |
| 5894 } | 5925 // Copy the boilerplate to prevent unsavory sharing between fullcodegen and |
| 5926 // crankshaft. |
| 5927 int size_without_allocation_sites = total_size - |
| 5928 allocation_sites_count * AllocationSiteInfo::kSize; |
| 5929 Handle<JSObject> boilerplate = DeepCopy(original_boilerplate); |
| 5895 literal = new(zone()) HFastLiteral(context, | 5930 literal = new(zone()) HFastLiteral(context, |
| 5896 boilerplate, | 5931 boilerplate, |
| 5932 original_boilerplate, |
| 5897 total_size, | 5933 total_size, |
| 5898 expr->literal_index(), | 5934 expr->literal_index(), |
| 5899 expr->depth(), | 5935 expr->depth(), |
| 5900 mode); | 5936 mode, |
| 5937 size_without_allocation_sites); |
| 5901 } else { | 5938 } else { |
| 5902 literal = new(zone()) HArrayLiteral(context, | 5939 literal = new(zone()) HArrayLiteral(context, |
| 5903 boilerplate, | 5940 original_boilerplate, |
| 5904 length, | 5941 length, |
| 5905 expr->literal_index(), | 5942 expr->literal_index(), |
| 5906 expr->depth(), | 5943 expr->depth(), |
| 5907 mode); | 5944 mode); |
| 5908 } | 5945 } |
| 5909 | 5946 |
| 5910 // The array is expected in the bailout environment during computation | 5947 // The array is expected in the bailout environment during computation |
| 5911 // of the property values and is the value of the entire expression. | 5948 // of the property values and is the value of the entire expression. |
| 5912 PushAndAdd(literal); | 5949 PushAndAdd(literal); |
| 5913 | 5950 |
| (...skipping 5035 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10949 } | 10986 } |
| 10950 } | 10987 } |
| 10951 | 10988 |
| 10952 #ifdef DEBUG | 10989 #ifdef DEBUG |
| 10953 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 10990 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 10954 if (allocator_ != NULL) allocator_->Verify(); | 10991 if (allocator_ != NULL) allocator_->Verify(); |
| 10955 #endif | 10992 #endif |
| 10956 } | 10993 } |
| 10957 | 10994 |
| 10958 } } // namespace v8::internal | 10995 } } // namespace v8::internal |
| OLD | NEW |