Commit 18ff15ca authored by ulan@chromium.org's avatar ulan@chromium.org

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
parent d33cda93
...@@ -104,19 +104,7 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) { ...@@ -104,19 +104,7 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
// ignore all slots that might have been recorded on it. // ignore all slots that might have been recorded on it.
isolate->heap()->mark_compact_collector()->InvalidateCode(code); isolate->heap()->mark_compact_collector()->InvalidateCode(code);
// Iterate over all the functions which share the same code object ReplaceCodeForRelatedFunctions(function, code);
// 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());
}
}
if (FLAG_trace_deopt) { if (FLAG_trace_deopt) {
PrintF("[forced deoptimization: "); PrintF("[forced deoptimization: ");
......
...@@ -1443,6 +1443,54 @@ void Deoptimizer::RemoveDeoptimizingCode(Code* code) { ...@@ -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, FrameDescription::FrameDescription(uint32_t frame_size,
JSFunction* function) JSFunction* function)
: frame_size_(frame_size), : frame_size_(frame_size),
......
...@@ -166,6 +166,10 @@ class Deoptimizer : public Malloced { ...@@ -166,6 +166,10 @@ class Deoptimizer : public Malloced {
// execution returns. // execution returns.
static void DeoptimizeFunction(JSFunction* function); 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. // Deoptimize all functions in the heap.
static void DeoptimizeAll(); static void DeoptimizeAll();
......
...@@ -198,19 +198,7 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) { ...@@ -198,19 +198,7 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
// ignore all slots that might have been recorded on it. // ignore all slots that might have been recorded on it.
isolate->heap()->mark_compact_collector()->InvalidateCode(code); isolate->heap()->mark_compact_collector()->InvalidateCode(code);
// Iterate over all the functions which share the same code object ReplaceCodeForRelatedFunctions(function, code);
// 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());
}
}
if (FLAG_trace_deopt) { if (FLAG_trace_deopt) {
PrintF("[forced deoptimization: "); PrintF("[forced deoptimization: ");
......
...@@ -100,19 +100,7 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) { ...@@ -100,19 +100,7 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
// ignore all slots that might have been recorded on it. // ignore all slots that might have been recorded on it.
isolate->heap()->mark_compact_collector()->InvalidateCode(code); isolate->heap()->mark_compact_collector()->InvalidateCode(code);
// Iterate over all the functions which share the same code object ReplaceCodeForRelatedFunctions(function, code);
// 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());
}
}
if (FLAG_trace_deopt) { if (FLAG_trace_deopt) {
PrintF("[forced deoptimization: "); PrintF("[forced deoptimization: ");
......
...@@ -104,19 +104,7 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) { ...@@ -104,19 +104,7 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
// ignore all slots that might have been recorded on it. // ignore all slots that might have been recorded on it.
isolate->heap()->mark_compact_collector()->InvalidateCode(code); isolate->heap()->mark_compact_collector()->InvalidateCode(code);
// Iterate over all the functions which share the same code object ReplaceCodeForRelatedFunctions(function, code);
// 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());
}
}
if (FLAG_trace_deopt) { if (FLAG_trace_deopt) {
PrintF("[forced deoptimization: "); PrintF("[forced deoptimization: ");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment