Speed up function deoptimization by avoiding quadratic pass over optimized function list.

R=danno@chromium.org
BUG=155270

Review URL: https://chromiumcodereview.appspot.com/11189091

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12780 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
ulan@chromium.org 2012-10-22 09:48:56 +00:00
parent d33cda9338
commit 18ff15ca8c
6 changed files with 56 additions and 52 deletions

View File

@ -104,19 +104,7 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
// ignore all slots that might have been recorded on it.
isolate->heap()->mark_compact_collector()->InvalidateCode(code);
// Iterate over all the functions which share the same code object
// and make them use unoptimized version.
Context* context = function->context()->native_context();
Object* element = context->get(Context::OPTIMIZED_FUNCTIONS_LIST);
SharedFunctionInfo* shared = function->shared();
while (!element->IsUndefined()) {
JSFunction* func = JSFunction::cast(element);
// Grab element before code replacement as ReplaceCode alters the list.
element = func->next_function_link();
if (func->code() == code) {
func->ReplaceCode(shared->code());
}
}
ReplaceCodeForRelatedFunctions(function, code);
if (FLAG_trace_deopt) {
PrintF("[forced deoptimization: ");

View File

@ -1443,6 +1443,54 @@ void Deoptimizer::RemoveDeoptimizingCode(Code* code) {
}
static Object* CutOutRelatedFunctionsList(Context* context,
Code* code,
Object* undefined) {
Object* result_list_head = undefined;
Object* head;
Object* current;
current = head = context->get(Context::OPTIMIZED_FUNCTIONS_LIST);
JSFunction* prev = NULL;
while (current != undefined) {
JSFunction* func = JSFunction::cast(current);
current = func->next_function_link();
if (func->code() == code) {
func->set_next_function_link(result_list_head);
result_list_head = func;
if (prev) {
prev->set_next_function_link(current);
} else {
head = current;
}
} else {
prev = func;
}
}
if (head != context->get(Context::OPTIMIZED_FUNCTIONS_LIST)) {
context->set(Context::OPTIMIZED_FUNCTIONS_LIST, head);
}
return result_list_head;
}
void Deoptimizer::ReplaceCodeForRelatedFunctions(JSFunction* function,
Code* code) {
Context* context = function->context()->native_context();
SharedFunctionInfo* shared = function->shared();
Object* undefined = Isolate::Current()->heap()->undefined_value();
Object* current = CutOutRelatedFunctionsList(context, code, undefined);
while (current != undefined) {
JSFunction* func = JSFunction::cast(current);
current = func->next_function_link();
func->set_code(shared->code());
func->set_next_function_link(undefined);
}
}
FrameDescription::FrameDescription(uint32_t frame_size,
JSFunction* function)
: frame_size_(frame_size),

View File

@ -166,6 +166,10 @@ class Deoptimizer : public Malloced {
// execution returns.
static void DeoptimizeFunction(JSFunction* function);
// Iterate over all the functions which share the same code object
// and make them use unoptimized version.
static void ReplaceCodeForRelatedFunctions(JSFunction* function, Code* code);
// Deoptimize all functions in the heap.
static void DeoptimizeAll();

View File

@ -198,19 +198,7 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
// ignore all slots that might have been recorded on it.
isolate->heap()->mark_compact_collector()->InvalidateCode(code);
// Iterate over all the functions which share the same code object
// and make them use unoptimized version.
Context* context = function->context()->native_context();
Object* element = context->get(Context::OPTIMIZED_FUNCTIONS_LIST);
SharedFunctionInfo* shared = function->shared();
while (!element->IsUndefined()) {
JSFunction* func = JSFunction::cast(element);
// Grab element before code replacement as ReplaceCode alters the list.
element = func->next_function_link();
if (func->code() == code) {
func->ReplaceCode(shared->code());
}
}
ReplaceCodeForRelatedFunctions(function, code);
if (FLAG_trace_deopt) {
PrintF("[forced deoptimization: ");

View File

@ -100,19 +100,7 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
// ignore all slots that might have been recorded on it.
isolate->heap()->mark_compact_collector()->InvalidateCode(code);
// Iterate over all the functions which share the same code object
// and make them use unoptimized version.
Context* context = function->context()->native_context();
Object* element = context->get(Context::OPTIMIZED_FUNCTIONS_LIST);
SharedFunctionInfo* shared = function->shared();
while (!element->IsUndefined()) {
JSFunction* func = JSFunction::cast(element);
// Grab element before code replacement as ReplaceCode alters the list.
element = func->next_function_link();
if (func->code() == code) {
func->ReplaceCode(shared->code());
}
}
ReplaceCodeForRelatedFunctions(function, code);
if (FLAG_trace_deopt) {
PrintF("[forced deoptimization: ");

View File

@ -104,19 +104,7 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
// ignore all slots that might have been recorded on it.
isolate->heap()->mark_compact_collector()->InvalidateCode(code);
// Iterate over all the functions which share the same code object
// and make them use unoptimized version.
Context* context = function->context()->native_context();
Object* element = context->get(Context::OPTIMIZED_FUNCTIONS_LIST);
SharedFunctionInfo* shared = function->shared();
while (!element->IsUndefined()) {
JSFunction* func = JSFunction::cast(element);
// Grab element before code replacement as ReplaceCode alters the list.
element = func->next_function_link();
if (func->code() == code) {
func->ReplaceCode(shared->code());
}
}
ReplaceCodeForRelatedFunctions(function, code);
if (FLAG_trace_deopt) {
PrintF("[forced deoptimization: ");