Chromium Code Reviews| 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 5268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5279 return false; | 5279 return false; |
| 5280 } | 5280 } |
| 5281 | 5281 |
| 5282 | 5282 |
| 5283 // Determines whether the given array or object literal boilerplate satisfies | 5283 // Determines whether the given array or object literal boilerplate satisfies |
| 5284 // all limits to be considered for fast deep-copying and computes the total | 5284 // all limits to be considered for fast deep-copying and computes the total |
| 5285 // size of all objects that are part of the graph. | 5285 // size of all objects that are part of the graph. |
| 5286 static bool IsFastLiteral(Handle<JSObject> boilerplate, | 5286 static bool IsFastLiteral(Handle<JSObject> boilerplate, |
| 5287 int max_depth, | 5287 int max_depth, |
| 5288 int* max_properties, | 5288 int* max_properties, |
| 5289 int* total_size) { | 5289 int* total_size, |
| 5290 bool allocation_sites_enabled) { | |
|
danno
2013/02/08 13:44:38
Maybe also pass this boolean flag around as a Allo
mvstanton
2013/02/11 11:11:24
Done. This area felt a little awkward because I ha
| |
| 5290 ASSERT(max_depth >= 0 && *max_properties >= 0); | 5291 ASSERT(max_depth >= 0 && *max_properties >= 0); |
| 5291 if (max_depth == 0) return false; | 5292 if (max_depth == 0) return false; |
| 5292 | 5293 |
| 5294 if (allocation_sites_enabled && boilerplate->IsJSArray()) { | |
|
danno
2013/02/08 13:44:38
boilerplate->ShouldTrackAllocationInfo instead?, r
mvstanton
2013/02/11 11:11:24
It's helpful in other places in the code too, furt
| |
| 5295 ElementsKind value_elements_kind = boilerplate->GetElementsKind(); | |
| 5296 AllocationSiteMode mode = AllocationSiteInfo::GetMode( | |
| 5297 value_elements_kind); | |
| 5298 if (mode == TRACK_ALLOCATION_SITE) { | |
| 5299 *total_size += AllocationSiteInfo::kSize; | |
| 5300 } | |
| 5301 } | |
| 5302 | |
| 5293 Handle<FixedArrayBase> elements(boilerplate->elements()); | 5303 Handle<FixedArrayBase> elements(boilerplate->elements()); |
| 5294 if (elements->length() > 0 && | 5304 if (elements->length() > 0 && |
| 5295 elements->map() != boilerplate->GetHeap()->fixed_cow_array_map()) { | 5305 elements->map() != boilerplate->GetHeap()->fixed_cow_array_map()) { |
| 5296 if (boilerplate->HasFastDoubleElements()) { | 5306 if (boilerplate->HasFastDoubleElements()) { |
| 5297 *total_size += FixedDoubleArray::SizeFor(elements->length()); | 5307 *total_size += FixedDoubleArray::SizeFor(elements->length()); |
| 5298 } else if (boilerplate->HasFastObjectElements()) { | 5308 } else if (boilerplate->HasFastObjectElements()) { |
| 5299 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); | 5309 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
| 5300 int length = elements->length(); | 5310 int length = elements->length(); |
| 5301 for (int i = 0; i < length; i++) { | 5311 for (int i = 0; i < length; i++) { |
| 5302 if ((*max_properties)-- == 0) return false; | 5312 if ((*max_properties)-- == 0) return false; |
| 5303 Handle<Object> value(fast_elements->get(i)); | 5313 Handle<Object> value(fast_elements->get(i)); |
| 5304 if (value->IsJSObject()) { | 5314 if (value->IsJSObject()) { |
| 5305 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 5315 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 5306 if (!IsFastLiteral(value_object, | 5316 if (!IsFastLiteral(value_object, |
| 5307 max_depth - 1, | 5317 max_depth - 1, |
| 5308 max_properties, | 5318 max_properties, |
| 5309 total_size)) { | 5319 total_size, |
| 5320 allocation_sites_enabled)) { | |
| 5310 return false; | 5321 return false; |
| 5311 } | 5322 } |
| 5312 } | 5323 } |
| 5313 } | 5324 } |
| 5314 *total_size += FixedArray::SizeFor(length); | 5325 *total_size += FixedArray::SizeFor(length); |
| 5315 } else { | 5326 } else { |
| 5316 return false; | 5327 return false; |
| 5317 } | 5328 } |
| 5318 } | 5329 } |
| 5319 | 5330 |
| 5320 Handle<FixedArray> properties(boilerplate->properties()); | 5331 Handle<FixedArray> properties(boilerplate->properties()); |
| 5321 if (properties->length() > 0) { | 5332 if (properties->length() > 0) { |
| 5322 return false; | 5333 return false; |
| 5323 } else { | 5334 } else { |
| 5324 int nof = boilerplate->map()->inobject_properties(); | 5335 int nof = boilerplate->map()->inobject_properties(); |
| 5325 for (int i = 0; i < nof; i++) { | 5336 for (int i = 0; i < nof; i++) { |
| 5326 if ((*max_properties)-- == 0) return false; | 5337 if ((*max_properties)-- == 0) return false; |
| 5327 Handle<Object> value(boilerplate->InObjectPropertyAt(i)); | 5338 Handle<Object> value(boilerplate->InObjectPropertyAt(i)); |
| 5328 if (value->IsJSObject()) { | 5339 if (value->IsJSObject()) { |
| 5329 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 5340 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 5330 if (!IsFastLiteral(value_object, | 5341 if (!IsFastLiteral(value_object, |
| 5331 max_depth - 1, | 5342 max_depth - 1, |
| 5332 max_properties, | 5343 max_properties, |
| 5333 total_size)) { | 5344 total_size, |
| 5345 allocation_sites_enabled)) { | |
| 5334 return false; | 5346 return false; |
| 5335 } | 5347 } |
| 5336 } | 5348 } |
| 5337 } | 5349 } |
| 5338 } | 5350 } |
| 5339 | 5351 |
| 5340 *total_size += boilerplate->map()->instance_size(); | 5352 *total_size += boilerplate->map()->instance_size(); |
| 5341 return true; | 5353 return true; |
| 5342 } | 5354 } |
| 5343 | 5355 |
| 5344 | 5356 |
| 5345 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 5357 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| 5346 ASSERT(!HasStackOverflow()); | 5358 ASSERT(!HasStackOverflow()); |
| 5347 ASSERT(current_block() != NULL); | 5359 ASSERT(current_block() != NULL); |
| 5348 ASSERT(current_block()->HasPredecessor()); | 5360 ASSERT(current_block()->HasPredecessor()); |
| 5349 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 5361 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
| 5350 HValue* context = environment()->LookupContext(); | 5362 HValue* context = environment()->LookupContext(); |
| 5351 HInstruction* literal; | 5363 HInstruction* literal; |
| 5352 | 5364 |
| 5365 // We don't want to use AllocationSiteInfo when the object literal is | |
| 5366 // declared at global scope without a surrounding loop, that means it's | |
| 5367 // literal arrays will never be re-created, and therefore don't benefit from | |
| 5368 // site info. | |
| 5369 bool one_time_code = info()->scope()->is_global_scope() && | |
| 5370 current_block()->LoopNestingDepth() == 0; | |
|
danno
2013/02/08 13:44:38
Maybe make this a predicate somewhere since you ca
mvstanton
2013/02/11 11:11:24
I made it a predicate on the FullCodeGenerator and
| |
| 5371 | |
| 5372 AllocationSiteMode mode = FLAG_track_allocation_sites && !one_time_code | |
| 5373 ? TRACK_ALLOCATION_SITE | |
| 5374 : DONT_TRACK_ALLOCATION_SITE; | |
| 5375 | |
| 5353 // Check whether to use fast or slow deep-copying for boilerplate. | 5376 // Check whether to use fast or slow deep-copying for boilerplate. |
| 5354 int total_size = 0; | 5377 int total_size = 0; |
| 5355 int max_properties = HFastLiteral::kMaxLiteralProperties; | 5378 int max_properties = HFastLiteral::kMaxLiteralProperties; |
| 5356 Handle<Object> boilerplate(closure->literals()->get(expr->literal_index())); | 5379 Handle<Object> original_boilerplate(closure->literals()->get( |
| 5357 if (boilerplate->IsJSObject() && | 5380 expr->literal_index())); |
| 5358 IsFastLiteral(Handle<JSObject>::cast(boilerplate), | 5381 if (original_boilerplate->IsJSObject() && |
| 5382 IsFastLiteral(Handle<JSObject>::cast(original_boilerplate), | |
| 5359 HFastLiteral::kMaxLiteralDepth, | 5383 HFastLiteral::kMaxLiteralDepth, |
| 5360 &max_properties, | 5384 &max_properties, |
| 5361 &total_size)) { | 5385 &total_size, |
| 5362 Handle<JSObject> boilerplate_object = Handle<JSObject>::cast(boilerplate); | 5386 mode == TRACK_ALLOCATION_SITE)) { |
| 5387 // Copy the boilerplate to prevent unsavory sharing between fullcodegen and | |
| 5388 // crankshaft. | |
| 5389 Handle<JSObject> original_boilerplate_object = | |
| 5390 Handle<JSObject>::cast(original_boilerplate); | |
| 5391 Handle<JSObject> boilerplate = DeepCopy(original_boilerplate_object); | |
| 5363 literal = new(zone()) HFastLiteral(context, | 5392 literal = new(zone()) HFastLiteral(context, |
| 5364 boilerplate_object, | 5393 boilerplate, |
| 5394 original_boilerplate_object, | |
| 5365 total_size, | 5395 total_size, |
| 5366 expr->literal_index(), | 5396 expr->literal_index(), |
| 5367 expr->depth(), | 5397 expr->depth(), |
| 5368 DONT_TRACK_ALLOCATION_SITE); | 5398 mode); |
| 5369 } else { | 5399 } else { |
| 5370 literal = new(zone()) HObjectLiteral(context, | 5400 literal = new(zone()) HObjectLiteral(context, |
| 5371 expr->constant_properties(), | 5401 expr->constant_properties(), |
| 5372 expr->fast_elements(), | 5402 expr->fast_elements(), |
| 5373 expr->literal_index(), | 5403 expr->literal_index(), |
| 5374 expr->depth(), | 5404 expr->depth(), |
| 5375 expr->has_function()); | 5405 expr->has_function(), |
| 5406 mode); | |
| 5376 } | 5407 } |
| 5377 | 5408 |
| 5378 // The object is expected in the bailout environment during computation | 5409 // The object is expected in the bailout environment during computation |
| 5379 // of the property values and is the value of the entire expression. | 5410 // of the property values and is the value of the entire expression. |
| 5380 PushAndAdd(literal); | 5411 PushAndAdd(literal); |
| 5381 | 5412 |
| 5382 expr->CalculateEmitStore(zone()); | 5413 expr->CalculateEmitStore(zone()); |
| 5383 | 5414 |
| 5384 for (int i = 0; i < expr->properties()->length(); i++) { | 5415 for (int i = 0; i < expr->properties()->length(); i++) { |
| 5385 ObjectLiteral::Property* property = expr->properties()->at(i); | 5416 ObjectLiteral::Property* property = expr->properties()->at(i); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5450 | 5481 |
| 5451 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 5482 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| 5452 ASSERT(!HasStackOverflow()); | 5483 ASSERT(!HasStackOverflow()); |
| 5453 ASSERT(current_block() != NULL); | 5484 ASSERT(current_block() != NULL); |
| 5454 ASSERT(current_block()->HasPredecessor()); | 5485 ASSERT(current_block()->HasPredecessor()); |
| 5455 ZoneList<Expression*>* subexprs = expr->values(); | 5486 ZoneList<Expression*>* subexprs = expr->values(); |
| 5456 int length = subexprs->length(); | 5487 int length = subexprs->length(); |
| 5457 HValue* context = environment()->LookupContext(); | 5488 HValue* context = environment()->LookupContext(); |
| 5458 HInstruction* literal; | 5489 HInstruction* literal; |
| 5459 | 5490 |
| 5491 bool one_time_code = info()->scope()->is_global_scope() && | |
| 5492 current_block()->LoopNestingDepth() == 0; | |
|
danno
2013/02/08 13:44:38
predicate for this
mvstanton
2013/02/11 11:11:24
Done.
| |
| 5493 | |
| 5494 AllocationSiteMode mode = FLAG_track_allocation_sites && !one_time_code | |
| 5495 ? TRACK_ALLOCATION_SITE | |
| 5496 : DONT_TRACK_ALLOCATION_SITE; | |
| 5497 | |
| 5460 Handle<FixedArray> literals(environment()->closure()->literals()); | 5498 Handle<FixedArray> literals(environment()->closure()->literals()); |
| 5461 Handle<Object> raw_boilerplate(literals->get(expr->literal_index())); | 5499 Handle<Object> raw_boilerplate(literals->get(expr->literal_index())); |
| 5462 | |
| 5463 if (raw_boilerplate->IsUndefined()) { | 5500 if (raw_boilerplate->IsUndefined()) { |
| 5464 raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( | 5501 raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( |
| 5465 isolate(), literals, expr->constant_elements()); | 5502 isolate(), literals, expr->constant_elements()); |
| 5466 if (raw_boilerplate.is_null()) { | 5503 if (raw_boilerplate.is_null()) { |
| 5467 return Bailout("array boilerplate creation failed"); | 5504 return Bailout("array boilerplate creation failed"); |
| 5468 } | 5505 } |
| 5469 literals->set(expr->literal_index(), *raw_boilerplate); | 5506 literals->set(expr->literal_index(), *raw_boilerplate); |
| 5470 if (JSObject::cast(*raw_boilerplate)->elements()->map() == | 5507 if (JSObject::cast(*raw_boilerplate)->elements()->map() == |
| 5471 isolate()->heap()->fixed_cow_array_map()) { | 5508 isolate()->heap()->fixed_cow_array_map()) { |
| 5472 isolate()->counters()->cow_arrays_created_runtime()->Increment(); | 5509 isolate()->counters()->cow_arrays_created_runtime()->Increment(); |
| 5473 } | 5510 } |
| 5474 } | 5511 } |
| 5475 | 5512 |
| 5476 Handle<JSObject> boilerplate = Handle<JSObject>::cast(raw_boilerplate); | 5513 Handle<JSObject> original_boilerplate = |
| 5514 Handle<JSObject>::cast(raw_boilerplate); | |
| 5477 ElementsKind boilerplate_elements_kind = | 5515 ElementsKind boilerplate_elements_kind = |
| 5478 Handle<JSObject>::cast(boilerplate)->GetElementsKind(); | 5516 original_boilerplate->GetElementsKind(); |
| 5479 | |
| 5480 // TODO(mvstanton): This heuristic is only a temporary solution. In the | |
| 5481 // end, we want to quit creating allocation site info after a certain number | |
| 5482 // of GCs for a call site. | |
| 5483 AllocationSiteMode mode = AllocationSiteInfo::GetMode( | |
| 5484 boilerplate_elements_kind); | |
| 5485 | 5517 |
| 5486 // Check whether to use fast or slow deep-copying for boilerplate. | 5518 // Check whether to use fast or slow deep-copying for boilerplate. |
| 5487 int total_size = 0; | 5519 int total_size = 0; |
| 5488 int max_properties = HFastLiteral::kMaxLiteralProperties; | 5520 int max_properties = HFastLiteral::kMaxLiteralProperties; |
| 5489 if (IsFastLiteral(boilerplate, | 5521 if (IsFastLiteral(original_boilerplate, |
| 5490 HFastLiteral::kMaxLiteralDepth, | 5522 HFastLiteral::kMaxLiteralDepth, |
| 5491 &max_properties, | 5523 &max_properties, |
| 5492 &total_size)) { | 5524 &total_size, |
| 5493 if (mode == TRACK_ALLOCATION_SITE) { | 5525 mode == TRACK_ALLOCATION_SITE)) { |
|
danno
2013/02/08 13:44:38
Pass mode rather than a boolean
mvstanton
2013/02/11 11:11:24
Done.
| |
| 5494 total_size += AllocationSiteInfo::kSize; | 5526 // Copy the boilerplate to prevent unsavory sharing between fullcodegen and |
| 5495 } | 5527 // crankshaft. |
| 5528 Handle<JSObject> boilerplate = DeepCopy(original_boilerplate); | |
| 5496 literal = new(zone()) HFastLiteral(context, | 5529 literal = new(zone()) HFastLiteral(context, |
| 5497 boilerplate, | 5530 boilerplate, |
| 5531 original_boilerplate, | |
| 5498 total_size, | 5532 total_size, |
| 5499 expr->literal_index(), | 5533 expr->literal_index(), |
| 5500 expr->depth(), | 5534 expr->depth(), |
| 5501 mode); | 5535 mode); |
| 5502 } else { | 5536 } else { |
| 5503 literal = new(zone()) HArrayLiteral(context, | 5537 literal = new(zone()) HArrayLiteral(context, |
| 5504 boilerplate, | 5538 original_boilerplate, |
| 5505 length, | 5539 length, |
| 5506 expr->literal_index(), | 5540 expr->literal_index(), |
| 5507 expr->depth(), | 5541 expr->depth(), |
| 5508 mode); | 5542 mode); |
| 5509 } | 5543 } |
| 5510 | 5544 |
| 5511 // The array is expected in the bailout environment during computation | 5545 // The array is expected in the bailout environment during computation |
| 5512 // of the property values and is the value of the entire expression. | 5546 // of the property values and is the value of the entire expression. |
| 5513 PushAndAdd(literal); | 5547 PushAndAdd(literal); |
| 5514 | 5548 |
| (...skipping 4869 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10384 } | 10418 } |
| 10385 } | 10419 } |
| 10386 | 10420 |
| 10387 #ifdef DEBUG | 10421 #ifdef DEBUG |
| 10388 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 10422 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 10389 if (allocator_ != NULL) allocator_->Verify(); | 10423 if (allocator_ != NULL) allocator_->Verify(); |
| 10390 #endif | 10424 #endif |
| 10391 } | 10425 } |
| 10392 | 10426 |
| 10393 } } // namespace v8::internal | 10427 } } // namespace v8::internal |
| OLD | NEW |