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

Side by Side Diff: src/runtime.cc

Issue 523051: Make the ResolvePossiblyDirectEval faster by avoiding the... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 11 months 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
« no previous file with comments | « src/runtime.h ('k') | src/scopes.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « src/runtime.h ('k') | src/scopes.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698