OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 // constant function properties. | 415 // constant function properties. |
416 if (should_transform && !has_function_literal) { | 416 if (should_transform && !has_function_literal) { |
417 TransformToFastProperties(boilerplate, | 417 TransformToFastProperties(boilerplate, |
418 boilerplate->map()->unused_property_fields()); | 418 boilerplate->map()->unused_property_fields()); |
419 } | 419 } |
420 | 420 |
421 return boilerplate; | 421 return boilerplate; |
422 } | 422 } |
423 | 423 |
424 | 424 |
| 425 static const int kSmiOnlyLiteralMinimumLength = 1024; |
| 426 |
| 427 |
425 static Handle<Object> CreateArrayLiteralBoilerplate( | 428 static Handle<Object> CreateArrayLiteralBoilerplate( |
426 Isolate* isolate, | 429 Isolate* isolate, |
427 Handle<FixedArray> literals, | 430 Handle<FixedArray> literals, |
428 Handle<FixedArray> elements) { | 431 Handle<FixedArray> elements) { |
429 // Create the JSArray. | 432 // Create the JSArray. |
430 Handle<JSFunction> constructor( | 433 Handle<JSFunction> constructor( |
431 JSFunction::GlobalContextFromLiterals(*literals)->array_function()); | 434 JSFunction::GlobalContextFromLiterals(*literals)->array_function()); |
432 Handle<Object> object = isolate->factory()->NewJSObject(constructor); | 435 Handle<Object> object = isolate->factory()->NewJSObject(constructor); |
433 | 436 |
| 437 if (elements->length() > kSmiOnlyLiteralMinimumLength) { |
| 438 Handle<Map> smi_array_map = isolate->factory()->GetElementsTransitionMap( |
| 439 Handle<JSObject>::cast(object), |
| 440 FAST_SMI_ONLY_ELEMENTS); |
| 441 HeapObject::cast(*object)->set_map(*smi_array_map); |
| 442 } |
| 443 |
434 const bool is_cow = | 444 const bool is_cow = |
435 (elements->map() == isolate->heap()->fixed_cow_array_map()); | 445 (elements->map() == isolate->heap()->fixed_cow_array_map()); |
436 Handle<FixedArray> copied_elements = | 446 Handle<FixedArray> copied_elements = |
437 is_cow ? elements : isolate->factory()->CopyFixedArray(elements); | 447 is_cow ? elements : isolate->factory()->CopyFixedArray(elements); |
438 | 448 |
439 Handle<FixedArray> content = Handle<FixedArray>::cast(copied_elements); | 449 Handle<FixedArray> content = Handle<FixedArray>::cast(copied_elements); |
440 bool has_non_smi = false; | 450 bool has_non_smi = false; |
441 if (is_cow) { | 451 if (is_cow) { |
442 // Copy-on-write arrays must be shallow (and simple). | 452 // Copy-on-write arrays must be shallow (and simple). |
443 if (FLAG_smi_only_arrays) { | 453 for (int i = 0; i < content->length(); i++) { |
444 for (int i = 0; i < content->length(); i++) { | 454 Object* current = content->get(i); |
445 Object* current = content->get(i); | 455 ASSERT(!current->IsFixedArray()); |
446 ASSERT(!current->IsFixedArray()); | 456 if (!current->IsSmi() && !current->IsTheHole()) { |
447 if (!current->IsSmi() && !current->IsTheHole()) { | 457 has_non_smi = true; |
448 has_non_smi = true; | |
449 } | |
450 } | 458 } |
451 } else { | 459 } |
452 #if DEBUG | 460 #if DEBUG |
453 for (int i = 0; i < content->length(); i++) { | 461 for (int i = 0; i < content->length(); i++) { |
454 ASSERT(!content->get(i)->IsFixedArray()); | 462 ASSERT(!content->get(i)->IsFixedArray()); |
455 } | 463 } |
456 #endif | 464 #endif |
457 } | |
458 } else { | 465 } else { |
459 for (int i = 0; i < content->length(); i++) { | 466 for (int i = 0; i < content->length(); i++) { |
460 Object* current = content->get(i); | 467 Object* current = content->get(i); |
461 if (current->IsFixedArray()) { | 468 if (current->IsFixedArray()) { |
462 // The value contains the constant_properties of a | 469 // The value contains the constant_properties of a |
463 // simple object or array literal. | 470 // simple object or array literal. |
464 Handle<FixedArray> fa(FixedArray::cast(content->get(i))); | 471 Handle<FixedArray> fa(FixedArray::cast(content->get(i))); |
465 Handle<Object> result = | 472 Handle<Object> result = |
466 CreateLiteralBoilerplate(isolate, literals, fa); | 473 CreateLiteralBoilerplate(isolate, literals, fa); |
467 if (result.is_null()) return result; | 474 if (result.is_null()) return result; |
468 content->set(i, *result); | 475 content->set(i, *result); |
469 has_non_smi = true; | 476 has_non_smi = true; |
470 } else { | 477 } else { |
471 if (!current->IsSmi() && !current->IsTheHole()) { | 478 if (!current->IsSmi() && !current->IsTheHole()) { |
472 has_non_smi = true; | 479 has_non_smi = true; |
473 } | 480 } |
474 } | 481 } |
475 } | 482 } |
476 } | 483 } |
477 | 484 |
478 // Set the elements. | 485 // Set the elements. |
479 Handle<JSArray> js_object(Handle<JSArray>::cast(object)); | 486 Handle<JSArray> js_object(Handle<JSArray>::cast(object)); |
480 isolate->factory()->SetContent(js_object, content); | 487 isolate->factory()->SetContent(js_object, content); |
481 | 488 |
482 if (FLAG_smi_only_arrays) { | 489 if (has_non_smi && js_object->HasFastSmiOnlyElements()) { |
483 if (has_non_smi && js_object->HasFastSmiOnlyElements()) { | 490 isolate->factory()->EnsureCanContainNonSmiElements(js_object); |
484 isolate->factory()->EnsureCanContainNonSmiElements(js_object); | |
485 } | |
486 } | 491 } |
487 | 492 |
488 return object; | 493 return object; |
489 } | 494 } |
490 | 495 |
491 | 496 |
492 static Handle<Object> CreateLiteralBoilerplate( | 497 static Handle<Object> CreateLiteralBoilerplate( |
493 Isolate* isolate, | 498 Isolate* isolate, |
494 Handle<FixedArray> literals, | 499 Handle<FixedArray> literals, |
495 Handle<FixedArray> array) { | 500 Handle<FixedArray> array) { |
(...skipping 1158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1654 if (object->HasFastProperties()) { | 1659 if (object->HasFastProperties()) { |
1655 NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties); | 1660 NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties); |
1656 } | 1661 } |
1657 return *object; | 1662 return *object; |
1658 } | 1663 } |
1659 | 1664 |
1660 | 1665 |
1661 RUNTIME_FUNCTION(MaybeObject*, Runtime_NonSmiElementStored) { | 1666 RUNTIME_FUNCTION(MaybeObject*, Runtime_NonSmiElementStored) { |
1662 ASSERT(args.length() == 1); | 1667 ASSERT(args.length() == 1); |
1663 CONVERT_ARG_CHECKED(JSObject, object, 0); | 1668 CONVERT_ARG_CHECKED(JSObject, object, 0); |
1664 if (FLAG_smi_only_arrays && object->HasFastSmiOnlyElements()) { | 1669 if (object->HasFastSmiOnlyElements()) { |
1665 MaybeObject* maybe_map = object->GetElementsTransitionMap(FAST_ELEMENTS); | 1670 MaybeObject* maybe_map = object->GetElementsTransitionMap(FAST_ELEMENTS); |
1666 Map* map; | 1671 Map* map; |
1667 if (!maybe_map->To<Map>(&map)) return maybe_map; | 1672 if (!maybe_map->To<Map>(&map)) return maybe_map; |
1668 object->set_map(Map::cast(map)); | 1673 object->set_map(Map::cast(map)); |
1669 } | 1674 } |
1670 return *object; | 1675 return *object; |
1671 } | 1676 } |
1672 | 1677 |
1673 | 1678 |
1674 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) { | 1679 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) { |
(...skipping 8066 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9741 } else if (receiver->HasElement(j)) { | 9746 } else if (receiver->HasElement(j)) { |
9742 // Call GetElement on receiver, not its prototype, or getters won't | 9747 // Call GetElement on receiver, not its prototype, or getters won't |
9743 // have the correct receiver. | 9748 // have the correct receiver. |
9744 element_value = GetElement(receiver, j); | 9749 element_value = GetElement(receiver, j); |
9745 if (element_value.is_null()) return false; | 9750 if (element_value.is_null()) return false; |
9746 visitor->visit(j, element_value); | 9751 visitor->visit(j, element_value); |
9747 } | 9752 } |
9748 } | 9753 } |
9749 break; | 9754 break; |
9750 } | 9755 } |
| 9756 case FAST_DOUBLE_ELEMENTS: { |
| 9757 // Run through the elements FixedArray and use HasElement and GetElement |
| 9758 // to check the prototype for missing elements. |
| 9759 Handle<FixedDoubleArray> elements( |
| 9760 FixedDoubleArray::cast(receiver->elements())); |
| 9761 int fast_length = static_cast<int>(length); |
| 9762 ASSERT(fast_length <= elements->length()); |
| 9763 for (int j = 0; j < fast_length; j++) { |
| 9764 HandleScope loop_scope(isolate); |
| 9765 if (!elements->is_the_hole(j)) { |
| 9766 MaybeObject* maybe_double_object = elements->get(j); |
| 9767 Object* double_object; |
| 9768 if (!maybe_double_object->ToObject(&double_object)) { |
| 9769 return false; |
| 9770 } |
| 9771 Handle<Object> element_value(double_object, isolate); |
| 9772 visitor->visit(j, element_value); |
| 9773 } else if (receiver->HasElement(j)) { |
| 9774 // Call GetElement on receiver, not its prototype, or getters won't |
| 9775 // have the correct receiver. |
| 9776 Handle<Object> element_value = GetElement(receiver, j); |
| 9777 if (element_value.is_null()) return false; |
| 9778 visitor->visit(j, element_value); |
| 9779 } |
| 9780 } |
| 9781 break; |
| 9782 } |
9751 case DICTIONARY_ELEMENTS: { | 9783 case DICTIONARY_ELEMENTS: { |
9752 Handle<NumberDictionary> dict(receiver->element_dictionary()); | 9784 Handle<NumberDictionary> dict(receiver->element_dictionary()); |
9753 List<uint32_t> indices(dict->Capacity() / 2); | 9785 List<uint32_t> indices(dict->Capacity() / 2); |
9754 // Collect all indices in the object and the prototypes less | 9786 // Collect all indices in the object and the prototypes less |
9755 // than length. This might introduce duplicates in the indices list. | 9787 // than length. This might introduce duplicates in the indices list. |
9756 CollectElementIndices(receiver, length, &indices); | 9788 CollectElementIndices(receiver, length, &indices); |
9757 indices.Sort(&compareUInt32); | 9789 indices.Sort(&compareUInt32); |
9758 int j = 0; | 9790 int j = 0; |
9759 int n = indices.length(); | 9791 int n = indices.length(); |
9760 while (j < n) { | 9792 while (j < n) { |
(...skipping 3478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13239 } else { | 13271 } else { |
13240 // Handle last resort GC and make sure to allow future allocations | 13272 // Handle last resort GC and make sure to allow future allocations |
13241 // to grow the heap without causing GCs (if possible). | 13273 // to grow the heap without causing GCs (if possible). |
13242 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13274 isolate->counters()->gc_last_resort_from_js()->Increment(); |
13243 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); | 13275 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); |
13244 } | 13276 } |
13245 } | 13277 } |
13246 | 13278 |
13247 | 13279 |
13248 } } // namespace v8::internal | 13280 } } // namespace v8::internal |
OLD | NEW |