| Index: src/parser.cc
|
| ===================================================================
|
| --- src/parser.cc (revision 854)
|
| +++ src/parser.cc (working copy)
|
| @@ -667,10 +667,16 @@
|
|
|
| virtual Expression* NewCall(Expression* expression,
|
| ZoneList<Expression*>* arguments,
|
| - bool is_eval, int pos) {
|
| + int pos) {
|
| return Call::sentinel();
|
| }
|
|
|
| + virtual Expression* NewCallEval(Expression* expression,
|
| + ZoneList<Expression*>* arguments,
|
| + int pos) {
|
| + return CallEval::sentinel();
|
| + }
|
| +
|
| virtual Statement* EmptyStatement() {
|
| return NULL;
|
| }
|
| @@ -717,10 +723,16 @@
|
|
|
| virtual Expression* NewCall(Expression* expression,
|
| ZoneList<Expression*>* arguments,
|
| - bool is_eval, int pos) {
|
| - return new Call(expression, arguments, is_eval, pos);
|
| + int pos) {
|
| + return new Call(expression, arguments, pos);
|
| }
|
|
|
| + virtual Expression* NewCallEval(Expression* expression,
|
| + ZoneList<Expression*>* arguments,
|
| + int pos) {
|
| + return new CallEval(expression, arguments, pos);
|
| + }
|
| +
|
| virtual Statement* EmptyStatement() {
|
| // Use a statically allocated empty statement singleton to avoid
|
| // allocating lots and lots of empty statements.
|
| @@ -1343,7 +1355,7 @@
|
| // to the calling function context.
|
| if (top_scope_->is_function_scope()) {
|
| // Declare the variable in the function scope.
|
| - var = top_scope_->Lookup(name);
|
| + var = top_scope_->LookupLocal(name);
|
| if (var == NULL) {
|
| // Declare the name.
|
| var = top_scope_->Declare(name, mode);
|
| @@ -2624,55 +2636,34 @@
|
| 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.
|
|
|
| + bool is_potentially_direct_eval = false;
|
| 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 = top_scope_->Lookup(name);
|
| + 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();
|
| + is_potentially_direct_eval = true;
|
| }
|
| }
|
| }
|
|
|
| - // Optimize the eval() case w/o arguments so we
|
| - // don't need to handle it every time at runtime.
|
| - //
|
| - // Note: For now we don't do static eval analysis
|
| - // as it appears that we need to be able to call
|
| - // eval() via alias names. We leave the code as
|
| - // is, in case we want to enable this again in the
|
| - // future.
|
| - const bool is_eval = false;
|
| - if (is_eval && args->length() == 0) {
|
| - result = NEW(Literal(Factory::undefined_value()));
|
| + if (is_potentially_direct_eval) {
|
| + result = factory()->NewCallEval(result, args, pos);
|
| } else {
|
| - result = factory()->NewCall(result, args, is_eval, pos);
|
| + result = factory()->NewCall(result, args, pos);
|
| }
|
| break;
|
| }
|
|
|