Index: src/parser.cc |
=================================================================== |
--- src/parser.cc (revision 805) |
+++ src/parser.cc (working copy) |
@@ -327,6 +327,8 @@ |
return Handle<String>(); |
} |
+ |
+ |
virtual Expression* NewProperty(Expression* obj, Expression* key, int pos) { |
if (obj == VariableProxySentinel::this_proxy()) { |
return Property::this_property(); |
@@ -337,7 +339,7 @@ |
virtual Expression* NewCall(Expression* expression, |
ZoneList<Expression*>* arguments, |
- bool is_eval, int pos) { |
+ Call::EvalType eval_type, int pos) { |
return Call::sentinel(); |
} |
@@ -387,8 +389,8 @@ |
virtual Expression* NewCall(Expression* expression, |
ZoneList<Expression*>* arguments, |
- bool is_eval, int pos) { |
- return new Call(expression, arguments, is_eval, pos); |
+ Call::EvalType eval_type, int pos) { |
+ return new Call(expression, arguments, eval_type, pos); |
} |
virtual Statement* EmptyStatement() { |
@@ -2294,39 +2296,33 @@ |
ZoneList<Expression*>* args = ParseArguments(CHECK_OK); |
// Keep track of eval() calls since they disable all local variable |
- // optimizations. We can ignore locally declared variables with |
- // name 'eval' since they override the global 'eval' function. We |
- // only need to look at unresolved variables (VariableProxies). |
+ // optimizations. |
+ // The calls that need special treatment are the |
+ // direct (i.e. not aliased) eval calls. These calls are all of the |
+ // form eval(...) with no explicit receiver object where eval is not |
+ // declared in the current scope chain. These calls are marked as |
+ // potentially direct eval calls. Whether they are actually direct calls |
+ // to eval is determined at run time. |
+ Call::EvalType eval_type = Call::ALIASED; |
if (!is_pre_parsing_) { |
- // We assume that only a function called 'eval' can be used |
- // to invoke the global eval() implementation. This permits |
- // for massive optimizations. |
VariableProxy* callee = result->AsVariableProxy(); |
if (callee != NULL && callee->IsVariable(Factory::eval_symbol())) { |
- // We do not allow direct calls to 'eval' in our internal |
- // JS files. Use builtin functions instead. |
- ASSERT(!Bootstrapper::IsActive()); |
- top_scope_->RecordEvalCall(); |
- } else { |
- // This is rather convoluted code to check if we're calling |
- // a function named 'eval' through a property access. If so, |
- // we mark it as a possible eval call (we don't know if the |
- // receiver will resolve to the global object or not), but |
- // we do not treat the call as an eval() call - we let the |
- // call get through to the JavaScript eval code defined in |
- // v8natives.js. |
- Property* property = result->AsProperty(); |
- if (property != NULL) { |
- Literal* key = property->key()->AsLiteral(); |
- if (key != NULL && |
- key->handle().is_identical_to(Factory::eval_symbol())) { |
- // We do not allow direct calls to 'eval' in our |
- // internal JS files. Use builtin functions instead. |
- ASSERT(!Bootstrapper::IsActive()); |
- top_scope_->RecordEvalCall(); |
- } |
+ Handle<String> name = callee->name(); |
+ Variable* var = NULL; |
+ for (Scope* scope = top_scope_; |
+ scope != NULL; |
+ scope = scope->outer_scope()) { |
+ var = scope->Lookup(callee->name()); |
+ if (var != NULL) break; |
} |
+ if (var == NULL) { |
+ // We do not allow direct calls to 'eval' in our internal |
+ // JS files. Use builtin functions instead. |
+ ASSERT(!Bootstrapper::IsActive()); |
+ top_scope_->RecordEvalCall(); |
+ eval_type = Call::POTENTIALLY_DIRECT; |
+ } |
} |
} |
@@ -2342,7 +2338,7 @@ |
if (is_eval && args->length() == 0) { |
result = NEW(Literal(Factory::undefined_value())); |
} else { |
- result = factory()->NewCall(result, args, is_eval, pos); |
+ result = factory()->NewCall(result, args, eval_type, pos); |
} |
break; |
} |