Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(275)

Side by Side Diff: src/parser.cc

Issue 61873003: Defer allocation of constant literal properties. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/parser.h ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 3645 matching lines...) Expand 10 before | Expand all | Expand 10 after
3656 values->Add(elem, zone()); 3656 values->Add(elem, zone());
3657 if (peek() != Token::RBRACK) { 3657 if (peek() != Token::RBRACK) {
3658 Expect(Token::COMMA, CHECK_OK); 3658 Expect(Token::COMMA, CHECK_OK);
3659 } 3659 }
3660 } 3660 }
3661 Expect(Token::RBRACK, CHECK_OK); 3661 Expect(Token::RBRACK, CHECK_OK);
3662 3662
3663 // Update the scope information before the pre-parsing bailout. 3663 // Update the scope information before the pre-parsing bailout.
3664 int literal_index = current_function_state_->NextMaterializedLiteralIndex(); 3664 int literal_index = current_function_state_->NextMaterializedLiteralIndex();
3665 3665
3666 // Allocate a fixed array to hold all the object literals. 3666 return factory()->NewArrayLiteral(values, literal_index, pos);
3667 Handle<JSArray> array =
3668 isolate()->factory()->NewJSArray(0, FAST_HOLEY_SMI_ELEMENTS);
3669 isolate()->factory()->SetElementsCapacityAndLength(
3670 array, values->length(), values->length());
3671
3672 // Fill in the literals.
3673 Heap* heap = isolate()->heap();
3674 bool is_simple = true;
3675 int depth = 1;
3676 bool is_holey = false;
3677 for (int i = 0, n = values->length(); i < n; i++) {
3678 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
3679 if (m_literal != NULL && m_literal->depth() + 1 > depth) {
3680 depth = m_literal->depth() + 1;
3681 }
3682 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
3683 if (boilerplate_value->IsTheHole()) {
3684 is_holey = true;
3685 } else if (boilerplate_value->IsUninitialized()) {
3686 is_simple = false;
3687 JSObject::SetOwnElement(
3688 array, i, handle(Smi::FromInt(0), isolate()), kNonStrictMode);
3689 } else {
3690 JSObject::SetOwnElement(array, i, boilerplate_value, kNonStrictMode);
3691 }
3692 }
3693
3694 Handle<FixedArrayBase> element_values(array->elements());
3695
3696 // Simple and shallow arrays can be lazily copied, we transform the
3697 // elements array to a copy-on-write array.
3698 if (is_simple && depth == 1 && values->length() > 0 &&
3699 array->HasFastSmiOrObjectElements()) {
3700 element_values->set_map(heap->fixed_cow_array_map());
3701 }
3702
3703 // Remember both the literal's constant values as well as the ElementsKind
3704 // in a 2-element FixedArray.
3705 Handle<FixedArray> literals = isolate()->factory()->NewFixedArray(2, TENURED);
3706
3707 ElementsKind kind = array->GetElementsKind();
3708 kind = is_holey ? GetHoleyElementsKind(kind) : GetPackedElementsKind(kind);
3709
3710 literals->set(0, Smi::FromInt(kind));
3711 literals->set(1, *element_values);
3712
3713 return factory()->NewArrayLiteral(
3714 literals, values, literal_index, is_simple, depth, pos);
3715 } 3667 }
3716 3668
3717 3669
3718 bool Parser::IsBoilerplateProperty(ObjectLiteral::Property* property) {
3719 return property != NULL &&
3720 property->kind() != ObjectLiteral::Property::PROTOTYPE;
3721 }
3722
3723
3724 bool CompileTimeValue::IsCompileTimeValue(Expression* expression) { 3670 bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
3725 if (expression->AsLiteral() != NULL) return true; 3671 if (expression->AsLiteral() != NULL) return true;
3726 MaterializedLiteral* lit = expression->AsMaterializedLiteral(); 3672 MaterializedLiteral* lit = expression->AsMaterializedLiteral();
3727 return lit != NULL && lit->is_simple(); 3673 return lit != NULL && lit->is_simple();
3728 } 3674 }
3729 3675
3730 3676
3731 Handle<FixedArray> CompileTimeValue::GetValue(Isolate* isolate, 3677 Handle<FixedArray> CompileTimeValue::GetValue(Isolate* isolate,
3732 Expression* expression) { 3678 Expression* expression) {
3733 Factory* factory = isolate->factory(); 3679 Factory* factory = isolate->factory();
(...skipping 23 matching lines...) Expand all
3757 Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot)); 3703 Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot));
3758 return static_cast<LiteralType>(literal_type->value()); 3704 return static_cast<LiteralType>(literal_type->value());
3759 } 3705 }
3760 3706
3761 3707
3762 Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) { 3708 Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3763 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot))); 3709 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3764 } 3710 }
3765 3711
3766 3712
3767 Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
3768 if (expression->AsLiteral() != NULL) {
3769 return expression->AsLiteral()->value();
3770 }
3771 if (CompileTimeValue::IsCompileTimeValue(expression)) {
3772 return CompileTimeValue::GetValue(isolate(), expression);
3773 }
3774 return isolate()->factory()->uninitialized_value();
3775 }
3776
3777
3778 void Parser::BuildObjectLiteralConstantProperties(
3779 ZoneList<ObjectLiteral::Property*>* properties,
3780 Handle<FixedArray> constant_properties,
3781 bool* is_simple,
3782 bool* fast_elements,
3783 int* depth,
3784 bool* may_store_doubles) {
3785 int position = 0;
3786 // Accumulate the value in local variables and store it at the end.
3787 bool is_simple_acc = true;
3788 int depth_acc = 1;
3789 uint32_t max_element_index = 0;
3790 uint32_t elements = 0;
3791 for (int i = 0; i < properties->length(); i++) {
3792 ObjectLiteral::Property* property = properties->at(i);
3793 if (!IsBoilerplateProperty(property)) {
3794 is_simple_acc = false;
3795 continue;
3796 }
3797 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
3798 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
3799 depth_acc = m_literal->depth() + 1;
3800 }
3801
3802 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
3803 // value for COMPUTED properties, the real value is filled in at
3804 // runtime. The enumeration order is maintained.
3805 Handle<Object> key = property->key()->value();
3806 Handle<Object> value = GetBoilerplateValue(property->value());
3807
3808 // Ensure objects that may, at any point in time, contain fields with double
3809 // representation are always treated as nested objects. This is true for
3810 // computed fields (value is undefined), and smi and double literals
3811 // (value->IsNumber()).
3812 // TODO(verwaest): Remove once we can store them inline.
3813 if (FLAG_track_double_fields &&
3814 (value->IsNumber() || value->IsUninitialized())) {
3815 *may_store_doubles = true;
3816 }
3817
3818 is_simple_acc = is_simple_acc && !value->IsUninitialized();
3819
3820 // Keep track of the number of elements in the object literal and
3821 // the largest element index. If the largest element index is
3822 // much larger than the number of elements, creating an object
3823 // literal with fast elements will be a waste of space.
3824 uint32_t element_index = 0;
3825 if (key->IsString()
3826 && Handle<String>::cast(key)->AsArrayIndex(&element_index)
3827 && element_index > max_element_index) {
3828 max_element_index = element_index;
3829 elements++;
3830 } else if (key->IsSmi()) {
3831 int key_value = Smi::cast(*key)->value();
3832 if (key_value > 0
3833 && static_cast<uint32_t>(key_value) > max_element_index) {
3834 max_element_index = key_value;
3835 }
3836 elements++;
3837 }
3838
3839 // Add name, value pair to the fixed array.
3840 constant_properties->set(position++, *key);
3841 constant_properties->set(position++, *value);
3842 }
3843 *fast_elements =
3844 (max_element_index <= 32) || ((2 * elements) >= max_element_index);
3845 *is_simple = is_simple_acc;
3846 *depth = depth_acc;
3847 }
3848
3849
3850 Expression* Parser::ParseObjectLiteral(bool* ok) { 3713 Expression* Parser::ParseObjectLiteral(bool* ok) {
3851 // ObjectLiteral :: 3714 // ObjectLiteral ::
3852 // '{' ( 3715 // '{' (
3853 // ((IdentifierName | String | Number) ':' AssignmentExpression) 3716 // ((IdentifierName | String | Number) ':' AssignmentExpression)
3854 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) 3717 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
3855 // )*[','] '}' 3718 // )*[','] '}'
3856 3719
3857 int pos = peek_position(); 3720 int pos = peek_position();
3858 ZoneList<ObjectLiteral::Property*>* properties = 3721 ZoneList<ObjectLiteral::Property*>* properties =
3859 new(zone()) ZoneList<ObjectLiteral::Property*>(4, zone()); 3722 new(zone()) ZoneList<ObjectLiteral::Property*>(4, zone());
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
3908 ParseFunctionLiteral(name, 3771 ParseFunctionLiteral(name,
3909 false, // reserved words are allowed here 3772 false, // reserved words are allowed here
3910 false, // not a generator 3773 false, // not a generator
3911 RelocInfo::kNoPosition, 3774 RelocInfo::kNoPosition,
3912 FunctionLiteral::ANONYMOUS_EXPRESSION, 3775 FunctionLiteral::ANONYMOUS_EXPRESSION,
3913 CHECK_OK); 3776 CHECK_OK);
3914 // Allow any number of parameters for compatibilty with JSC. 3777 // Allow any number of parameters for compatibilty with JSC.
3915 // Specification only allows zero parameters for get and one for set. 3778 // Specification only allows zero parameters for get and one for set.
3916 ObjectLiteral::Property* property = 3779 ObjectLiteral::Property* property =
3917 factory()->NewObjectLiteralProperty(is_getter, value, next_pos); 3780 factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
3918 if (IsBoilerplateProperty(property)) { 3781 if (ObjectLiteral::IsBoilerplateProperty(property)) {
3919 number_of_boilerplate_properties++; 3782 number_of_boilerplate_properties++;
3920 } 3783 }
3921 properties->Add(property, zone()); 3784 properties->Add(property, zone());
3922 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); 3785 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
3923 3786
3924 if (fni_ != NULL) { 3787 if (fni_ != NULL) {
3925 fni_->Infer(); 3788 fni_->Infer();
3926 fni_->Leave(); 3789 fni_->Leave();
3927 } 3790 }
3928 continue; // restart the while 3791 continue; // restart the while
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
3980 // Mark top-level object literals that contain function literals and 3843 // Mark top-level object literals that contain function literals and
3981 // pretenure the literal so it can be added as a constant function 3844 // pretenure the literal so it can be added as a constant function
3982 // property. 3845 // property.
3983 if (top_scope_->DeclarationScope()->is_global_scope() && 3846 if (top_scope_->DeclarationScope()->is_global_scope() &&
3984 value->AsFunctionLiteral() != NULL) { 3847 value->AsFunctionLiteral() != NULL) {
3985 has_function = true; 3848 has_function = true;
3986 value->AsFunctionLiteral()->set_pretenure(); 3849 value->AsFunctionLiteral()->set_pretenure();
3987 } 3850 }
3988 3851
3989 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. 3852 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
3990 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++; 3853 if (ObjectLiteral::IsBoilerplateProperty(property)) {
3854 number_of_boilerplate_properties++;
3855 }
3991 properties->Add(property, zone()); 3856 properties->Add(property, zone());
3992 3857
3993 // TODO(1240767): Consider allowing trailing comma. 3858 // TODO(1240767): Consider allowing trailing comma.
3994 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); 3859 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
3995 3860
3996 if (fni_ != NULL) { 3861 if (fni_ != NULL) {
3997 fni_->Infer(); 3862 fni_->Infer();
3998 fni_->Leave(); 3863 fni_->Leave();
3999 } 3864 }
4000 } 3865 }
4001 Expect(Token::RBRACE, CHECK_OK); 3866 Expect(Token::RBRACE, CHECK_OK);
4002 3867
4003 // Computation of literal_index must happen before pre parse bailout. 3868 // Computation of literal_index must happen before pre parse bailout.
4004 int literal_index = current_function_state_->NextMaterializedLiteralIndex(); 3869 int literal_index = current_function_state_->NextMaterializedLiteralIndex();
4005 3870
4006 Handle<FixedArray> constant_properties = isolate()->factory()->NewFixedArray( 3871 return factory()->NewObjectLiteral(properties,
4007 number_of_boilerplate_properties * 2, TENURED);
4008
4009 bool is_simple = true;
4010 bool fast_elements = true;
4011 int depth = 1;
4012 bool may_store_doubles = false;
4013 BuildObjectLiteralConstantProperties(properties,
4014 constant_properties,
4015 &is_simple,
4016 &fast_elements,
4017 &depth,
4018 &may_store_doubles);
4019 return factory()->NewObjectLiteral(constant_properties,
4020 properties,
4021 literal_index, 3872 literal_index,
4022 is_simple, 3873 number_of_boilerplate_properties,
4023 fast_elements,
4024 depth,
4025 may_store_doubles,
4026 has_function, 3874 has_function,
4027 pos); 3875 pos);
4028 } 3876 }
4029 3877
4030 3878
4031 Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) { 3879 Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
4032 int pos = peek_position(); 3880 int pos = peek_position();
4033 if (!scanner().ScanRegExpPattern(seen_equal)) { 3881 if (!scanner().ScanRegExpPattern(seen_equal)) {
4034 Next(); 3882 Next();
4035 ReportMessage("unterminated_regexp", Vector<const char*>::empty()); 3883 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
(...skipping 1814 matching lines...) Expand 10 before | Expand all | Expand 10 after
5850 ASSERT(info()->isolate()->has_pending_exception()); 5698 ASSERT(info()->isolate()->has_pending_exception());
5851 } else { 5699 } else {
5852 result = ParseProgram(); 5700 result = ParseProgram();
5853 } 5701 }
5854 } 5702 }
5855 info()->SetFunction(result); 5703 info()->SetFunction(result);
5856 return (result != NULL); 5704 return (result != NULL);
5857 } 5705 }
5858 5706
5859 } } // namespace v8::internal 5707 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698