| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 5215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5226 context, | 5226 context, |
| 5227 true, | 5227 true, |
| 5228 validate); | 5228 validate); |
| 5229 if (boilerplate.is_null()) return Failure::Exception(); | 5229 if (boilerplate.is_null()) return Failure::Exception(); |
| 5230 Handle<JSFunction> fun = | 5230 Handle<JSFunction> fun = |
| 5231 Factory::NewFunctionFromBoilerplate(boilerplate, context, NOT_TENURED); | 5231 Factory::NewFunctionFromBoilerplate(boilerplate, context, NOT_TENURED); |
| 5232 return *fun; | 5232 return *fun; |
| 5233 } | 5233 } |
| 5234 | 5234 |
| 5235 | 5235 |
| 5236 static Handle<JSFunction> GetBuiltinFunction(String* name) { | 5236 static ObjectPair Runtime_ResolvePossiblyDirectEval(Arguments args) { |
| 5237 LookupResult result; | 5237 ASSERT(args.length() == 3); |
| 5238 Top::global_context()->builtins()->LocalLookup(name, &result); | 5238 if (!args[0]->IsJSFunction()) { |
| 5239 return Handle<JSFunction>(JSFunction::cast(result.GetValue())); | 5239 return MakePair(Top::ThrowIllegalOperation(), NULL); |
| 5240 } | 5240 } |
| 5241 | 5241 |
| 5242 HandleScope scope; |
| 5243 Handle<JSFunction> callee = args.at<JSFunction>(0); |
| 5244 Handle<Object> receiver; // Will be overwritten. |
| 5242 | 5245 |
| 5243 static Object* CompileDirectEval(Handle<String> source) { | 5246 // Compute the calling context. |
| 5244 // Compute the eval context. | 5247 Handle<Context> context = Handle<Context>(Top::context()); |
| 5245 HandleScope scope; | 5248 #ifdef DEBUG |
| 5249 // Make sure Top::context() agrees with the old code that traversed |
| 5250 // the stack frames to compute the context. |
| 5246 StackFrameLocator locator; | 5251 StackFrameLocator locator; |
| 5247 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 5252 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
| 5248 Handle<Context> context(Context::cast(frame->context())); | 5253 ASSERT(Context::cast(frame->context()) == *context); |
| 5249 bool is_global = context->IsGlobalContext(); | 5254 #endif |
| 5250 | |
| 5251 // Compile source string in the current context. | |
| 5252 Handle<JSFunction> boilerplate = Compiler::CompileEval( | |
| 5253 source, | |
| 5254 context, | |
| 5255 is_global, | |
| 5256 Compiler::DONT_VALIDATE_JSON); | |
| 5257 if (boilerplate.is_null()) return Failure::Exception(); | |
| 5258 Handle<JSFunction> fun = | |
| 5259 Factory::NewFunctionFromBoilerplate(boilerplate, context, NOT_TENURED); | |
| 5260 return *fun; | |
| 5261 } | |
| 5262 | |
| 5263 | |
| 5264 static Object* Runtime_ResolvePossiblyDirectEval(Arguments args) { | |
| 5265 ASSERT(args.length() == 2); | |
| 5266 | |
| 5267 HandleScope scope; | |
| 5268 | |
| 5269 CONVERT_ARG_CHECKED(JSFunction, callee, 0); | |
| 5270 | |
| 5271 Handle<Object> receiver; | |
| 5272 | 5255 |
| 5273 // Find where the 'eval' symbol is bound. It is unaliased only if | 5256 // Find where the 'eval' symbol is bound. It is unaliased only if |
| 5274 // it is bound in the global context. | 5257 // it is bound in the global context. |
| 5275 StackFrameLocator locator; | 5258 int index = -1; |
| 5276 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 5259 PropertyAttributes attributes = ABSENT; |
| 5277 Handle<Context> context(Context::cast(frame->context())); | 5260 while (true) { |
| 5278 int index; | |
| 5279 PropertyAttributes attributes; | |
| 5280 while (!context.is_null()) { | |
| 5281 receiver = context->Lookup(Factory::eval_symbol(), FOLLOW_PROTOTYPE_CHAIN, | 5261 receiver = context->Lookup(Factory::eval_symbol(), FOLLOW_PROTOTYPE_CHAIN, |
| 5282 &index, &attributes); | 5262 &index, &attributes); |
| 5283 // Stop search when eval is found or when the global context is | 5263 // Stop search when eval is found or when the global context is |
| 5284 // reached. | 5264 // reached. |
| 5285 if (attributes != ABSENT || context->IsGlobalContext()) break; | 5265 if (attributes != ABSENT || context->IsGlobalContext()) break; |
| 5286 if (context->is_function_context()) { | 5266 if (context->is_function_context()) { |
| 5287 context = Handle<Context>(Context::cast(context->closure()->context())); | 5267 context = Handle<Context>(Context::cast(context->closure()->context())); |
| 5288 } else { | 5268 } else { |
| 5289 context = Handle<Context>(context->previous()); | 5269 context = Handle<Context>(context->previous()); |
| 5290 } | 5270 } |
| 5291 } | 5271 } |
| 5292 | 5272 |
| 5293 // If eval could not be resolved, it has been deleted and we need to | 5273 // If eval could not be resolved, it has been deleted and we need to |
| 5294 // throw a reference error. | 5274 // throw a reference error. |
| 5295 if (attributes == ABSENT) { | 5275 if (attributes == ABSENT) { |
| 5296 Handle<Object> name = Factory::eval_symbol(); | 5276 Handle<Object> name = Factory::eval_symbol(); |
| 5297 Handle<Object> reference_error = | 5277 Handle<Object> reference_error = |
| 5298 Factory::NewReferenceError("not_defined", HandleVector(&name, 1)); | 5278 Factory::NewReferenceError("not_defined", HandleVector(&name, 1)); |
| 5299 return Top::Throw(*reference_error); | 5279 return MakePair(Top::Throw(*reference_error), NULL); |
| 5300 } | 5280 } |
| 5301 | 5281 |
| 5302 if (context->IsGlobalContext()) { | 5282 if (!context->IsGlobalContext()) { |
| 5303 // 'eval' is bound in the global context, but it may have been overwritten. | |
| 5304 // Compare it to the builtin 'GlobalEval' function to make sure. | |
| 5305 Handle<JSFunction> global_eval = | |
| 5306 GetBuiltinFunction(Heap::global_eval_symbol()); | |
| 5307 if (global_eval.is_identical_to(callee)) { | |
| 5308 // A direct eval call. | |
| 5309 if (args[1]->IsString()) { | |
| 5310 CONVERT_ARG_CHECKED(String, source, 1); | |
| 5311 // A normal eval call on a string. Compile it and return the | |
| 5312 // compiled function bound in the local context. | |
| 5313 Object* compiled_source = CompileDirectEval(source); | |
| 5314 if (compiled_source->IsFailure()) return compiled_source; | |
| 5315 receiver = Handle<Object>(frame->receiver()); | |
| 5316 callee = Handle<JSFunction>(JSFunction::cast(compiled_source)); | |
| 5317 } else { | |
| 5318 // An eval call that is not called on a string. Global eval | |
| 5319 // deals better with this. | |
| 5320 receiver = Handle<Object>(Top::global_context()->global()); | |
| 5321 } | |
| 5322 } else { | |
| 5323 // 'eval' is overwritten. Just call the function with the given arguments. | |
| 5324 receiver = Handle<Object>(Top::global_context()->global()); | |
| 5325 } | |
| 5326 } else { | |
| 5327 // 'eval' is not bound in the global context. Just call the function | 5283 // 'eval' is not bound in the global context. Just call the function |
| 5328 // with the given arguments. This is not necessarily the global eval. | 5284 // with the given arguments. This is not necessarily the global eval. |
| 5329 if (receiver->IsContext()) { | 5285 if (receiver->IsContext()) { |
| 5330 context = Handle<Context>::cast(receiver); | 5286 context = Handle<Context>::cast(receiver); |
| 5331 receiver = Handle<Object>(context->get(index)); | 5287 receiver = Handle<Object>(context->get(index)); |
| 5288 } else if (receiver->IsJSContextExtensionObject()) { |
| 5289 receiver = Handle<JSObject>(Top::context()->global()->global_receiver()); |
| 5332 } | 5290 } |
| 5291 return MakePair(*callee, *receiver); |
| 5333 } | 5292 } |
| 5334 | 5293 |
| 5335 Handle<FixedArray> call = Factory::NewFixedArray(2); | 5294 // 'eval' is bound in the global context, but it may have been overwritten. |
| 5336 call->set(0, *callee); | 5295 // Compare it to the builtin 'GlobalEval' function to make sure. |
| 5337 call->set(1, *receiver); | 5296 if (*callee != Top::global_context()->global_eval_fun() || |
| 5338 return *call; | 5297 !args[1]->IsString()) { |
| 5298 return MakePair(*callee, Top::context()->global()->global_receiver()); |
| 5299 } |
| 5300 |
| 5301 // Deal with a normal eval call with a string argument. Compile it |
| 5302 // and return the compiled function bound in the local context. |
| 5303 Handle<String> source = args.at<String>(1); |
| 5304 Handle<JSFunction> boilerplate = Compiler::CompileEval( |
| 5305 source, |
| 5306 Handle<Context>(Top::context()), |
| 5307 Top::context()->IsGlobalContext(), |
| 5308 Compiler::DONT_VALIDATE_JSON); |
| 5309 if (boilerplate.is_null()) return MakePair(Failure::Exception(), NULL); |
| 5310 callee = Factory::NewFunctionFromBoilerplate( |
| 5311 boilerplate, |
| 5312 Handle<Context>(Top::context()), |
| 5313 NOT_TENURED); |
| 5314 return MakePair(*callee, args[2]); |
| 5339 } | 5315 } |
| 5340 | 5316 |
| 5341 | 5317 |
| 5342 static Object* Runtime_SetNewFunctionAttributes(Arguments args) { | 5318 static Object* Runtime_SetNewFunctionAttributes(Arguments args) { |
| 5343 // This utility adjusts the property attributes for newly created Function | 5319 // This utility adjusts the property attributes for newly created Function |
| 5344 // object ("new Function(...)") by changing the map. | 5320 // object ("new Function(...)") by changing the map. |
| 5345 // All it does is changing the prototype property to enumerable | 5321 // All it does is changing the prototype property to enumerable |
| 5346 // as specified in ECMA262, 15.3.5.2. | 5322 // as specified in ECMA262, 15.3.5.2. |
| 5347 HandleScope scope; | 5323 HandleScope scope; |
| 5348 ASSERT(args.length() == 1); | 5324 ASSERT(args.length() == 1); |
| (...skipping 2699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8048 } else { | 8024 } else { |
| 8049 // Handle last resort GC and make sure to allow future allocations | 8025 // Handle last resort GC and make sure to allow future allocations |
| 8050 // to grow the heap without causing GCs (if possible). | 8026 // to grow the heap without causing GCs (if possible). |
| 8051 Counters::gc_last_resort_from_js.Increment(); | 8027 Counters::gc_last_resort_from_js.Increment(); |
| 8052 Heap::CollectAllGarbage(false); | 8028 Heap::CollectAllGarbage(false); |
| 8053 } | 8029 } |
| 8054 } | 8030 } |
| 8055 | 8031 |
| 8056 | 8032 |
| 8057 } } // namespace v8::internal | 8033 } } // namespace v8::internal |
| OLD | NEW |