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 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
660 virtual Expression* NewProperty(Expression* obj, Expression* key, int pos) { | 660 virtual Expression* NewProperty(Expression* obj, Expression* key, int pos) { |
661 if (obj == VariableProxySentinel::this_proxy()) { | 661 if (obj == VariableProxySentinel::this_proxy()) { |
662 return Property::this_property(); | 662 return Property::this_property(); |
663 } else { | 663 } else { |
664 return ValidLeftHandSideSentinel::instance(); | 664 return ValidLeftHandSideSentinel::instance(); |
665 } | 665 } |
666 } | 666 } |
667 | 667 |
668 virtual Expression* NewCall(Expression* expression, | 668 virtual Expression* NewCall(Expression* expression, |
669 ZoneList<Expression*>* arguments, | 669 ZoneList<Expression*>* arguments, |
670 bool is_eval, int pos) { | 670 int pos) { |
671 return Call::sentinel(); | 671 return Call::sentinel(); |
672 } | 672 } |
673 | 673 |
| 674 virtual Expression* NewCallEval(Expression* expression, |
| 675 ZoneList<Expression*>* arguments, |
| 676 int pos) { |
| 677 return CallEval::sentinel(); |
| 678 } |
| 679 |
674 virtual Statement* EmptyStatement() { | 680 virtual Statement* EmptyStatement() { |
675 return NULL; | 681 return NULL; |
676 } | 682 } |
677 | 683 |
678 template <typename T> ZoneListWrapper<T> NewList(int size) { | 684 template <typename T> ZoneListWrapper<T> NewList(int size) { |
679 return is_pre_parsing_ ? ZoneListWrapper<T>() : ZoneListWrapper<T>(size); | 685 return is_pre_parsing_ ? ZoneListWrapper<T>() : ZoneListWrapper<T>(size); |
680 } | 686 } |
681 | 687 |
682 private: | 688 private: |
683 bool is_pre_parsing_; | 689 bool is_pre_parsing_; |
(...skipping 26 matching lines...) Expand all Loading... |
710 virtual Handle<String> EmptySymbol() { | 716 virtual Handle<String> EmptySymbol() { |
711 return Factory::empty_symbol(); | 717 return Factory::empty_symbol(); |
712 } | 718 } |
713 | 719 |
714 virtual Expression* NewProperty(Expression* obj, Expression* key, int pos) { | 720 virtual Expression* NewProperty(Expression* obj, Expression* key, int pos) { |
715 return new Property(obj, key, pos); | 721 return new Property(obj, key, pos); |
716 } | 722 } |
717 | 723 |
718 virtual Expression* NewCall(Expression* expression, | 724 virtual Expression* NewCall(Expression* expression, |
719 ZoneList<Expression*>* arguments, | 725 ZoneList<Expression*>* arguments, |
720 bool is_eval, int pos) { | 726 int pos) { |
721 return new Call(expression, arguments, is_eval, pos); | 727 return new Call(expression, arguments, pos); |
| 728 } |
| 729 |
| 730 virtual Expression* NewCallEval(Expression* expression, |
| 731 ZoneList<Expression*>* arguments, |
| 732 int pos) { |
| 733 return new CallEval(expression, arguments, pos); |
722 } | 734 } |
723 | 735 |
724 virtual Statement* EmptyStatement() { | 736 virtual Statement* EmptyStatement() { |
725 // Use a statically allocated empty statement singleton to avoid | 737 // Use a statically allocated empty statement singleton to avoid |
726 // allocating lots and lots of empty statements. | 738 // allocating lots and lots of empty statements. |
727 static v8::internal::EmptyStatement empty; | 739 static v8::internal::EmptyStatement empty; |
728 return ∅ | 740 return ∅ |
729 } | 741 } |
730 }; | 742 }; |
731 | 743 |
(...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1336 // is always the function scope. | 1348 // is always the function scope. |
1337 | 1349 |
1338 // If a function scope exists, then we can statically declare this | 1350 // If a function scope exists, then we can statically declare this |
1339 // variable and also set its mode. In any case, a Declaration node | 1351 // variable and also set its mode. In any case, a Declaration node |
1340 // will be added to the scope so that the declaration can be added | 1352 // will be added to the scope so that the declaration can be added |
1341 // to the corresponding activation frame at runtime if necessary. | 1353 // to the corresponding activation frame at runtime if necessary. |
1342 // For instance declarations inside an eval scope need to be added | 1354 // For instance declarations inside an eval scope need to be added |
1343 // to the calling function context. | 1355 // to the calling function context. |
1344 if (top_scope_->is_function_scope()) { | 1356 if (top_scope_->is_function_scope()) { |
1345 // Declare the variable in the function scope. | 1357 // Declare the variable in the function scope. |
1346 var = top_scope_->Lookup(name); | 1358 var = top_scope_->LookupLocal(name); |
1347 if (var == NULL) { | 1359 if (var == NULL) { |
1348 // Declare the name. | 1360 // Declare the name. |
1349 var = top_scope_->Declare(name, mode); | 1361 var = top_scope_->Declare(name, mode); |
1350 } else { | 1362 } else { |
1351 // The name was declared before; check for conflicting | 1363 // The name was declared before; check for conflicting |
1352 // re-declarations. If the previous declaration was a const or the | 1364 // re-declarations. If the previous declaration was a const or the |
1353 // current declaration is a const then we have a conflict. There is | 1365 // current declaration is a const then we have a conflict. There is |
1354 // similar code in runtime.cc in the Declare functions. | 1366 // similar code in runtime.cc in the Declare functions. |
1355 if ((mode == Variable::CONST) || (var->mode() == Variable::CONST)) { | 1367 if ((mode == Variable::CONST) || (var->mode() == Variable::CONST)) { |
1356 // We only have vars and consts in declarations. | 1368 // We only have vars and consts in declarations. |
(...skipping 1260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2617 result = factory()->NewProperty(result, index, pos); | 2629 result = factory()->NewProperty(result, index, pos); |
2618 Expect(Token::RBRACK, CHECK_OK); | 2630 Expect(Token::RBRACK, CHECK_OK); |
2619 break; | 2631 break; |
2620 } | 2632 } |
2621 | 2633 |
2622 case Token::LPAREN: { | 2634 case Token::LPAREN: { |
2623 int pos = scanner().location().beg_pos; | 2635 int pos = scanner().location().beg_pos; |
2624 ZoneList<Expression*>* args = ParseArguments(CHECK_OK); | 2636 ZoneList<Expression*>* args = ParseArguments(CHECK_OK); |
2625 | 2637 |
2626 // Keep track of eval() calls since they disable all local variable | 2638 // Keep track of eval() calls since they disable all local variable |
2627 // optimizations. We can ignore locally declared variables with | 2639 // optimizations. |
2628 // name 'eval' since they override the global 'eval' function. We | 2640 // The calls that need special treatment are the |
2629 // only need to look at unresolved variables (VariableProxies). | 2641 // direct (i.e. not aliased) eval calls. These calls are all of the |
| 2642 // form eval(...) with no explicit receiver object where eval is not |
| 2643 // declared in the current scope chain. These calls are marked as |
| 2644 // potentially direct eval calls. Whether they are actually direct calls |
| 2645 // to eval is determined at run time. |
2630 | 2646 |
| 2647 bool is_potentially_direct_eval = false; |
2631 if (!is_pre_parsing_) { | 2648 if (!is_pre_parsing_) { |
2632 // We assume that only a function called 'eval' can be used | |
2633 // to invoke the global eval() implementation. This permits | |
2634 // for massive optimizations. | |
2635 VariableProxy* callee = result->AsVariableProxy(); | 2649 VariableProxy* callee = result->AsVariableProxy(); |
2636 if (callee != NULL && callee->IsVariable(Factory::eval_symbol())) { | 2650 if (callee != NULL && callee->IsVariable(Factory::eval_symbol())) { |
2637 // We do not allow direct calls to 'eval' in our internal | 2651 Handle<String> name = callee->name(); |
2638 // JS files. Use builtin functions instead. | 2652 Variable* var = top_scope_->Lookup(name); |
2639 ASSERT(!Bootstrapper::IsActive()); | 2653 if (var == NULL) { |
2640 top_scope_->RecordEvalCall(); | 2654 // We do not allow direct calls to 'eval' in our internal |
2641 } else { | 2655 // JS files. Use builtin functions instead. |
2642 // This is rather convoluted code to check if we're calling | 2656 ASSERT(!Bootstrapper::IsActive()); |
2643 // a function named 'eval' through a property access. If so, | 2657 top_scope_->RecordEvalCall(); |
2644 // we mark it as a possible eval call (we don't know if the | 2658 is_potentially_direct_eval = true; |
2645 // receiver will resolve to the global object or not), but | |
2646 // we do not treat the call as an eval() call - we let the | |
2647 // call get through to the JavaScript eval code defined in | |
2648 // v8natives.js. | |
2649 Property* property = result->AsProperty(); | |
2650 if (property != NULL) { | |
2651 Literal* key = property->key()->AsLiteral(); | |
2652 if (key != NULL && | |
2653 key->handle().is_identical_to(Factory::eval_symbol())) { | |
2654 // We do not allow direct calls to 'eval' in our | |
2655 // internal JS files. Use builtin functions instead. | |
2656 ASSERT(!Bootstrapper::IsActive()); | |
2657 top_scope_->RecordEvalCall(); | |
2658 } | |
2659 } | 2659 } |
2660 } | 2660 } |
2661 } | 2661 } |
2662 | 2662 |
2663 // Optimize the eval() case w/o arguments so we | 2663 if (is_potentially_direct_eval) { |
2664 // don't need to handle it every time at runtime. | 2664 result = factory()->NewCallEval(result, args, pos); |
2665 // | |
2666 // Note: For now we don't do static eval analysis | |
2667 // as it appears that we need to be able to call | |
2668 // eval() via alias names. We leave the code as | |
2669 // is, in case we want to enable this again in the | |
2670 // future. | |
2671 const bool is_eval = false; | |
2672 if (is_eval && args->length() == 0) { | |
2673 result = NEW(Literal(Factory::undefined_value())); | |
2674 } else { | 2665 } else { |
2675 result = factory()->NewCall(result, args, is_eval, pos); | 2666 result = factory()->NewCall(result, args, pos); |
2676 } | 2667 } |
2677 break; | 2668 break; |
2678 } | 2669 } |
2679 | 2670 |
2680 case Token::PERIOD: { | 2671 case Token::PERIOD: { |
2681 Consume(Token::PERIOD); | 2672 Consume(Token::PERIOD); |
2682 int pos = scanner().location().beg_pos; | 2673 int pos = scanner().location().beg_pos; |
2683 Handle<String> name = ParseIdentifier(CHECK_OK); | 2674 Handle<String> name = ParseIdentifier(CHECK_OK); |
2684 result = factory()->NewProperty(result, NEW(Literal(name)), pos); | 2675 result = factory()->NewProperty(result, NEW(Literal(name)), pos); |
2685 break; | 2676 break; |
(...skipping 1674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4360 start_position, | 4351 start_position, |
4361 is_expression); | 4352 is_expression); |
4362 return result; | 4353 return result; |
4363 } | 4354 } |
4364 | 4355 |
4365 | 4356 |
4366 #undef NEW | 4357 #undef NEW |
4367 | 4358 |
4368 | 4359 |
4369 } } // namespace v8::internal | 4360 } } // namespace v8::internal |
OLD | NEW |