OLD | NEW |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |