From 18ff15ca8ca5ec63752cae0078906368b8374043 Mon Sep 17 00:00:00 2001 From: "ulan@chromium.org" Date: Mon, 22 Oct 2012 09:48:56 +0000 Subject: [PATCH] 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 --- src/arm/deoptimizer-arm.cc | 14 +---------- src/deoptimizer.cc | 48 ++++++++++++++++++++++++++++++++++++ src/deoptimizer.h | 4 +++ src/ia32/deoptimizer-ia32.cc | 14 +---------- src/mips/deoptimizer-mips.cc | 14 +---------- src/x64/deoptimizer-x64.cc | 14 +---------- 6 files changed, 56 insertions(+), 52 deletions(-) diff --git a/src/arm/deoptimizer-arm.cc b/src/arm/deoptimizer-arm.cc index 5339be1d84..19667b9d5f 100644 --- a/src/arm/deoptimizer-arm.cc +++ b/src/arm/deoptimizer-arm.cc @@ -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: "); diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc index d7d392a966..ad893b3b43 100644 --- a/src/deoptimizer.cc +++ b/src/deoptimizer.cc @@ -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), diff --git a/src/deoptimizer.h b/src/deoptimizer.h index 1995754967..f67f986ba1 100644 --- a/src/deoptimizer.h +++ b/src/deoptimizer.h @@ -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(); diff --git a/src/ia32/deoptimizer-ia32.cc b/src/ia32/deoptimizer-ia32.cc index f50010b9d9..99ad5225bc 100644 --- a/src/ia32/deoptimizer-ia32.cc +++ b/src/ia32/deoptimizer-ia32.cc @@ -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: "); diff --git a/src/mips/deoptimizer-mips.cc b/src/mips/deoptimizer-mips.cc index 371d120887..9fd815bb42 100644 --- a/src/mips/deoptimizer-mips.cc +++ b/src/mips/deoptimizer-mips.cc @@ -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: "); diff --git a/src/x64/deoptimizer-x64.cc b/src/x64/deoptimizer-x64.cc index 0502502ab0..a3fe8f9cf7 100644 --- a/src/x64/deoptimizer-x64.cc +++ b/src/x64/deoptimizer-x64.cc @@ -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: ");