| 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 12 matching lines...) Expand all Loading... |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "api.h" | 30 #include "api.h" |
| 31 #include "ast.h" | 31 #include "ast.h" |
| 32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
| 33 #include "codegen.h" |
| 33 #include "compiler.h" | 34 #include "compiler.h" |
| 34 #include "messages.h" | 35 #include "messages.h" |
| 35 #include "platform.h" | 36 #include "platform.h" |
| 36 #include "runtime.h" | 37 #include "runtime.h" |
| 37 #include "parser.h" | 38 #include "parser.h" |
| 38 #include "scopes.h" | 39 #include "scopes.h" |
| 39 #include "string-stream.h" | 40 #include "string-stream.h" |
| 40 | 41 |
| 41 namespace v8 { | 42 namespace v8 { |
| 42 namespace internal { | 43 namespace internal { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 TemporaryScope* temp_scope_; | 141 TemporaryScope* temp_scope_; |
| 141 Mode mode_; | 142 Mode mode_; |
| 142 | 143 |
| 143 Target* target_stack_; // for break, continue statements | 144 Target* target_stack_; // for break, continue statements |
| 144 bool allow_natives_syntax_; | 145 bool allow_natives_syntax_; |
| 145 v8::Extension* extension_; | 146 v8::Extension* extension_; |
| 146 ParserFactory* factory_; | 147 ParserFactory* factory_; |
| 147 ParserLog* log_; | 148 ParserLog* log_; |
| 148 bool is_pre_parsing_; | 149 bool is_pre_parsing_; |
| 149 ScriptDataImpl* pre_data_; | 150 ScriptDataImpl* pre_data_; |
| 151 bool seen_loop_stmt_; // Used for inner loop detection. |
| 150 | 152 |
| 151 bool inside_with() const { return with_nesting_level_ > 0; } | 153 bool inside_with() const { return with_nesting_level_ > 0; } |
| 152 ParserFactory* factory() const { return factory_; } | 154 ParserFactory* factory() const { return factory_; } |
| 153 ParserLog* log() const { return log_; } | 155 ParserLog* log() const { return log_; } |
| 154 Scanner& scanner() { return scanner_; } | 156 Scanner& scanner() { return scanner_; } |
| 155 Mode mode() const { return mode_; } | 157 Mode mode() const { return mode_; } |
| 156 ScriptDataImpl* pre_data() const { return pre_data_; } | 158 ScriptDataImpl* pre_data() const { return pre_data_; } |
| 157 | 159 |
| 158 // All ParseXXX functions take as the last argument an *ok parameter | 160 // All ParseXXX functions take as the last argument an *ok parameter |
| 159 // which is set to false if parsing failed; it is unchanged otherwise. | 161 // which is set to false if parsing failed; it is unchanged otherwise. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 Expression* ParseArrayLiteral(bool* ok); | 206 Expression* ParseArrayLiteral(bool* ok); |
| 205 Expression* ParseObjectLiteral(bool* ok); | 207 Expression* ParseObjectLiteral(bool* ok); |
| 206 Expression* ParseRegExpLiteral(bool seen_equal, bool* ok); | 208 Expression* ParseRegExpLiteral(bool seen_equal, bool* ok); |
| 207 | 209 |
| 208 // Populate the constant properties fixed array for a materialized object | 210 // Populate the constant properties fixed array for a materialized object |
| 209 // literal. | 211 // literal. |
| 210 void BuildObjectLiteralConstantProperties( | 212 void BuildObjectLiteralConstantProperties( |
| 211 ZoneList<ObjectLiteral::Property*>* properties, | 213 ZoneList<ObjectLiteral::Property*>* properties, |
| 212 Handle<FixedArray> constants, | 214 Handle<FixedArray> constants, |
| 213 bool* is_simple, | 215 bool* is_simple, |
| 216 bool* fast_elements, |
| 214 int* depth); | 217 int* depth); |
| 215 | 218 |
| 216 // Populate the literals fixed array for a materialized array literal. | 219 // Populate the literals fixed array for a materialized array literal. |
| 217 void BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* properties, | 220 void BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* properties, |
| 218 Handle<FixedArray> constants, | 221 Handle<FixedArray> constants, |
| 219 bool* is_simple, | 222 bool* is_simple, |
| 220 int* depth); | 223 int* depth); |
| 221 | 224 |
| 222 // Decide if a property should be in the object boilerplate. | 225 // Decide if a property should be in the object boilerplate. |
| 223 bool IsBoilerplateProperty(ObjectLiteral::Property* property); | 226 bool IsBoilerplateProperty(ObjectLiteral::Property* property); |
| (...skipping 972 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1196 scanner_(is_pre_parsing), | 1199 scanner_(is_pre_parsing), |
| 1197 top_scope_(NULL), | 1200 top_scope_(NULL), |
| 1198 with_nesting_level_(0), | 1201 with_nesting_level_(0), |
| 1199 temp_scope_(NULL), | 1202 temp_scope_(NULL), |
| 1200 target_stack_(NULL), | 1203 target_stack_(NULL), |
| 1201 allow_natives_syntax_(allow_natives_syntax), | 1204 allow_natives_syntax_(allow_natives_syntax), |
| 1202 extension_(extension), | 1205 extension_(extension), |
| 1203 factory_(factory), | 1206 factory_(factory), |
| 1204 log_(log), | 1207 log_(log), |
| 1205 is_pre_parsing_(is_pre_parsing == PREPARSE), | 1208 is_pre_parsing_(is_pre_parsing == PREPARSE), |
| 1206 pre_data_(pre_data) { | 1209 pre_data_(pre_data), |
| 1210 seen_loop_stmt_(false) { |
| 1207 } | 1211 } |
| 1208 | 1212 |
| 1209 | 1213 |
| 1210 bool Parser::PreParseProgram(Handle<String> source, | 1214 bool Parser::PreParseProgram(Handle<String> source, |
| 1211 unibrow::CharacterStream* stream) { | 1215 unibrow::CharacterStream* stream) { |
| 1212 HistogramTimerScope timer(&Counters::pre_parse); | 1216 HistogramTimerScope timer(&Counters::pre_parse); |
| 1213 AssertNoZoneAllocation assert_no_zone_allocation; | 1217 AssertNoZoneAllocation assert_no_zone_allocation; |
| 1214 AssertNoAllocation assert_no_allocation; | 1218 AssertNoAllocation assert_no_allocation; |
| 1215 NoHandleAllocation no_handle_allocation; | 1219 NoHandleAllocation no_handle_allocation; |
| 1216 scanner_.Initialize(source, stream, JAVASCRIPT); | 1220 scanner_.Initialize(source, stream, JAVASCRIPT); |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1576 Property* property = assignment->target()->AsProperty(); | 1580 Property* property = assignment->target()->AsProperty(); |
| 1577 return assignment->op() == Token::ASSIGN | 1581 return assignment->op() == Token::ASSIGN |
| 1578 && property != NULL | 1582 && property != NULL |
| 1579 && property->obj()->AsVariableProxy() != NULL | 1583 && property->obj()->AsVariableProxy() != NULL |
| 1580 && property->obj()->AsVariableProxy()->is_this(); | 1584 && property->obj()->AsVariableProxy()->is_this(); |
| 1581 } | 1585 } |
| 1582 return false; | 1586 return false; |
| 1583 } | 1587 } |
| 1584 | 1588 |
| 1585 void HandleThisPropertyAssignment(Scope* scope, Assignment* assignment) { | 1589 void HandleThisPropertyAssignment(Scope* scope, Assignment* assignment) { |
| 1586 // Check that the property assigned to is a named property. | 1590 // Check that the property assigned to is a named property, which is not |
| 1591 // __proto__. |
| 1587 Property* property = assignment->target()->AsProperty(); | 1592 Property* property = assignment->target()->AsProperty(); |
| 1588 ASSERT(property != NULL); | 1593 ASSERT(property != NULL); |
| 1589 Literal* literal = property->key()->AsLiteral(); | 1594 Literal* literal = property->key()->AsLiteral(); |
| 1590 uint32_t dummy; | 1595 uint32_t dummy; |
| 1591 if (literal != NULL && | 1596 if (literal != NULL && |
| 1592 literal->handle()->IsString() && | 1597 literal->handle()->IsString() && |
| 1598 !String::cast(*(literal->handle()))->Equals(Heap::Proto_symbol()) && |
| 1593 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) { | 1599 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) { |
| 1594 Handle<String> key = Handle<String>::cast(literal->handle()); | 1600 Handle<String> key = Handle<String>::cast(literal->handle()); |
| 1595 | 1601 |
| 1596 // Check whether the value assigned is either a constant or matches the | 1602 // Check whether the value assigned is either a constant or matches the |
| 1597 // name of one of the arguments to the function. | 1603 // name of one of the arguments to the function. |
| 1598 if (assignment->value()->AsLiteral() != NULL) { | 1604 if (assignment->value()->AsLiteral() != NULL) { |
| 1599 // Constant assigned. | 1605 // Constant assigned. |
| 1600 Literal* literal = assignment->value()->AsLiteral(); | 1606 Literal* literal = assignment->value()->AsLiteral(); |
| 1601 AssignmentFromConstant(key, literal->handle()); | 1607 AssignmentFromConstant(key, literal->handle()); |
| 1602 return; | 1608 return; |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1955 | 1961 |
| 1956 // Instantiate the function and create a boilerplate function from it. | 1962 // Instantiate the function and create a boilerplate function from it. |
| 1957 Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction()); | 1963 Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction()); |
| 1958 const int literals = fun->NumberOfLiterals(); | 1964 const int literals = fun->NumberOfLiterals(); |
| 1959 Handle<Code> code = Handle<Code>(fun->shared()->code()); | 1965 Handle<Code> code = Handle<Code>(fun->shared()->code()); |
| 1960 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub()); | 1966 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub()); |
| 1961 Handle<JSFunction> boilerplate = | 1967 Handle<JSFunction> boilerplate = |
| 1962 Factory::NewFunctionBoilerplate(name, literals, code); | 1968 Factory::NewFunctionBoilerplate(name, literals, code); |
| 1963 boilerplate->shared()->set_construct_stub(*construct_stub); | 1969 boilerplate->shared()->set_construct_stub(*construct_stub); |
| 1964 | 1970 |
| 1965 // Copy the function data to the boilerplate. Used by | 1971 // Copy the function data to the boilerplate. |
| 1966 // builtins.cc:HandleApiCall to perform argument type checks and to | |
| 1967 // find the right native code to call. | |
| 1968 boilerplate->shared()->set_function_data(fun->shared()->function_data()); | 1972 boilerplate->shared()->set_function_data(fun->shared()->function_data()); |
| 1969 int parameters = fun->shared()->formal_parameter_count(); | 1973 int parameters = fun->shared()->formal_parameter_count(); |
| 1970 boilerplate->shared()->set_formal_parameter_count(parameters); | 1974 boilerplate->shared()->set_formal_parameter_count(parameters); |
| 1971 | 1975 |
| 1972 // TODO(1240846): It's weird that native function declarations are | 1976 // TODO(1240846): It's weird that native function declarations are |
| 1973 // introduced dynamically when we meet their declarations, whereas | 1977 // introduced dynamically when we meet their declarations, whereas |
| 1974 // other functions are setup when entering the surrounding scope. | 1978 // other functions are setup when entering the surrounding scope. |
| 1975 FunctionBoilerplateLiteral* lit = | 1979 FunctionBoilerplateLiteral* lit = |
| 1976 NEW(FunctionBoilerplateLiteral(boilerplate)); | 1980 NEW(FunctionBoilerplateLiteral(boilerplate)); |
| 1977 VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK); | 1981 VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK); |
| (...skipping 666 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2644 Expression* cond = ParseExpression(true, CHECK_OK); | 2648 Expression* cond = ParseExpression(true, CHECK_OK); |
| 2645 Expect(Token::RPAREN, CHECK_OK); | 2649 Expect(Token::RPAREN, CHECK_OK); |
| 2646 | 2650 |
| 2647 // Allow do-statements to be terminated with and without | 2651 // Allow do-statements to be terminated with and without |
| 2648 // semi-colons. This allows code such as 'do;while(0)return' to | 2652 // semi-colons. This allows code such as 'do;while(0)return' to |
| 2649 // parse, which would not be the case if we had used the | 2653 // parse, which would not be the case if we had used the |
| 2650 // ExpectSemicolon() functionality here. | 2654 // ExpectSemicolon() functionality here. |
| 2651 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON); | 2655 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON); |
| 2652 | 2656 |
| 2653 if (loop != NULL) loop->Initialize(cond, body); | 2657 if (loop != NULL) loop->Initialize(cond, body); |
| 2658 |
| 2659 seen_loop_stmt_ = true; |
| 2660 |
| 2654 return loop; | 2661 return loop; |
| 2655 } | 2662 } |
| 2656 | 2663 |
| 2657 | 2664 |
| 2658 WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) { | 2665 WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) { |
| 2659 // WhileStatement :: | 2666 // WhileStatement :: |
| 2660 // 'while' '(' Expression ')' Statement | 2667 // 'while' '(' Expression ')' Statement |
| 2661 | 2668 |
| 2662 WhileStatement* loop = NEW(WhileStatement(labels)); | 2669 WhileStatement* loop = NEW(WhileStatement(labels)); |
| 2663 Target target(this, loop); | 2670 Target target(this, loop); |
| 2664 | 2671 |
| 2665 Expect(Token::WHILE, CHECK_OK); | 2672 Expect(Token::WHILE, CHECK_OK); |
| 2666 Expect(Token::LPAREN, CHECK_OK); | 2673 Expect(Token::LPAREN, CHECK_OK); |
| 2667 Expression* cond = ParseExpression(true, CHECK_OK); | 2674 Expression* cond = ParseExpression(true, CHECK_OK); |
| 2668 Expect(Token::RPAREN, CHECK_OK); | 2675 Expect(Token::RPAREN, CHECK_OK); |
| 2669 Statement* body = ParseStatement(NULL, CHECK_OK); | 2676 Statement* body = ParseStatement(NULL, CHECK_OK); |
| 2670 | 2677 |
| 2671 if (loop != NULL) loop->Initialize(cond, body); | 2678 if (loop != NULL) loop->Initialize(cond, body); |
| 2679 |
| 2680 seen_loop_stmt_ = true; |
| 2681 |
| 2672 return loop; | 2682 return loop; |
| 2673 } | 2683 } |
| 2674 | 2684 |
| 2675 | 2685 |
| 2676 Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { | 2686 Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { |
| 2677 // ForStatement :: | 2687 // ForStatement :: |
| 2678 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 2688 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
| 2679 | 2689 |
| 2680 Statement* init = NULL; | 2690 Statement* init = NULL; |
| 2681 | 2691 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2695 Expect(Token::RPAREN, CHECK_OK); | 2705 Expect(Token::RPAREN, CHECK_OK); |
| 2696 | 2706 |
| 2697 Statement* body = ParseStatement(NULL, CHECK_OK); | 2707 Statement* body = ParseStatement(NULL, CHECK_OK); |
| 2698 if (is_pre_parsing_) { | 2708 if (is_pre_parsing_) { |
| 2699 return NULL; | 2709 return NULL; |
| 2700 } else { | 2710 } else { |
| 2701 loop->Initialize(each, enumerable, body); | 2711 loop->Initialize(each, enumerable, body); |
| 2702 Block* result = NEW(Block(NULL, 2, false)); | 2712 Block* result = NEW(Block(NULL, 2, false)); |
| 2703 result->AddStatement(variable_statement); | 2713 result->AddStatement(variable_statement); |
| 2704 result->AddStatement(loop); | 2714 result->AddStatement(loop); |
| 2715 |
| 2716 seen_loop_stmt_ = true; |
| 2717 |
| 2705 // Parsed for-in loop w/ variable/const declaration. | 2718 // Parsed for-in loop w/ variable/const declaration. |
| 2706 return result; | 2719 return result; |
| 2707 } | 2720 } |
| 2708 | 2721 |
| 2709 } else { | 2722 } else { |
| 2710 init = variable_statement; | 2723 init = variable_statement; |
| 2711 } | 2724 } |
| 2712 | 2725 |
| 2713 } else { | 2726 } else { |
| 2714 Expression* expression = ParseExpression(false, CHECK_OK); | 2727 Expression* expression = ParseExpression(false, CHECK_OK); |
| 2715 if (peek() == Token::IN) { | 2728 if (peek() == Token::IN) { |
| 2716 // Signal a reference error if the expression is an invalid | 2729 // Signal a reference error if the expression is an invalid |
| 2717 // left-hand side expression. We could report this as a syntax | 2730 // left-hand side expression. We could report this as a syntax |
| 2718 // error here but for compatibility with JSC we choose to report | 2731 // error here but for compatibility with JSC we choose to report |
| 2719 // the error at runtime. | 2732 // the error at runtime. |
| 2720 if (expression == NULL || !expression->IsValidLeftHandSide()) { | 2733 if (expression == NULL || !expression->IsValidLeftHandSide()) { |
| 2721 Handle<String> type = Factory::invalid_lhs_in_for_in_symbol(); | 2734 Handle<String> type = Factory::invalid_lhs_in_for_in_symbol(); |
| 2722 expression = NewThrowReferenceError(type); | 2735 expression = NewThrowReferenceError(type); |
| 2723 } | 2736 } |
| 2724 ForInStatement* loop = NEW(ForInStatement(labels)); | 2737 ForInStatement* loop = NEW(ForInStatement(labels)); |
| 2725 Target target(this, loop); | 2738 Target target(this, loop); |
| 2726 | 2739 |
| 2727 Expect(Token::IN, CHECK_OK); | 2740 Expect(Token::IN, CHECK_OK); |
| 2728 Expression* enumerable = ParseExpression(true, CHECK_OK); | 2741 Expression* enumerable = ParseExpression(true, CHECK_OK); |
| 2729 Expect(Token::RPAREN, CHECK_OK); | 2742 Expect(Token::RPAREN, CHECK_OK); |
| 2730 | 2743 |
| 2731 Statement* body = ParseStatement(NULL, CHECK_OK); | 2744 Statement* body = ParseStatement(NULL, CHECK_OK); |
| 2732 if (loop) loop->Initialize(expression, enumerable, body); | 2745 if (loop) loop->Initialize(expression, enumerable, body); |
| 2733 | 2746 |
| 2747 seen_loop_stmt_ = true; |
| 2748 |
| 2734 // Parsed for-in loop. | 2749 // Parsed for-in loop. |
| 2735 return loop; | 2750 return loop; |
| 2736 | 2751 |
| 2737 } else { | 2752 } else { |
| 2738 init = NEW(ExpressionStatement(expression)); | 2753 init = NEW(ExpressionStatement(expression)); |
| 2739 } | 2754 } |
| 2740 } | 2755 } |
| 2741 } | 2756 } |
| 2742 | 2757 |
| 2743 // Standard 'for' loop | 2758 // Standard 'for' loop |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2756 } | 2771 } |
| 2757 Expect(Token::SEMICOLON, CHECK_OK); | 2772 Expect(Token::SEMICOLON, CHECK_OK); |
| 2758 | 2773 |
| 2759 Statement* next = NULL; | 2774 Statement* next = NULL; |
| 2760 if (peek() != Token::RPAREN) { | 2775 if (peek() != Token::RPAREN) { |
| 2761 Expression* exp = ParseExpression(true, CHECK_OK); | 2776 Expression* exp = ParseExpression(true, CHECK_OK); |
| 2762 next = NEW(ExpressionStatement(exp)); | 2777 next = NEW(ExpressionStatement(exp)); |
| 2763 } | 2778 } |
| 2764 Expect(Token::RPAREN, CHECK_OK); | 2779 Expect(Token::RPAREN, CHECK_OK); |
| 2765 | 2780 |
| 2781 seen_loop_stmt_ = false; |
| 2782 |
| 2766 Statement* body = ParseStatement(NULL, CHECK_OK); | 2783 Statement* body = ParseStatement(NULL, CHECK_OK); |
| 2767 | 2784 |
| 2785 // Mark this loop if it is an inner loop. |
| 2786 if (loop && !seen_loop_stmt_) loop->set_peel_this_loop(true); |
| 2787 |
| 2768 if (loop) loop->Initialize(init, cond, next, body); | 2788 if (loop) loop->Initialize(init, cond, next, body); |
| 2789 |
| 2790 seen_loop_stmt_ = true; |
| 2791 |
| 2769 return loop; | 2792 return loop; |
| 2770 } | 2793 } |
| 2771 | 2794 |
| 2772 | 2795 |
| 2773 // Precedence = 1 | 2796 // Precedence = 1 |
| 2774 Expression* Parser::ParseExpression(bool accept_IN, bool* ok) { | 2797 Expression* Parser::ParseExpression(bool accept_IN, bool* ok) { |
| 2775 // Expression :: | 2798 // Expression :: |
| 2776 // AssignmentExpression | 2799 // AssignmentExpression |
| 2777 // Expression ',' AssignmentExpression | 2800 // Expression ',' AssignmentExpression |
| 2778 | 2801 |
| (...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3438 MaterializedLiteral* lit = expression->AsMaterializedLiteral(); | 3461 MaterializedLiteral* lit = expression->AsMaterializedLiteral(); |
| 3439 return lit != NULL && lit->is_simple(); | 3462 return lit != NULL && lit->is_simple(); |
| 3440 } | 3463 } |
| 3441 | 3464 |
| 3442 Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) { | 3465 Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) { |
| 3443 ASSERT(IsCompileTimeValue(expression)); | 3466 ASSERT(IsCompileTimeValue(expression)); |
| 3444 Handle<FixedArray> result = Factory::NewFixedArray(2, TENURED); | 3467 Handle<FixedArray> result = Factory::NewFixedArray(2, TENURED); |
| 3445 ObjectLiteral* object_literal = expression->AsObjectLiteral(); | 3468 ObjectLiteral* object_literal = expression->AsObjectLiteral(); |
| 3446 if (object_literal != NULL) { | 3469 if (object_literal != NULL) { |
| 3447 ASSERT(object_literal->is_simple()); | 3470 ASSERT(object_literal->is_simple()); |
| 3448 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL)); | 3471 if (object_literal->fast_elements()) { |
| 3472 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS)); |
| 3473 } else { |
| 3474 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS)); |
| 3475 } |
| 3449 result->set(kElementsSlot, *object_literal->constant_properties()); | 3476 result->set(kElementsSlot, *object_literal->constant_properties()); |
| 3450 } else { | 3477 } else { |
| 3451 ArrayLiteral* array_literal = expression->AsArrayLiteral(); | 3478 ArrayLiteral* array_literal = expression->AsArrayLiteral(); |
| 3452 ASSERT(array_literal != NULL && array_literal->is_simple()); | 3479 ASSERT(array_literal != NULL && array_literal->is_simple()); |
| 3453 result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL)); | 3480 result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL)); |
| 3454 result->set(kElementsSlot, *array_literal->constant_elements()); | 3481 result->set(kElementsSlot, *array_literal->constant_elements()); |
| 3455 } | 3482 } |
| 3456 return result; | 3483 return result; |
| 3457 } | 3484 } |
| 3458 | 3485 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3476 return CompileTimeValue::GetValue(expression); | 3503 return CompileTimeValue::GetValue(expression); |
| 3477 } | 3504 } |
| 3478 return Factory::undefined_value(); | 3505 return Factory::undefined_value(); |
| 3479 } | 3506 } |
| 3480 | 3507 |
| 3481 | 3508 |
| 3482 void Parser::BuildObjectLiteralConstantProperties( | 3509 void Parser::BuildObjectLiteralConstantProperties( |
| 3483 ZoneList<ObjectLiteral::Property*>* properties, | 3510 ZoneList<ObjectLiteral::Property*>* properties, |
| 3484 Handle<FixedArray> constant_properties, | 3511 Handle<FixedArray> constant_properties, |
| 3485 bool* is_simple, | 3512 bool* is_simple, |
| 3513 bool* fast_elements, |
| 3486 int* depth) { | 3514 int* depth) { |
| 3487 int position = 0; | 3515 int position = 0; |
| 3488 // Accumulate the value in local variables and store it at the end. | 3516 // Accumulate the value in local variables and store it at the end. |
| 3489 bool is_simple_acc = true; | 3517 bool is_simple_acc = true; |
| 3490 int depth_acc = 1; | 3518 int depth_acc = 1; |
| 3519 uint32_t max_element_index = 0; |
| 3520 uint32_t elements = 0; |
| 3491 for (int i = 0; i < properties->length(); i++) { | 3521 for (int i = 0; i < properties->length(); i++) { |
| 3492 ObjectLiteral::Property* property = properties->at(i); | 3522 ObjectLiteral::Property* property = properties->at(i); |
| 3493 if (!IsBoilerplateProperty(property)) { | 3523 if (!IsBoilerplateProperty(property)) { |
| 3494 is_simple_acc = false; | 3524 is_simple_acc = false; |
| 3495 continue; | 3525 continue; |
| 3496 } | 3526 } |
| 3497 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral(); | 3527 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral(); |
| 3498 if (m_literal != NULL && m_literal->depth() >= depth_acc) { | 3528 if (m_literal != NULL && m_literal->depth() >= depth_acc) { |
| 3499 depth_acc = m_literal->depth() + 1; | 3529 depth_acc = m_literal->depth() + 1; |
| 3500 } | 3530 } |
| 3501 | 3531 |
| 3502 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined | 3532 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined |
| 3503 // value for COMPUTED properties, the real value is filled in at | 3533 // value for COMPUTED properties, the real value is filled in at |
| 3504 // runtime. The enumeration order is maintained. | 3534 // runtime. The enumeration order is maintained. |
| 3505 Handle<Object> key = property->key()->handle(); | 3535 Handle<Object> key = property->key()->handle(); |
| 3506 Handle<Object> value = GetBoilerplateValue(property->value()); | 3536 Handle<Object> value = GetBoilerplateValue(property->value()); |
| 3507 is_simple_acc = is_simple_acc && !value->IsUndefined(); | 3537 is_simple_acc = is_simple_acc && !value->IsUndefined(); |
| 3508 | 3538 |
| 3539 // Keep track of the number of elements in the object literal and |
| 3540 // the largest element index. If the largest element index is |
| 3541 // much larger than the number of elements, creating an object |
| 3542 // literal with fast elements will be a waste of space. |
| 3543 uint32_t element_index = 0; |
| 3544 if (key->IsString() |
| 3545 && Handle<String>::cast(key)->AsArrayIndex(&element_index) |
| 3546 && element_index > max_element_index) { |
| 3547 max_element_index = element_index; |
| 3548 elements++; |
| 3549 } else if (key->IsSmi()) { |
| 3550 int key_value = Smi::cast(*key)->value(); |
| 3551 if (key_value > 0 |
| 3552 && static_cast<uint32_t>(key_value) > max_element_index) { |
| 3553 max_element_index = key_value; |
| 3554 } |
| 3555 elements++; |
| 3556 } |
| 3557 |
| 3509 // Add name, value pair to the fixed array. | 3558 // Add name, value pair to the fixed array. |
| 3510 constant_properties->set(position++, *key); | 3559 constant_properties->set(position++, *key); |
| 3511 constant_properties->set(position++, *value); | 3560 constant_properties->set(position++, *value); |
| 3512 } | 3561 } |
| 3513 | 3562 *fast_elements = |
| 3563 (max_element_index <= 32) || ((2 * elements) >= max_element_index); |
| 3514 *is_simple = is_simple_acc; | 3564 *is_simple = is_simple_acc; |
| 3515 *depth = depth_acc; | 3565 *depth = depth_acc; |
| 3516 } | 3566 } |
| 3517 | 3567 |
| 3518 | 3568 |
| 3519 Expression* Parser::ParseObjectLiteral(bool* ok) { | 3569 Expression* Parser::ParseObjectLiteral(bool* ok) { |
| 3520 // ObjectLiteral :: | 3570 // ObjectLiteral :: |
| 3521 // '{' ( | 3571 // '{' ( |
| 3522 // ((Identifier | String | Number) ':' AssignmentExpression) | 3572 // ((Identifier | String | Number) ':' AssignmentExpression) |
| 3523 // | (('get' | 'set') FunctionLiteral) | 3573 // | (('get' | 'set') FunctionLiteral) |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3601 } | 3651 } |
| 3602 Expect(Token::RBRACE, CHECK_OK); | 3652 Expect(Token::RBRACE, CHECK_OK); |
| 3603 // Computation of literal_index must happen before pre parse bailout. | 3653 // Computation of literal_index must happen before pre parse bailout. |
| 3604 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); | 3654 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); |
| 3605 if (is_pre_parsing_) return NULL; | 3655 if (is_pre_parsing_) return NULL; |
| 3606 | 3656 |
| 3607 Handle<FixedArray> constant_properties = | 3657 Handle<FixedArray> constant_properties = |
| 3608 Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED); | 3658 Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED); |
| 3609 | 3659 |
| 3610 bool is_simple = true; | 3660 bool is_simple = true; |
| 3661 bool fast_elements = true; |
| 3611 int depth = 1; | 3662 int depth = 1; |
| 3612 BuildObjectLiteralConstantProperties(properties.elements(), | 3663 BuildObjectLiteralConstantProperties(properties.elements(), |
| 3613 constant_properties, | 3664 constant_properties, |
| 3614 &is_simple, | 3665 &is_simple, |
| 3666 &fast_elements, |
| 3615 &depth); | 3667 &depth); |
| 3616 return new ObjectLiteral(constant_properties, | 3668 return new ObjectLiteral(constant_properties, |
| 3617 properties.elements(), | 3669 properties.elements(), |
| 3618 literal_index, | 3670 literal_index, |
| 3619 is_simple, | 3671 is_simple, |
| 3672 fast_elements, |
| 3620 depth); | 3673 depth); |
| 3621 } | 3674 } |
| 3622 | 3675 |
| 3623 | 3676 |
| 3624 Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) { | 3677 Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) { |
| 3625 if (!scanner_.ScanRegExpPattern(seen_equal)) { | 3678 if (!scanner_.ScanRegExpPattern(seen_equal)) { |
| 3626 Next(); | 3679 Next(); |
| 3627 ReportMessage("unterminated_regexp", Vector<const char*>::empty()); | 3680 ReportMessage("unterminated_regexp", Vector<const char*>::empty()); |
| 3628 *ok = false; | 3681 *ok = false; |
| 3629 return NULL; | 3682 return NULL; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3673 } | 3726 } |
| 3674 | 3727 |
| 3675 | 3728 |
| 3676 FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, | 3729 FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, |
| 3677 int function_token_position, | 3730 int function_token_position, |
| 3678 FunctionLiteralType type, | 3731 FunctionLiteralType type, |
| 3679 bool* ok) { | 3732 bool* ok) { |
| 3680 // Function :: | 3733 // Function :: |
| 3681 // '(' FormalParameterList? ')' '{' FunctionBody '}' | 3734 // '(' FormalParameterList? ')' '{' FunctionBody '}' |
| 3682 | 3735 |
| 3736 // Reset flag used for inner loop detection. |
| 3737 seen_loop_stmt_ = false; |
| 3738 |
| 3683 bool is_named = !var_name.is_null(); | 3739 bool is_named = !var_name.is_null(); |
| 3684 | 3740 |
| 3685 // The name associated with this function. If it's a function expression, | 3741 // The name associated with this function. If it's a function expression, |
| 3686 // this is the actual function name, otherwise this is the name of the | 3742 // this is the actual function name, otherwise this is the name of the |
| 3687 // variable declared and initialized with the function (expression). In | 3743 // variable declared and initialized with the function (expression). In |
| 3688 // that case, we don't have a function name (it's empty). | 3744 // that case, we don't have a function name (it's empty). |
| 3689 Handle<String> name = is_named ? var_name : factory()->EmptySymbol(); | 3745 Handle<String> name = is_named ? var_name : factory()->EmptySymbol(); |
| 3690 // The function name, if any. | 3746 // The function name, if any. |
| 3691 Handle<String> function_name = factory()->EmptySymbol(); | 3747 Handle<String> function_name = factory()->EmptySymbol(); |
| 3692 if (is_named && (type == EXPRESSION || type == NESTED)) { | 3748 if (is_named && (type == EXPRESSION || type == NESTED)) { |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3783 expected_property_count, | 3839 expected_property_count, |
| 3784 only_simple_this_property_assignments, | 3840 only_simple_this_property_assignments, |
| 3785 this_property_assignments, | 3841 this_property_assignments, |
| 3786 num_parameters, | 3842 num_parameters, |
| 3787 start_pos, | 3843 start_pos, |
| 3788 end_pos, | 3844 end_pos, |
| 3789 function_name->length() > 0)); | 3845 function_name->length() > 0)); |
| 3790 if (!is_pre_parsing_) { | 3846 if (!is_pre_parsing_) { |
| 3791 function_literal->set_function_token_position(function_token_position); | 3847 function_literal->set_function_token_position(function_token_position); |
| 3792 } | 3848 } |
| 3849 |
| 3850 // Set flag for inner loop detection. We treat loops that contain a function |
| 3851 // literal not as inner loops because we avoid duplicating function literals |
| 3852 // when peeling or unrolling such a loop. |
| 3853 seen_loop_stmt_ = true; |
| 3854 |
| 3793 return function_literal; | 3855 return function_literal; |
| 3794 } | 3856 } |
| 3795 } | 3857 } |
| 3796 | 3858 |
| 3797 | 3859 |
| 3798 Expression* Parser::ParseV8Intrinsic(bool* ok) { | 3860 Expression* Parser::ParseV8Intrinsic(bool* ok) { |
| 3799 // CallRuntime :: | 3861 // CallRuntime :: |
| 3800 // '%' Identifier Arguments | 3862 // '%' Identifier Arguments |
| 3801 | 3863 |
| 3802 Expect(Token::MOD, CHECK_OK); | 3864 Expect(Token::MOD, CHECK_OK); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 3825 // ... | 3887 // ... |
| 3826 } | 3888 } |
| 3827 | 3889 |
| 3828 if (!*ok) { | 3890 if (!*ok) { |
| 3829 // We found a macro but it failed. | 3891 // We found a macro but it failed. |
| 3830 ReportMessage("unable_to_parse", Vector<const char*>::empty()); | 3892 ReportMessage("unable_to_parse", Vector<const char*>::empty()); |
| 3831 return NULL; | 3893 return NULL; |
| 3832 } | 3894 } |
| 3833 } | 3895 } |
| 3834 | 3896 |
| 3835 // Otherwise we have a runtime call. | 3897 // Check that the expected number arguments are passed to runtime functions. |
| 3898 if (!is_pre_parsing_) { |
| 3899 if (function != NULL |
| 3900 && function->nargs != -1 |
| 3901 && function->nargs != args->length()) { |
| 3902 ReportMessage("illegal_access", Vector<const char*>::empty()); |
| 3903 *ok = false; |
| 3904 return NULL; |
| 3905 } else if (function == NULL && !name.is_null()) { |
| 3906 // If this is not a runtime function implemented in C++ it might be an |
| 3907 // inlined runtime function. |
| 3908 int argc = CodeGenerator::InlineRuntimeCallArgumentsCount(name); |
| 3909 if (argc != -1 && argc != args->length()) { |
| 3910 ReportMessage("illegal_access", Vector<const char*>::empty()); |
| 3911 *ok = false; |
| 3912 return NULL; |
| 3913 } |
| 3914 } |
| 3915 } |
| 3916 |
| 3917 // Otherwise we have a valid runtime call. |
| 3836 return NEW(CallRuntime(name, function, args)); | 3918 return NEW(CallRuntime(name, function, args)); |
| 3837 } | 3919 } |
| 3838 | 3920 |
| 3839 | 3921 |
| 3840 void Parser::Consume(Token::Value token) { | 3922 void Parser::Consume(Token::Value token) { |
| 3841 Token::Value next = Next(); | 3923 Token::Value next = Next(); |
| 3842 USE(next); | 3924 USE(next); |
| 3843 USE(token); | 3925 USE(token); |
| 3844 ASSERT(next == token); | 3926 ASSERT(next == token); |
| 3845 } | 3927 } |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4116 } while (Check(Token::COMMA)); | 4198 } while (Check(Token::COMMA)); |
| 4117 } | 4199 } |
| 4118 Expect(Token::RBRACE, CHECK_OK); | 4200 Expect(Token::RBRACE, CHECK_OK); |
| 4119 | 4201 |
| 4120 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); | 4202 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); |
| 4121 if (is_pre_parsing_) return NULL; | 4203 if (is_pre_parsing_) return NULL; |
| 4122 | 4204 |
| 4123 Handle<FixedArray> constant_properties = | 4205 Handle<FixedArray> constant_properties = |
| 4124 Factory::NewFixedArray(boilerplate_properties * 2, TENURED); | 4206 Factory::NewFixedArray(boilerplate_properties * 2, TENURED); |
| 4125 bool is_simple = true; | 4207 bool is_simple = true; |
| 4208 bool fast_elements = true; |
| 4126 int depth = 1; | 4209 int depth = 1; |
| 4127 BuildObjectLiteralConstantProperties(properties.elements(), | 4210 BuildObjectLiteralConstantProperties(properties.elements(), |
| 4128 constant_properties, | 4211 constant_properties, |
| 4129 &is_simple, | 4212 &is_simple, |
| 4213 &fast_elements, |
| 4130 &depth); | 4214 &depth); |
| 4131 return new ObjectLiteral(constant_properties, | 4215 return new ObjectLiteral(constant_properties, |
| 4132 properties.elements(), | 4216 properties.elements(), |
| 4133 literal_index, | 4217 literal_index, |
| 4134 is_simple, | 4218 is_simple, |
| 4219 fast_elements, |
| 4135 depth); | 4220 depth); |
| 4136 } | 4221 } |
| 4137 | 4222 |
| 4138 | 4223 |
| 4139 // Parse a JSON array. Scanner must be right after '[' token. | 4224 // Parse a JSON array. Scanner must be right after '[' token. |
| 4140 Expression* Parser::ParseJsonArray(bool* ok) { | 4225 Expression* Parser::ParseJsonArray(bool* ok) { |
| 4141 Consume(Token::LBRACK); | 4226 Consume(Token::LBRACK); |
| 4142 | 4227 |
| 4143 ZoneListWrapper<Expression> values = factory()->NewList<Expression>(4); | 4228 ZoneListWrapper<Expression> values = factory()->NewList<Expression>(4); |
| 4144 if (peek() != Token::RBRACK) { | 4229 if (peek() != Token::RBRACK) { |
| (...skipping 944 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5089 parser.ParseLazy(script_source, name, | 5174 parser.ParseLazy(script_source, name, |
| 5090 start_position, end_position, is_expression); | 5175 start_position, end_position, is_expression); |
| 5091 return result; | 5176 return result; |
| 5092 } | 5177 } |
| 5093 | 5178 |
| 5094 | 5179 |
| 5095 #undef NEW | 5180 #undef NEW |
| 5096 | 5181 |
| 5097 | 5182 |
| 5098 } } // namespace v8::internal | 5183 } } // namespace v8::internal |
| OLD | NEW |