OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 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 2434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2445 } | 2445 } |
2446 } | 2446 } |
2447 bool FoundCode() {return found_;} | 2447 bool FoundCode() {return found_;} |
2448 | 2448 |
2449 private: | 2449 private: |
2450 bool found_; | 2450 bool found_; |
2451 Code* code_; | 2451 Code* code_; |
2452 }; | 2452 }; |
2453 | 2453 |
2454 | 2454 |
2455 static void FlushCodeForFunction(SharedFunctionInfo* function_info) { | 2455 static bool CodeIsActive(Code* code) { |
2456 // The function must be compiled and have the source code available, | |
2457 // to be able to recompile it in case we need the function again. | |
2458 if (!(function_info->is_compiled() && function_info->HasSourceCode())) return; | |
2459 | |
2460 // We never flush code for Api functions. | |
2461 if (function_info->IsApiFunction()) return; | |
2462 | |
2463 // Only flush code for functions. | |
2464 if (!function_info->code()->kind() == Code::FUNCTION) return; | |
2465 | |
2466 // Function must be lazy compilable. | |
2467 if (!function_info->allows_lazy_compilation()) return; | |
2468 | |
2469 // If this is a full script wrapped in a function we do no flush the code. | |
2470 if (function_info->is_toplevel()) return; | |
2471 | |
2472 // If this function is in the compilation cache we do not flush the code. | |
2473 if (CompilationCache::HasFunction(function_info)) return; | |
2474 | |
2475 // Make sure we are not referencing the code from the stack. | 2456 // Make sure we are not referencing the code from the stack. |
2476 for (StackFrameIterator it; !it.done(); it.Advance()) { | 2457 for (StackFrameIterator it; !it.done(); it.Advance()) { |
2477 if (function_info->code()->contains(it.frame()->pc())) return; | 2458 if (code->contains(it.frame()->pc())) return true; |
2478 } | 2459 } |
2479 // Iterate the archived stacks in all threads to check if | 2460 // Iterate the archived stacks in all threads to check if |
2480 // the code is referenced. | 2461 // the code is referenced. |
2481 FlushingStackVisitor threadvisitor(function_info->code()); | 2462 FlushingStackVisitor threadvisitor(code); |
2482 ThreadManager::IterateArchivedThreads(&threadvisitor); | 2463 ThreadManager::IterateArchivedThreads(&threadvisitor); |
2483 if (threadvisitor.FoundCode()) return; | 2464 if (threadvisitor.FoundCode()) return true; |
| 2465 return false; |
| 2466 } |
| 2467 |
| 2468 |
| 2469 static void FlushCodeForFunction(JSFunction* function) { |
| 2470 SharedFunctionInfo* shared_info = function->shared(); |
| 2471 |
| 2472 // Special handling if the function and shared info objects |
| 2473 // have different code objects. |
| 2474 if (function->code() != shared_info->code()) { |
| 2475 // If the shared function has been flushed but the function has not, |
| 2476 // we flush the function if possible. |
| 2477 if (!shared_info->is_compiled() && function->is_compiled() && |
| 2478 !CodeIsActive(function->code())) { |
| 2479 function->set_code(shared_info->code()); |
| 2480 } |
| 2481 return; |
| 2482 } |
| 2483 |
| 2484 // The function must be compiled and have the source code available, |
| 2485 // to be able to recompile it in case we need the function again. |
| 2486 if (!(shared_info->is_compiled() && shared_info->HasSourceCode())) return; |
| 2487 |
| 2488 // We never flush code for Api functions. |
| 2489 if (shared_info->IsApiFunction()) return; |
| 2490 |
| 2491 // Only flush code for functions. |
| 2492 if (!shared_info->code()->kind() == Code::FUNCTION) return; |
| 2493 |
| 2494 // Function must be lazy compilable. |
| 2495 if (!shared_info->allows_lazy_compilation()) return; |
| 2496 |
| 2497 // If this is a full script wrapped in a function we do no flush the code. |
| 2498 if (shared_info->is_toplevel()) return; |
| 2499 |
| 2500 // If this function is in the compilation cache we do not flush the code. |
| 2501 if (CompilationCache::HasFunction(shared_info)) return; |
| 2502 |
| 2503 // Check stack and archived threads for the code. |
| 2504 if (CodeIsActive(shared_info->code())) return; |
2484 | 2505 |
2485 // Compute the lazy compilable version of the code. | 2506 // Compute the lazy compilable version of the code. |
2486 HandleScope scope; | 2507 HandleScope scope; |
2487 function_info->set_code(*ComputeLazyCompile(function_info->length())); | 2508 Code* code = *ComputeLazyCompile(shared_info->length()); |
| 2509 shared_info->set_code(code); |
| 2510 function->set_code(code); |
2488 } | 2511 } |
2489 | 2512 |
2490 | 2513 |
2491 void Heap::FlushCode() { | 2514 void Heap::FlushCode() { |
2492 #ifdef ENABLE_DEBUGGER_SUPPORT | 2515 #ifdef ENABLE_DEBUGGER_SUPPORT |
2493 // Do not flush code if the debugger is loaded or there are breakpoints. | 2516 // Do not flush code if the debugger is loaded or there are breakpoints. |
2494 if (Debug::IsLoaded() || Debug::has_break_points()) return; | 2517 if (Debug::IsLoaded() || Debug::has_break_points()) return; |
2495 #endif | 2518 #endif |
2496 HeapObjectIterator it(old_pointer_space()); | 2519 HeapObjectIterator it(old_pointer_space()); |
2497 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) { | 2520 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) { |
2498 if (obj->IsJSFunction()) { | 2521 if (obj->IsJSFunction()) { |
2499 JSFunction* jsfunction = JSFunction::cast(obj); | 2522 JSFunction* function = JSFunction::cast(obj); |
2500 | 2523 |
2501 // The function must have a valid context and not be a builtin. | 2524 // The function must have a valid context and not be a builtin. |
2502 if (jsfunction->unchecked_context()->IsContext() && | 2525 if (function->unchecked_context()->IsContext() && |
2503 !jsfunction->IsBuiltin()) { | 2526 !function->IsBuiltin()) { |
2504 FlushCodeForFunction(jsfunction->shared()); | 2527 FlushCodeForFunction(function); |
2505 } | 2528 } |
2506 } | 2529 } |
2507 } | 2530 } |
2508 } | 2531 } |
2509 | 2532 |
2510 | 2533 |
2511 Object* Heap::CreateCode(const CodeDesc& desc, | 2534 Object* Heap::CreateCode(const CodeDesc& desc, |
2512 Code::Flags flags, | 2535 Code::Flags flags, |
2513 Handle<Object> self_reference) { | 2536 Handle<Object> self_reference) { |
2514 // Allocate ByteArray before the Code object, so that we do not risk | 2537 // Allocate ByteArray before the Code object, so that we do not risk |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2644 } | 2667 } |
2645 | 2668 |
2646 | 2669 |
2647 Object* Heap::InitializeFunction(JSFunction* function, | 2670 Object* Heap::InitializeFunction(JSFunction* function, |
2648 SharedFunctionInfo* shared, | 2671 SharedFunctionInfo* shared, |
2649 Object* prototype) { | 2672 Object* prototype) { |
2650 ASSERT(!prototype->IsMap()); | 2673 ASSERT(!prototype->IsMap()); |
2651 function->initialize_properties(); | 2674 function->initialize_properties(); |
2652 function->initialize_elements(); | 2675 function->initialize_elements(); |
2653 function->set_shared(shared); | 2676 function->set_shared(shared); |
| 2677 function->set_code(shared->code()); |
2654 function->set_prototype_or_initial_map(prototype); | 2678 function->set_prototype_or_initial_map(prototype); |
2655 function->set_context(undefined_value()); | 2679 function->set_context(undefined_value()); |
2656 function->set_literals(empty_fixed_array()); | 2680 function->set_literals(empty_fixed_array()); |
2657 return function; | 2681 return function; |
2658 } | 2682 } |
2659 | 2683 |
2660 | 2684 |
2661 Object* Heap::AllocateFunctionPrototype(JSFunction* function) { | 2685 Object* Heap::AllocateFunctionPrototype(JSFunction* function) { |
2662 // Allocate the prototype. Make sure to use the object function | 2686 // Allocate the prototype. Make sure to use the object function |
2663 // from the function's context, since the function can be from a | 2687 // from the function's context, since the function can be from a |
(...skipping 2338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5002 void ExternalStringTable::TearDown() { | 5026 void ExternalStringTable::TearDown() { |
5003 new_space_strings_.Free(); | 5027 new_space_strings_.Free(); |
5004 old_space_strings_.Free(); | 5028 old_space_strings_.Free(); |
5005 } | 5029 } |
5006 | 5030 |
5007 | 5031 |
5008 List<Object*> ExternalStringTable::new_space_strings_; | 5032 List<Object*> ExternalStringTable::new_space_strings_; |
5009 List<Object*> ExternalStringTable::old_space_strings_; | 5033 List<Object*> ExternalStringTable::old_space_strings_; |
5010 | 5034 |
5011 } } // namespace v8::internal | 5035 } } // namespace v8::internal |
OLD | NEW |