| Index: src/runtime.cc | 
| =================================================================== | 
| --- src/runtime.cc	(revision 805) | 
| +++ src/runtime.cc	(working copy) | 
| @@ -3930,95 +3930,107 @@ | 
| } | 
|  | 
|  | 
| -static Object* EvalContext() { | 
| -  // The topmost JS frame belongs to the eval function which called | 
| -  // the CompileString runtime function. We need to unwind one level | 
| -  // to get to the caller of eval. | 
| -  StackFrameLocator locator; | 
| -  JavaScriptFrame* frame = locator.FindJavaScriptFrame(1); | 
| +static Object* Runtime_GlobalReceiver(Arguments args) { | 
| +  ASSERT(args.length() == 1); | 
| +  Object* global = args[0]; | 
| +  if (!global->IsJSGlobalObject()) return Heap::null_value(); | 
| +  return JSGlobalObject::cast(global)->global_receiver(); | 
| +} | 
|  | 
| -  // TODO(900055): Right now we check if the caller of eval() supports | 
| -  // eval to determine if it's an aliased eval or not. This may not be | 
| -  // entirely correct in the unlikely case where a function uses both | 
| -  // aliased and direct eval calls. | 
| + | 
| +static Object* Runtime_CompileString(Arguments args) { | 
| HandleScope scope; | 
| -  if (!ScopeInfo<>::SupportsEval(frame->FindCode())) { | 
| -    // Aliased eval: Evaluate in the global context of the eval | 
| -    // function to support aliased, cross environment evals. | 
| -    return *Top::global_context(); | 
| -  } | 
| +  ASSERT(args.length() == 2); | 
| +  CONVERT_ARG_CHECKED(String, source, 0); | 
| +  CONVERT_ARG_CHECKED(Smi, line_offset, 1); | 
|  | 
| -  // Fetch the caller context from the frame. | 
| -  Handle<Context> caller(Context::cast(frame->context())); | 
| +  // Compile source string. | 
| +  Handle<JSFunction> boilerplate = | 
| +      Compiler::CompileEval(source, line_offset->value(), true); | 
| +  if (boilerplate.is_null()) return Failure::Exception(); | 
| +  Handle<Context> context(Top::context()->global_context()); | 
| +  Handle<JSFunction> fun = | 
| +      Factory::NewFunctionFromBoilerplate(boilerplate, context); | 
| +  return *fun; | 
| +} | 
|  | 
| -  // Check for eval() invocations that cross environments. Use the | 
| -  // context from the stack if evaluating in current environment. | 
| -  Handle<Context> target = Top::global_context(); | 
| -  if (caller->global_context() == *target) return *caller; | 
|  | 
| -  // Otherwise, use the global context from the other environment. | 
| -  return *target; | 
| -} | 
| +static Object* Runtime_ExecDirectEval(Arguments args) { | 
| +  ASSERT(args.length() == 1); | 
|  | 
| +  if (!args[0]->IsString()) return args[0]; | 
|  | 
| -static Object* Runtime_EvalReceiver(Arguments args) { | 
| -  ASSERT(args.length() == 1); | 
| +  Handle<String> source = args.at<String>(0); | 
| + | 
| +  // Compute the eval context. | 
| +  HandleScope scope; | 
| StackFrameLocator locator; | 
| JavaScriptFrame* frame = locator.FindJavaScriptFrame(1); | 
| -  // Fetch the caller context from the frame. | 
| -  Context* caller = Context::cast(frame->context()); | 
| +  Handle<Context> context(Context::cast(frame->context())); | 
| +  bool is_global = context->IsGlobalContext(); | 
|  | 
| -  // Check for eval() invocations that cross environments. Use the | 
| -  // top frames receiver if evaluating in current environment. | 
| -  Context* global_context = Top::context()->global()->global_context(); | 
| -  if (caller->global_context() == global_context) { | 
| -    return frame->receiver(); | 
| +  // Compile source string. | 
| +  Handle<JSFunction> boilerplate = | 
| +      Compiler::CompileEval(source, 0, is_global); | 
| +  if (boilerplate.is_null()) return Failure::Exception(); | 
| +  Handle<JSFunction> fun = | 
| +      Factory::NewFunctionFromBoilerplate(boilerplate, context); | 
| + | 
| +  // Call generated function | 
| +  Handle<Object> receiver(frame->receiver()); | 
| +  bool has_pending_exception = false; | 
| +  Handle<Object> result = | 
| +      Execution::Call(fun, receiver, 0, NULL, &has_pending_exception); | 
| +  if (has_pending_exception) { | 
| +    ASSERT(Top::has_pending_exception()); | 
| +    return Failure::Exception(); | 
| } | 
| +  return *result; | 
| +} | 
|  | 
| -  // Otherwise use the given argument (the global object of the | 
| -  // receiving context). | 
| -  return args[0]; | 
| + | 
| +static Object* Runtime_SetInPotentiallyDirectEval(Arguments args) { | 
| +  ASSERT(args.length() == 0); | 
| +  Top::set_in_potentially_direct_eval(true); | 
| +  return Heap::undefined_value(); | 
| } | 
|  | 
|  | 
| -static Object* Runtime_GlobalReceiver(Arguments args) { | 
| -  ASSERT(args.length() == 1); | 
| -  Object* global = args[0]; | 
| -  if (!global->IsJSGlobalObject()) return Heap::null_value(); | 
| -  return JSGlobalObject::cast(global)->global_receiver(); | 
| +static Object* Runtime_ClearInPotentiallyDirectEval(Arguments args) { | 
| +  ASSERT(args.length() == 0); | 
| +  Top::set_in_potentially_direct_eval(false); | 
| +  return Heap::undefined_value(); | 
| } | 
|  | 
|  | 
| -static Object* Runtime_CompileString(Arguments args) { | 
| -  HandleScope scope; | 
| -  ASSERT(args.length() == 3); | 
| -  CONVERT_ARG_CHECKED(String, source, 0); | 
| -  CONVERT_ARG_CHECKED(Smi, line_offset, 1); | 
| -  bool contextual = args[2]->IsTrue(); | 
| -  RUNTIME_ASSERT(contextual || args[2]->IsFalse()); | 
| +static Object* Runtime_InDirectEval(Arguments args) { | 
| +  ASSERT(args.length() == 0); | 
|  | 
| -  // Compute the eval context. | 
| -  Handle<Context> context; | 
| -  if (contextual) { | 
| -    // Get eval context. May not be available if we are calling eval | 
| -    // through an alias, and the corresponding frame doesn't have a | 
| -    // proper eval context set up. | 
| -    Object* eval_context = EvalContext(); | 
| -    if (eval_context->IsFailure()) return eval_context; | 
| -    context = Handle<Context>(Context::cast(eval_context)); | 
| -  } else { | 
| -    context = Handle<Context>(Top::context()->global_context()); | 
| +  // No need to look further if the static analysis showed that this | 
| +  // is aliased. | 
| +  if (!Top::is_in_potentially_direct_eval()) { | 
| +    return Heap::false_value(); | 
| } | 
|  | 
| - | 
| -  // Compile source string. | 
| -  bool is_global = context->IsGlobalContext(); | 
| -  Handle<JSFunction> boilerplate = | 
| -      Compiler::CompileEval(source, line_offset->value(), is_global); | 
| -  if (boilerplate.is_null()) return Failure::Exception(); | 
| -  Handle<JSFunction> fun = | 
| -      Factory::NewFunctionFromBoilerplate(boilerplate, context); | 
| -  return *fun; | 
| +  // Find where the 'eval' symbol is bound. It is unaliased only if | 
| +  // it is bound in the global object. | 
| +  HandleScope scope; | 
| +  StackFrameLocator locator; | 
| +  JavaScriptFrame* frame = locator.FindJavaScriptFrame(1); | 
| +  Context* context = Context::cast(frame->context()); | 
| +  int index; | 
| +  PropertyAttributes attributes; | 
| +  while (context && !context->IsGlobalContext()) { | 
| +    context->Lookup(Factory::eval_symbol(), FOLLOW_PROTOTYPE_CHAIN, | 
| +                    &index, &attributes); | 
| +    if (attributes != ABSENT) return Heap::false_value(); | 
| +    if (context->is_function_context()) { | 
| +      context = Context::cast(context->closure()->context()); | 
| +    } else { | 
| +      context = context->previous(); | 
| +    } | 
| +  } | 
| +  return Heap::true_value(); | 
| } | 
|  | 
|  | 
|  |