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 6093 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6104 return false; | 6104 return false; |
6105 } | 6105 } |
6106 | 6106 |
6107 | 6107 |
6108 // Determines whether the given array or object literal boilerplate satisfies | 6108 // Determines whether the given array or object literal boilerplate satisfies |
6109 // all limits to be considered for fast deep-copying and computes the total | 6109 // all limits to be considered for fast deep-copying and computes the total |
6110 // size of all objects that are part of the graph. | 6110 // size of all objects that are part of the graph. |
6111 static bool IsFastLiteral(Handle<JSObject> boilerplate, | 6111 static bool IsFastLiteral(Handle<JSObject> boilerplate, |
6112 int max_depth, | 6112 int max_depth, |
6113 int* max_properties, | 6113 int* max_properties, |
6114 int* total_size) { | 6114 int* data_size, |
| 6115 int* pointer_size) { |
6115 ASSERT(max_depth >= 0 && *max_properties >= 0); | 6116 ASSERT(max_depth >= 0 && *max_properties >= 0); |
6116 if (max_depth == 0) return false; | 6117 if (max_depth == 0) return false; |
6117 | 6118 |
6118 Isolate* isolate = boilerplate->GetIsolate(); | 6119 Isolate* isolate = boilerplate->GetIsolate(); |
6119 Handle<FixedArrayBase> elements(boilerplate->elements()); | 6120 Handle<FixedArrayBase> elements(boilerplate->elements()); |
6120 if (elements->length() > 0 && | 6121 if (elements->length() > 0 && |
6121 elements->map() != isolate->heap()->fixed_cow_array_map()) { | 6122 elements->map() != isolate->heap()->fixed_cow_array_map()) { |
6122 if (boilerplate->HasFastDoubleElements()) { | 6123 if (boilerplate->HasFastDoubleElements()) { |
6123 *total_size += FixedDoubleArray::SizeFor(elements->length()); | 6124 *data_size += FixedDoubleArray::SizeFor(elements->length()); |
6124 } else if (boilerplate->HasFastObjectElements()) { | 6125 } else if (boilerplate->HasFastObjectElements()) { |
6125 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); | 6126 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
6126 int length = elements->length(); | 6127 int length = elements->length(); |
6127 for (int i = 0; i < length; i++) { | 6128 for (int i = 0; i < length; i++) { |
6128 if ((*max_properties)-- == 0) return false; | 6129 if ((*max_properties)-- == 0) return false; |
6129 Handle<Object> value(fast_elements->get(i), isolate); | 6130 Handle<Object> value(fast_elements->get(i), isolate); |
6130 if (value->IsJSObject()) { | 6131 if (value->IsJSObject()) { |
6131 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 6132 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
6132 if (!IsFastLiteral(value_object, | 6133 if (!IsFastLiteral(value_object, |
6133 max_depth - 1, | 6134 max_depth - 1, |
6134 max_properties, | 6135 max_properties, |
6135 total_size)) { | 6136 data_size, |
| 6137 pointer_size)) { |
6136 return false; | 6138 return false; |
6137 } | 6139 } |
6138 } | 6140 } |
6139 } | 6141 } |
6140 *total_size += FixedArray::SizeFor(length); | 6142 *pointer_size += FixedArray::SizeFor(length); |
6141 } else { | 6143 } else { |
6142 return false; | 6144 return false; |
6143 } | 6145 } |
6144 } | 6146 } |
6145 | 6147 |
6146 Handle<FixedArray> properties(boilerplate->properties()); | 6148 Handle<FixedArray> properties(boilerplate->properties()); |
6147 if (properties->length() > 0) { | 6149 if (properties->length() > 0) { |
6148 return false; | 6150 return false; |
6149 } else { | 6151 } else { |
6150 int nof = boilerplate->map()->inobject_properties(); | 6152 int nof = boilerplate->map()->inobject_properties(); |
6151 for (int i = 0; i < nof; i++) { | 6153 for (int i = 0; i < nof; i++) { |
6152 if ((*max_properties)-- == 0) return false; | 6154 if ((*max_properties)-- == 0) return false; |
6153 Handle<Object> value(boilerplate->InObjectPropertyAt(i), isolate); | 6155 Handle<Object> value(boilerplate->InObjectPropertyAt(i), isolate); |
6154 if (value->IsJSObject()) { | 6156 if (value->IsJSObject()) { |
6155 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 6157 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
6156 if (!IsFastLiteral(value_object, | 6158 if (!IsFastLiteral(value_object, |
6157 max_depth - 1, | 6159 max_depth - 1, |
6158 max_properties, | 6160 max_properties, |
6159 total_size)) { | 6161 data_size, |
| 6162 pointer_size)) { |
6160 return false; | 6163 return false; |
6161 } | 6164 } |
6162 } | 6165 } |
6163 } | 6166 } |
6164 } | 6167 } |
6165 | 6168 |
6166 *total_size += boilerplate->map()->instance_size(); | 6169 *pointer_size += boilerplate->map()->instance_size(); |
6167 return true; | 6170 return true; |
6168 } | 6171 } |
6169 | 6172 |
6170 | 6173 |
6171 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 6174 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
6172 ASSERT(!HasStackOverflow()); | 6175 ASSERT(!HasStackOverflow()); |
6173 ASSERT(current_block() != NULL); | 6176 ASSERT(current_block() != NULL); |
6174 ASSERT(current_block()->HasPredecessor()); | 6177 ASSERT(current_block()->HasPredecessor()); |
6175 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 6178 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
6176 HValue* context = environment()->LookupContext(); | 6179 HValue* context = environment()->LookupContext(); |
6177 HInstruction* literal; | 6180 HInstruction* literal; |
6178 | 6181 |
6179 // Check whether to use fast or slow deep-copying for boilerplate. | 6182 // Check whether to use fast or slow deep-copying for boilerplate. |
6180 int total_size = 0; | 6183 int data_size = 0; |
| 6184 int pointer_size = 0; |
6181 int max_properties = kMaxFastLiteralProperties; | 6185 int max_properties = kMaxFastLiteralProperties; |
6182 Handle<Object> original_boilerplate(closure->literals()->get( | 6186 Handle<Object> original_boilerplate(closure->literals()->get( |
6183 expr->literal_index()), isolate()); | 6187 expr->literal_index()), isolate()); |
6184 if (original_boilerplate->IsJSObject() && | 6188 if (original_boilerplate->IsJSObject() && |
6185 IsFastLiteral(Handle<JSObject>::cast(original_boilerplate), | 6189 IsFastLiteral(Handle<JSObject>::cast(original_boilerplate), |
6186 kMaxFastLiteralDepth, | 6190 kMaxFastLiteralDepth, |
6187 &max_properties, | 6191 &max_properties, |
6188 &total_size)) { | 6192 &data_size, |
| 6193 &pointer_size)) { |
6189 Handle<JSObject> original_boilerplate_object = | 6194 Handle<JSObject> original_boilerplate_object = |
6190 Handle<JSObject>::cast(original_boilerplate); | 6195 Handle<JSObject>::cast(original_boilerplate); |
6191 Handle<JSObject> boilerplate_object = | 6196 Handle<JSObject> boilerplate_object = |
6192 DeepCopy(original_boilerplate_object); | 6197 DeepCopy(original_boilerplate_object); |
6193 | 6198 |
6194 literal = BuildFastLiteral(context, | 6199 literal = BuildFastLiteral(context, |
6195 boilerplate_object, | 6200 boilerplate_object, |
6196 original_boilerplate_object, | 6201 original_boilerplate_object, |
6197 total_size, | 6202 data_size, |
| 6203 pointer_size, |
6198 DONT_TRACK_ALLOCATION_SITE, | 6204 DONT_TRACK_ALLOCATION_SITE, |
6199 environment()->previous_ast_id()); | 6205 environment()->previous_ast_id()); |
6200 } else { | 6206 } else { |
6201 literal = AddInstruction( | 6207 literal = AddInstruction( |
6202 new(zone()) HObjectLiteral(context, | 6208 new(zone()) HObjectLiteral(context, |
6203 expr->constant_properties(), | 6209 expr->constant_properties(), |
6204 expr->fast_elements(), | 6210 expr->fast_elements(), |
6205 expr->literal_index(), | 6211 expr->literal_index(), |
6206 expr->depth(), | 6212 expr->depth(), |
6207 expr->has_function())); | 6213 expr->has_function())); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6311 ElementsKind boilerplate_elements_kind = | 6317 ElementsKind boilerplate_elements_kind = |
6312 Handle<JSObject>::cast(original_boilerplate_object)->GetElementsKind(); | 6318 Handle<JSObject>::cast(original_boilerplate_object)->GetElementsKind(); |
6313 | 6319 |
6314 // TODO(mvstanton): This heuristic is only a temporary solution. In the | 6320 // TODO(mvstanton): This heuristic is only a temporary solution. In the |
6315 // end, we want to quit creating allocation site info after a certain number | 6321 // end, we want to quit creating allocation site info after a certain number |
6316 // of GCs for a call site. | 6322 // of GCs for a call site. |
6317 AllocationSiteMode mode = AllocationSiteInfo::GetMode( | 6323 AllocationSiteMode mode = AllocationSiteInfo::GetMode( |
6318 boilerplate_elements_kind); | 6324 boilerplate_elements_kind); |
6319 | 6325 |
6320 // Check whether to use fast or slow deep-copying for boilerplate. | 6326 // Check whether to use fast or slow deep-copying for boilerplate. |
6321 int total_size = 0; | 6327 int data_size = 0; |
| 6328 int pointer_size = 0; |
6322 int max_properties = kMaxFastLiteralProperties; | 6329 int max_properties = kMaxFastLiteralProperties; |
6323 if (IsFastLiteral(original_boilerplate_object, | 6330 if (IsFastLiteral(original_boilerplate_object, |
6324 kMaxFastLiteralDepth, | 6331 kMaxFastLiteralDepth, |
6325 &max_properties, | 6332 &max_properties, |
6326 &total_size)) { | 6333 &data_size, |
| 6334 &pointer_size)) { |
6327 if (mode == TRACK_ALLOCATION_SITE) { | 6335 if (mode == TRACK_ALLOCATION_SITE) { |
6328 total_size += AllocationSiteInfo::kSize; | 6336 pointer_size += AllocationSiteInfo::kSize; |
6329 } | 6337 } |
6330 | 6338 |
6331 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object); | 6339 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object); |
6332 literal = BuildFastLiteral(context, | 6340 literal = BuildFastLiteral(context, |
6333 boilerplate_object, | 6341 boilerplate_object, |
6334 original_boilerplate_object, | 6342 original_boilerplate_object, |
6335 total_size, | 6343 data_size, |
| 6344 pointer_size, |
6336 mode, | 6345 mode, |
6337 environment()->previous_ast_id()); | 6346 environment()->previous_ast_id()); |
6338 } else { | 6347 } else { |
6339 literal = AddInstruction( | 6348 literal = AddInstruction( |
6340 new(zone()) HArrayLiteral(context, | 6349 new(zone()) HArrayLiteral(context, |
6341 original_boilerplate_object, | 6350 original_boilerplate_object, |
6342 length, | 6351 length, |
6343 expr->literal_index(), | 6352 expr->literal_index(), |
6344 expr->depth(), | 6353 expr->depth(), |
6345 mode)); | 6354 mode)); |
(...skipping 3737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10083 } else { | 10092 } else { |
10084 return new(zone()) HThisFunction; | 10093 return new(zone()) HThisFunction; |
10085 } | 10094 } |
10086 } | 10095 } |
10087 | 10096 |
10088 | 10097 |
10089 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( | 10098 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( |
10090 HValue* context, | 10099 HValue* context, |
10091 Handle<JSObject> boilerplate_object, | 10100 Handle<JSObject> boilerplate_object, |
10092 Handle<JSObject> original_boilerplate_object, | 10101 Handle<JSObject> original_boilerplate_object, |
10093 int size, | 10102 int data_size, |
| 10103 int pointer_size, |
10094 AllocationSiteMode mode, | 10104 AllocationSiteMode mode, |
10095 BailoutId id) { | 10105 BailoutId id) { |
10096 Zone* zone = this->zone(); | 10106 Zone* zone = this->zone(); |
| 10107 int total_size = data_size + pointer_size; |
10097 | 10108 |
10098 NoObservableSideEffectsScope no_effects(this); | 10109 NoObservableSideEffectsScope no_effects(this); |
10099 | 10110 |
10100 HValue* size_in_bytes = | 10111 HValue* size_in_bytes = |
10101 AddInstruction(new(zone) HConstant(size, Representation::Integer32())); | 10112 AddInstruction(new(zone) HConstant(total_size, |
| 10113 Representation::Integer32())); |
10102 HInstruction* result = | 10114 HInstruction* result = |
10103 AddInstruction(new(zone) HAllocate(context, | 10115 AddInstruction(new(zone) HAllocate(context, |
10104 size_in_bytes, | 10116 size_in_bytes, |
10105 HType::JSObject(), | 10117 HType::JSObject(), |
10106 HAllocate::CAN_ALLOCATE_IN_NEW_SPACE)); | 10118 HAllocate::CAN_ALLOCATE_IN_NEW_SPACE)); |
10107 int offset = 0; | 10119 int offset = 0; |
10108 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, result, | 10120 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, result, |
10109 &offset, mode, id); | 10121 &offset, mode, id); |
10110 ASSERT_EQ(size, offset); | 10122 ASSERT_EQ(total_size, offset); |
10111 return result; | 10123 return result; |
10112 } | 10124 } |
10113 | 10125 |
10114 | 10126 |
10115 void HOptimizedGraphBuilder::BuildEmitDeepCopy( | 10127 void HOptimizedGraphBuilder::BuildEmitDeepCopy( |
10116 Handle<JSObject> boilerplate_object, | 10128 Handle<JSObject> boilerplate_object, |
10117 Handle<JSObject> original_boilerplate_object, | 10129 Handle<JSObject> original_boilerplate_object, |
10118 HInstruction* target, | 10130 HInstruction* target, |
10119 int* offset, | 10131 int* offset, |
10120 AllocationSiteMode mode, | 10132 AllocationSiteMode mode, |
(...skipping 1534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11655 } | 11667 } |
11656 } | 11668 } |
11657 | 11669 |
11658 #ifdef DEBUG | 11670 #ifdef DEBUG |
11659 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11671 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
11660 if (allocator_ != NULL) allocator_->Verify(); | 11672 if (allocator_ != NULL) allocator_->Verify(); |
11661 #endif | 11673 #endif |
11662 } | 11674 } |
11663 | 11675 |
11664 } } // namespace v8::internal | 11676 } } // namespace v8::internal |
OLD | NEW |