Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(165)

Unified Diff: src/runtime.cc

Issue 12673: Change implementation of eval to make an exact distinction between direct eva... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 12 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/codegen-ia32.cc ('K') | « src/runtime.h ('k') | src/scopes.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/runtime.cc
===================================================================
--- src/runtime.cc (revision 854)
+++ src/runtime.cc (working copy)
@@ -3934,57 +3934,6 @@
}
-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);
-
- // 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.
- 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();
- }
-
- // Fetch the caller context from the frame.
- Handle<Context> caller(Context::cast(frame->context()));
-
- // 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_EvalReceiver(Arguments args) {
- ASSERT(args.length() == 1);
- StackFrameLocator locator;
- JavaScriptFrame* frame = locator.FindJavaScriptFrame(1);
- // Fetch the caller context from the frame.
- Context* caller = Context::cast(frame->context());
-
- // 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();
- }
-
- // Otherwise use the given argument (the global object of the
- // receiving context).
- return args[0];
-}
-
-
static Object* Runtime_GlobalReceiver(Arguments args) {
ASSERT(args.length() == 1);
Object* global = args[0];
@@ -3995,37 +3944,112 @@
static Object* Runtime_CompileString(Arguments args) {
HandleScope scope;
- ASSERT(args.length() == 3);
+ ASSERT(args.length() == 2);
CONVERT_ARG_CHECKED(String, source, 0);
CONVERT_ARG_CHECKED(Smi, line_offset, 1);
- bool contextual = args[2]->IsTrue();
- RUNTIME_ASSERT(contextual || args[2]->IsFalse());
- // 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());
- }
-
-
// Compile source string.
- bool is_global = context->IsGlobalContext();
Handle<JSFunction> boilerplate =
- Compiler::CompileEval(source, line_offset->value(), is_global);
+ 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;
}
+static Handle<JSFunction> GetBuiltinFunction(String* name) {
+ LookupResult result;
+ Top::global_context()->builtins()->LocalLookup(name, &result);
+ return Handle<JSFunction>(JSFunction::cast(result.GetValue()));
+}
+
+
+static Object* CompileDirectEval(Handle<String> source) {
+ // Compute the eval context.
+ HandleScope scope;
+ StackFrameLocator locator;
+ JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
+ Handle<Context> context(Context::cast(frame->context()));
+ bool is_global = context->IsGlobalContext();
+
+ // 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);
+ return *fun;
+}
+
+
+static Object* Runtime_ResolvePossiblyDirectEval(Arguments args) {
+ ASSERT(args.length() == 2);
+
+ HandleScope scope;
+
+ CONVERT_ARG_CHECKED(JSFunction, callee, 0);
+
+ Handle<Object> receiver;
+
+ // Find where the 'eval' symbol is bound. It is unaliased only if
+ // it is bound in the global context.
+ StackFrameLocator locator;
+ JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
+ Handle<Context> context(Context::cast(frame->context()));
+ int index;
+ PropertyAttributes attributes;
+ while (!context.is_null()) {
+ receiver = context->Lookup(Factory::eval_symbol(), FOLLOW_PROTOTYPE_CHAIN,
+ &index, &attributes);
+ if (attributes != ABSENT) break;
+ if (context->is_function_context()) {
+ context = Handle<Context>(Context::cast(context->closure()->context()));
+ } else {
+ context = Handle<Context>(context->previous());
+ }
+ }
+
+ if (context->IsGlobalContext()) {
+ // 'eval' is bound in the global context, but it may have been overwritten.
+ // Compare it to the builtin 'GlobalEval' function to make sure.
+ Handle<JSFunction> global_eval =
+ GetBuiltinFunction(Heap::global_eval_symbol());
+ if (global_eval.is_identical_to(callee)) {
+ // A direct eval call.
+ if (args[1]->IsString()) {
+ CONVERT_ARG_CHECKED(String, source, 1);
+ // A normal eval call on a string. Compile it and return the
+ // compiled function bound in the local context.
+ Object* compiled_source = CompileDirectEval(source);
+ if (compiled_source->IsFailure()) return compiled_source;
+ receiver = Handle<Object>(frame->receiver());
+ callee = Handle<JSFunction>(JSFunction::cast(compiled_source));
+ } else {
+ // An eval call that is not called on a string. Global eval
+ // deals better with this.
+ receiver = Handle<Object>(Top::global_context()->global());
+ }
+ } else {
+ // 'eval' is overwritten. Just call the function with the given arguments.
+ receiver = Handle<Object>(Top::global_context()->global());
+ }
+ } else {
+ // 'eval' is not bound in the global context. Just call the function
+ // with the given arguments. This is not necessarily the global eval.
+ if (receiver->IsContext()) {
+ context = Handle<Context>::cast(receiver);
+ receiver = Handle<Object>(context->get(index));
+ }
+ }
+
+ Handle<FixedArray> call = Factory::NewFixedArray(2);
+ call->set(0, *callee);
+ call->set(1, *receiver);
+ return *call;
+}
+
+
static Object* Runtime_CompileScript(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 4);
« src/codegen-ia32.cc ('K') | « src/runtime.h ('k') | src/scopes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698