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

Side by Side 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 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 3916 matching lines...) Expand 10 before | Expand all | Expand 10 after
3927 Object* result; 3927 Object* result;
3928 if (isnan(value) || (fpclassify(value) == FP_INFINITE)) { 3928 if (isnan(value) || (fpclassify(value) == FP_INFINITE)) {
3929 result = Heap::false_value(); 3929 result = Heap::false_value();
3930 } else { 3930 } else {
3931 result = Heap::true_value(); 3931 result = Heap::true_value();
3932 } 3932 }
3933 return result; 3933 return result;
3934 } 3934 }
3935 3935
3936 3936
3937 static Object* EvalContext() {
3938 // The topmost JS frame belongs to the eval function which called
3939 // the CompileString runtime function. We need to unwind one level
3940 // to get to the caller of eval.
3941 StackFrameLocator locator;
3942 JavaScriptFrame* frame = locator.FindJavaScriptFrame(1);
3943
3944 // TODO(900055): Right now we check if the caller of eval() supports
3945 // eval to determine if it's an aliased eval or not. This may not be
3946 // entirely correct in the unlikely case where a function uses both
3947 // aliased and direct eval calls.
3948 HandleScope scope;
3949 if (!ScopeInfo<>::SupportsEval(frame->FindCode())) {
3950 // Aliased eval: Evaluate in the global context of the eval
3951 // function to support aliased, cross environment evals.
3952 return *Top::global_context();
3953 }
3954
3955 // Fetch the caller context from the frame.
3956 Handle<Context> caller(Context::cast(frame->context()));
3957
3958 // Check for eval() invocations that cross environments. Use the
3959 // context from the stack if evaluating in current environment.
3960 Handle<Context> target = Top::global_context();
3961 if (caller->global_context() == *target) return *caller;
3962
3963 // Otherwise, use the global context from the other environment.
3964 return *target;
3965 }
3966
3967
3968 static Object* Runtime_EvalReceiver(Arguments args) {
3969 ASSERT(args.length() == 1);
3970 StackFrameLocator locator;
3971 JavaScriptFrame* frame = locator.FindJavaScriptFrame(1);
3972 // Fetch the caller context from the frame.
3973 Context* caller = Context::cast(frame->context());
3974
3975 // Check for eval() invocations that cross environments. Use the
3976 // top frames receiver if evaluating in current environment.
3977 Context* global_context = Top::context()->global()->global_context();
3978 if (caller->global_context() == global_context) {
3979 return frame->receiver();
3980 }
3981
3982 // Otherwise use the given argument (the global object of the
3983 // receiving context).
3984 return args[0];
3985 }
3986
3987
3988 static Object* Runtime_GlobalReceiver(Arguments args) { 3937 static Object* Runtime_GlobalReceiver(Arguments args) {
3989 ASSERT(args.length() == 1); 3938 ASSERT(args.length() == 1);
3990 Object* global = args[0]; 3939 Object* global = args[0];
3991 if (!global->IsJSGlobalObject()) return Heap::null_value(); 3940 if (!global->IsJSGlobalObject()) return Heap::null_value();
3992 return JSGlobalObject::cast(global)->global_receiver(); 3941 return JSGlobalObject::cast(global)->global_receiver();
3993 } 3942 }
3994 3943
3995 3944
3996 static Object* Runtime_CompileString(Arguments args) { 3945 static Object* Runtime_CompileString(Arguments args) {
3997 HandleScope scope; 3946 HandleScope scope;
3998 ASSERT(args.length() == 3); 3947 ASSERT(args.length() == 2);
3999 CONVERT_ARG_CHECKED(String, source, 0); 3948 CONVERT_ARG_CHECKED(String, source, 0);
4000 CONVERT_ARG_CHECKED(Smi, line_offset, 1); 3949 CONVERT_ARG_CHECKED(Smi, line_offset, 1);
4001 bool contextual = args[2]->IsTrue();
4002 RUNTIME_ASSERT(contextual || args[2]->IsFalse());
4003
4004 // Compute the eval context.
4005 Handle<Context> context;
4006 if (contextual) {
4007 // Get eval context. May not be available if we are calling eval
4008 // through an alias, and the corresponding frame doesn't have a
4009 // proper eval context set up.
4010 Object* eval_context = EvalContext();
4011 if (eval_context->IsFailure()) return eval_context;
4012 context = Handle<Context>(Context::cast(eval_context));
4013 } else {
4014 context = Handle<Context>(Top::context()->global_context());
4015 }
4016
4017 3950
4018 // Compile source string. 3951 // Compile source string.
4019 bool is_global = context->IsGlobalContext();
4020 Handle<JSFunction> boilerplate = 3952 Handle<JSFunction> boilerplate =
4021 Compiler::CompileEval(source, line_offset->value(), is_global); 3953 Compiler::CompileEval(source, line_offset->value(), true);
4022 if (boilerplate.is_null()) return Failure::Exception(); 3954 if (boilerplate.is_null()) return Failure::Exception();
3955 Handle<Context> context(Top::context()->global_context());
4023 Handle<JSFunction> fun = 3956 Handle<JSFunction> fun =
4024 Factory::NewFunctionFromBoilerplate(boilerplate, context); 3957 Factory::NewFunctionFromBoilerplate(boilerplate, context);
4025 return *fun; 3958 return *fun;
4026 } 3959 }
4027 3960
4028 3961
3962 static Handle<JSFunction> GetBuiltinFunction(String* name) {
3963 LookupResult result;
3964 Top::global_context()->builtins()->LocalLookup(name, &result);
3965 return Handle<JSFunction>(JSFunction::cast(result.GetValue()));
3966 }
3967
3968
3969 static Object* CompileDirectEval(Handle<String> source) {
3970 // Compute the eval context.
3971 HandleScope scope;
3972 StackFrameLocator locator;
3973 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
3974 Handle<Context> context(Context::cast(frame->context()));
3975 bool is_global = context->IsGlobalContext();
3976
3977 // Compile source string.
3978 Handle<JSFunction> boilerplate = Compiler::CompileEval(source, 0, is_global);
3979 if (boilerplate.is_null()) return Failure::Exception();
3980 Handle<JSFunction> fun =
3981 Factory::NewFunctionFromBoilerplate(boilerplate, context);
3982 return *fun;
3983 }
3984
3985
3986 static Object* Runtime_ResolvePossiblyDirectEval(Arguments args) {
3987 ASSERT(args.length() == 2);
3988
3989 HandleScope scope;
3990
3991 CONVERT_ARG_CHECKED(JSFunction, callee, 0);
3992
3993 Handle<Object> receiver;
3994
3995 // Find where the 'eval' symbol is bound. It is unaliased only if
3996 // it is bound in the global context.
3997 StackFrameLocator locator;
3998 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
3999 Handle<Context> context(Context::cast(frame->context()));
4000 int index;
4001 PropertyAttributes attributes;
4002 while (!context.is_null()) {
4003 receiver = context->Lookup(Factory::eval_symbol(), FOLLOW_PROTOTYPE_CHAIN,
4004 &index, &attributes);
4005 if (attributes != ABSENT) break;
4006 if (context->is_function_context()) {
4007 context = Handle<Context>(Context::cast(context->closure()->context()));
4008 } else {
4009 context = Handle<Context>(context->previous());
4010 }
4011 }
4012
4013 if (context->IsGlobalContext()) {
4014 // 'eval' is bound in the global context, but it may have been overwritten.
4015 // Compare it to the builtin 'GlobalEval' function to make sure.
4016 Handle<JSFunction> global_eval =
4017 GetBuiltinFunction(Heap::global_eval_symbol());
4018 if (global_eval.is_identical_to(callee)) {
4019 // A direct eval call.
4020 if (args[1]->IsString()) {
4021 CONVERT_ARG_CHECKED(String, source, 1);
4022 // A normal eval call on a string. Compile it and return the
4023 // compiled function bound in the local context.
4024 Object* compiled_source = CompileDirectEval(source);
4025 if (compiled_source->IsFailure()) return compiled_source;
4026 receiver = Handle<Object>(frame->receiver());
4027 callee = Handle<JSFunction>(JSFunction::cast(compiled_source));
4028 } else {
4029 // An eval call that is not called on a string. Global eval
4030 // deals better with this.
4031 receiver = Handle<Object>(Top::global_context()->global());
4032 }
4033 } else {
4034 // 'eval' is overwritten. Just call the function with the given arguments.
4035 receiver = Handle<Object>(Top::global_context()->global());
4036 }
4037 } else {
4038 // 'eval' is not bound in the global context. Just call the function
4039 // with the given arguments. This is not necessarily the global eval.
4040 if (receiver->IsContext()) {
4041 context = Handle<Context>::cast(receiver);
4042 receiver = Handle<Object>(context->get(index));
4043 }
4044 }
4045
4046 Handle<FixedArray> call = Factory::NewFixedArray(2);
4047 call->set(0, *callee);
4048 call->set(1, *receiver);
4049 return *call;
4050 }
4051
4052
4029 static Object* Runtime_CompileScript(Arguments args) { 4053 static Object* Runtime_CompileScript(Arguments args) {
4030 HandleScope scope; 4054 HandleScope scope;
4031 ASSERT(args.length() == 4); 4055 ASSERT(args.length() == 4);
4032 4056
4033 CONVERT_ARG_CHECKED(String, source, 0); 4057 CONVERT_ARG_CHECKED(String, source, 0);
4034 CONVERT_ARG_CHECKED(String, script, 1); 4058 CONVERT_ARG_CHECKED(String, script, 1);
4035 CONVERT_CHECKED(Smi, line_attrs, args[2]); 4059 CONVERT_CHECKED(Smi, line_attrs, args[2]);
4036 int line = line_attrs->value(); 4060 int line = line_attrs->value();
4037 CONVERT_CHECKED(Smi, col_attrs, args[3]); 4061 CONVERT_CHECKED(Smi, col_attrs, args[3]);
4038 int col = col_attrs->value(); 4062 int col = col_attrs->value();
(...skipping 1837 matching lines...) Expand 10 before | Expand all | Expand 10 after
5876 } else { 5900 } else {
5877 // Handle last resort GC and make sure to allow future allocations 5901 // Handle last resort GC and make sure to allow future allocations
5878 // to grow the heap without causing GCs (if possible). 5902 // to grow the heap without causing GCs (if possible).
5879 Counters::gc_last_resort_from_js.Increment(); 5903 Counters::gc_last_resort_from_js.Increment();
5880 Heap::CollectAllGarbage(); 5904 Heap::CollectAllGarbage();
5881 } 5905 }
5882 } 5906 }
5883 5907
5884 5908
5885 } } // namespace v8::internal 5909 } } // namespace v8::internal
OLDNEW
« 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