OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 Expression* ParseArrayLiteral(bool* ok); | 204 Expression* ParseArrayLiteral(bool* ok); |
205 Expression* ParseObjectLiteral(bool* ok); | 205 Expression* ParseObjectLiteral(bool* ok); |
206 Expression* ParseRegExpLiteral(bool seen_equal, bool* ok); | 206 Expression* ParseRegExpLiteral(bool seen_equal, bool* ok); |
207 | 207 |
208 // Populate the constant properties fixed array for a materialized object | 208 // Populate the constant properties fixed array for a materialized object |
209 // literal. | 209 // literal. |
210 void BuildObjectLiteralConstantProperties( | 210 void BuildObjectLiteralConstantProperties( |
211 ZoneList<ObjectLiteral::Property*>* properties, | 211 ZoneList<ObjectLiteral::Property*>* properties, |
212 Handle<FixedArray> constants, | 212 Handle<FixedArray> constants, |
213 bool* is_simple, | 213 bool* is_simple, |
| 214 bool* fast_elements, |
214 int* depth); | 215 int* depth); |
215 | 216 |
216 // Populate the literals fixed array for a materialized array literal. | 217 // Populate the literals fixed array for a materialized array literal. |
217 void BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* properties, | 218 void BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* properties, |
218 Handle<FixedArray> constants, | 219 Handle<FixedArray> constants, |
219 bool* is_simple, | 220 bool* is_simple, |
220 int* depth); | 221 int* depth); |
221 | 222 |
222 // Decide if a property should be in the object boilerplate. | 223 // Decide if a property should be in the object boilerplate. |
223 bool IsBoilerplateProperty(ObjectLiteral::Property* property); | 224 bool IsBoilerplateProperty(ObjectLiteral::Property* property); |
(...skipping 3214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3438 MaterializedLiteral* lit = expression->AsMaterializedLiteral(); | 3439 MaterializedLiteral* lit = expression->AsMaterializedLiteral(); |
3439 return lit != NULL && lit->is_simple(); | 3440 return lit != NULL && lit->is_simple(); |
3440 } | 3441 } |
3441 | 3442 |
3442 Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) { | 3443 Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) { |
3443 ASSERT(IsCompileTimeValue(expression)); | 3444 ASSERT(IsCompileTimeValue(expression)); |
3444 Handle<FixedArray> result = Factory::NewFixedArray(2, TENURED); | 3445 Handle<FixedArray> result = Factory::NewFixedArray(2, TENURED); |
3445 ObjectLiteral* object_literal = expression->AsObjectLiteral(); | 3446 ObjectLiteral* object_literal = expression->AsObjectLiteral(); |
3446 if (object_literal != NULL) { | 3447 if (object_literal != NULL) { |
3447 ASSERT(object_literal->is_simple()); | 3448 ASSERT(object_literal->is_simple()); |
3448 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL)); | 3449 if (object_literal->fast_elements()) { |
| 3450 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS)); |
| 3451 } else { |
| 3452 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS)); |
| 3453 } |
3449 result->set(kElementsSlot, *object_literal->constant_properties()); | 3454 result->set(kElementsSlot, *object_literal->constant_properties()); |
3450 } else { | 3455 } else { |
3451 ArrayLiteral* array_literal = expression->AsArrayLiteral(); | 3456 ArrayLiteral* array_literal = expression->AsArrayLiteral(); |
3452 ASSERT(array_literal != NULL && array_literal->is_simple()); | 3457 ASSERT(array_literal != NULL && array_literal->is_simple()); |
3453 result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL)); | 3458 result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL)); |
3454 result->set(kElementsSlot, *array_literal->constant_elements()); | 3459 result->set(kElementsSlot, *array_literal->constant_elements()); |
3455 } | 3460 } |
3456 return result; | 3461 return result; |
3457 } | 3462 } |
3458 | 3463 |
(...skipping 17 matching lines...) Expand all Loading... |
3476 return CompileTimeValue::GetValue(expression); | 3481 return CompileTimeValue::GetValue(expression); |
3477 } | 3482 } |
3478 return Factory::undefined_value(); | 3483 return Factory::undefined_value(); |
3479 } | 3484 } |
3480 | 3485 |
3481 | 3486 |
3482 void Parser::BuildObjectLiteralConstantProperties( | 3487 void Parser::BuildObjectLiteralConstantProperties( |
3483 ZoneList<ObjectLiteral::Property*>* properties, | 3488 ZoneList<ObjectLiteral::Property*>* properties, |
3484 Handle<FixedArray> constant_properties, | 3489 Handle<FixedArray> constant_properties, |
3485 bool* is_simple, | 3490 bool* is_simple, |
| 3491 bool* fast_elements, |
3486 int* depth) { | 3492 int* depth) { |
3487 int position = 0; | 3493 int position = 0; |
3488 // Accumulate the value in local variables and store it at the end. | 3494 // Accumulate the value in local variables and store it at the end. |
3489 bool is_simple_acc = true; | 3495 bool is_simple_acc = true; |
3490 int depth_acc = 1; | 3496 int depth_acc = 1; |
| 3497 uint32_t max_element_index = 0; |
| 3498 uint32_t elements = 0; |
3491 for (int i = 0; i < properties->length(); i++) { | 3499 for (int i = 0; i < properties->length(); i++) { |
3492 ObjectLiteral::Property* property = properties->at(i); | 3500 ObjectLiteral::Property* property = properties->at(i); |
3493 if (!IsBoilerplateProperty(property)) { | 3501 if (!IsBoilerplateProperty(property)) { |
3494 is_simple_acc = false; | 3502 is_simple_acc = false; |
3495 continue; | 3503 continue; |
3496 } | 3504 } |
3497 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral(); | 3505 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral(); |
3498 if (m_literal != NULL && m_literal->depth() >= depth_acc) { | 3506 if (m_literal != NULL && m_literal->depth() >= depth_acc) { |
3499 depth_acc = m_literal->depth() + 1; | 3507 depth_acc = m_literal->depth() + 1; |
3500 } | 3508 } |
3501 | 3509 |
3502 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined | 3510 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined |
3503 // value for COMPUTED properties, the real value is filled in at | 3511 // value for COMPUTED properties, the real value is filled in at |
3504 // runtime. The enumeration order is maintained. | 3512 // runtime. The enumeration order is maintained. |
3505 Handle<Object> key = property->key()->handle(); | 3513 Handle<Object> key = property->key()->handle(); |
3506 Handle<Object> value = GetBoilerplateValue(property->value()); | 3514 Handle<Object> value = GetBoilerplateValue(property->value()); |
3507 is_simple_acc = is_simple_acc && !value->IsUndefined(); | 3515 is_simple_acc = is_simple_acc && !value->IsUndefined(); |
3508 | 3516 |
| 3517 // Keep track of the number of elements in the object literal and |
| 3518 // the largest element index. If the largest element index is |
| 3519 // much larger than the number of elements, creating an object |
| 3520 // literal with fast elements will be a waste of space. |
| 3521 uint32_t element_index = 0; |
| 3522 if (key->IsString() |
| 3523 && Handle<String>::cast(key)->AsArrayIndex(&element_index) |
| 3524 && element_index > max_element_index) { |
| 3525 max_element_index = element_index; |
| 3526 elements++; |
| 3527 } else if (key->IsSmi()) { |
| 3528 int key_value = Smi::cast(*key)->value(); |
| 3529 if (key_value > 0 |
| 3530 && static_cast<uint32_t>(key_value) > max_element_index) { |
| 3531 max_element_index = key_value; |
| 3532 } |
| 3533 elements++; |
| 3534 } |
| 3535 |
3509 // Add name, value pair to the fixed array. | 3536 // Add name, value pair to the fixed array. |
3510 constant_properties->set(position++, *key); | 3537 constant_properties->set(position++, *key); |
3511 constant_properties->set(position++, *value); | 3538 constant_properties->set(position++, *value); |
3512 } | 3539 } |
3513 | 3540 *fast_elements = |
| 3541 (max_element_index <= 32) || ((2 * elements) >= max_element_index); |
3514 *is_simple = is_simple_acc; | 3542 *is_simple = is_simple_acc; |
3515 *depth = depth_acc; | 3543 *depth = depth_acc; |
3516 } | 3544 } |
3517 | 3545 |
3518 | 3546 |
3519 Expression* Parser::ParseObjectLiteral(bool* ok) { | 3547 Expression* Parser::ParseObjectLiteral(bool* ok) { |
3520 // ObjectLiteral :: | 3548 // ObjectLiteral :: |
3521 // '{' ( | 3549 // '{' ( |
3522 // ((Identifier | String | Number) ':' AssignmentExpression) | 3550 // ((Identifier | String | Number) ':' AssignmentExpression) |
3523 // | (('get' | 'set') FunctionLiteral) | 3551 // | (('get' | 'set') FunctionLiteral) |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3601 } | 3629 } |
3602 Expect(Token::RBRACE, CHECK_OK); | 3630 Expect(Token::RBRACE, CHECK_OK); |
3603 // Computation of literal_index must happen before pre parse bailout. | 3631 // Computation of literal_index must happen before pre parse bailout. |
3604 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); | 3632 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); |
3605 if (is_pre_parsing_) return NULL; | 3633 if (is_pre_parsing_) return NULL; |
3606 | 3634 |
3607 Handle<FixedArray> constant_properties = | 3635 Handle<FixedArray> constant_properties = |
3608 Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED); | 3636 Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED); |
3609 | 3637 |
3610 bool is_simple = true; | 3638 bool is_simple = true; |
| 3639 bool fast_elements = true; |
3611 int depth = 1; | 3640 int depth = 1; |
3612 BuildObjectLiteralConstantProperties(properties.elements(), | 3641 BuildObjectLiteralConstantProperties(properties.elements(), |
3613 constant_properties, | 3642 constant_properties, |
3614 &is_simple, | 3643 &is_simple, |
| 3644 &fast_elements, |
3615 &depth); | 3645 &depth); |
3616 return new ObjectLiteral(constant_properties, | 3646 return new ObjectLiteral(constant_properties, |
3617 properties.elements(), | 3647 properties.elements(), |
3618 literal_index, | 3648 literal_index, |
3619 is_simple, | 3649 is_simple, |
| 3650 fast_elements, |
3620 depth); | 3651 depth); |
3621 } | 3652 } |
3622 | 3653 |
3623 | 3654 |
3624 Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) { | 3655 Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) { |
3625 if (!scanner_.ScanRegExpPattern(seen_equal)) { | 3656 if (!scanner_.ScanRegExpPattern(seen_equal)) { |
3626 Next(); | 3657 Next(); |
3627 ReportMessage("unterminated_regexp", Vector<const char*>::empty()); | 3658 ReportMessage("unterminated_regexp", Vector<const char*>::empty()); |
3628 *ok = false; | 3659 *ok = false; |
3629 return NULL; | 3660 return NULL; |
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4116 } while (Check(Token::COMMA)); | 4147 } while (Check(Token::COMMA)); |
4117 } | 4148 } |
4118 Expect(Token::RBRACE, CHECK_OK); | 4149 Expect(Token::RBRACE, CHECK_OK); |
4119 | 4150 |
4120 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); | 4151 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); |
4121 if (is_pre_parsing_) return NULL; | 4152 if (is_pre_parsing_) return NULL; |
4122 | 4153 |
4123 Handle<FixedArray> constant_properties = | 4154 Handle<FixedArray> constant_properties = |
4124 Factory::NewFixedArray(boilerplate_properties * 2, TENURED); | 4155 Factory::NewFixedArray(boilerplate_properties * 2, TENURED); |
4125 bool is_simple = true; | 4156 bool is_simple = true; |
| 4157 bool fast_elements = true; |
4126 int depth = 1; | 4158 int depth = 1; |
4127 BuildObjectLiteralConstantProperties(properties.elements(), | 4159 BuildObjectLiteralConstantProperties(properties.elements(), |
4128 constant_properties, | 4160 constant_properties, |
4129 &is_simple, | 4161 &is_simple, |
| 4162 &fast_elements, |
4130 &depth); | 4163 &depth); |
4131 return new ObjectLiteral(constant_properties, | 4164 return new ObjectLiteral(constant_properties, |
4132 properties.elements(), | 4165 properties.elements(), |
4133 literal_index, | 4166 literal_index, |
4134 is_simple, | 4167 is_simple, |
| 4168 fast_elements, |
4135 depth); | 4169 depth); |
4136 } | 4170 } |
4137 | 4171 |
4138 | 4172 |
4139 // Parse a JSON array. Scanner must be right after '[' token. | 4173 // Parse a JSON array. Scanner must be right after '[' token. |
4140 Expression* Parser::ParseJsonArray(bool* ok) { | 4174 Expression* Parser::ParseJsonArray(bool* ok) { |
4141 Consume(Token::LBRACK); | 4175 Consume(Token::LBRACK); |
4142 | 4176 |
4143 ZoneListWrapper<Expression> values = factory()->NewList<Expression>(4); | 4177 ZoneListWrapper<Expression> values = factory()->NewList<Expression>(4); |
4144 if (peek() != Token::RBRACK) { | 4178 if (peek() != Token::RBRACK) { |
(...skipping 944 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5089 parser.ParseLazy(script_source, name, | 5123 parser.ParseLazy(script_source, name, |
5090 start_position, end_position, is_expression); | 5124 start_position, end_position, is_expression); |
5091 return result; | 5125 return result; |
5092 } | 5126 } |
5093 | 5127 |
5094 | 5128 |
5095 #undef NEW | 5129 #undef NEW |
5096 | 5130 |
5097 | 5131 |
5098 } } // namespace v8::internal | 5132 } } // namespace v8::internal |
OLD | NEW |