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

Unified Diff: src/deoptimizer.cc

Issue 11547015: Use a filter instead of a visitor to deoptimize selected functions in a context. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years 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 side-by-side diff with in-line comments
Download patch
Index: src/deoptimizer.cc
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index 8f1711144e65c9a121a233b08a44d507ea893332..c4dae93b62fe111ab3f6dbfb7b3da6ff1d8479a4 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -247,45 +247,6 @@ void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
}
-class DeoptimizingVisitor : public OptimizedFunctionVisitor {
- public:
- virtual void EnterContext(Context* context) {
- if (FLAG_trace_deopt) {
- PrintF("[deoptimize context: %" V8PRIxPTR "]\n",
- reinterpret_cast<intptr_t>(context));
- }
- }
-
- virtual void VisitFunction(JSFunction* function) {
- Deoptimizer::DeoptimizeFunction(function);
- }
-
- virtual void LeaveContext(Context* context) {
- context->ClearOptimizedFunctions();
- }
-};
-
-
-void Deoptimizer::DeoptimizeAll() {
- AssertNoAllocation no_allocation;
-
- if (FLAG_trace_deopt) {
- PrintF("[deoptimize all contexts]\n");
- }
-
- DeoptimizingVisitor visitor;
- VisitAllOptimizedFunctions(&visitor);
-}
-
-
-void Deoptimizer::DeoptimizeGlobalObject(JSObject* object) {
- AssertNoAllocation no_allocation;
-
- DeoptimizingVisitor visitor;
- VisitAllOptimizedFunctionsForGlobalObject(object, &visitor);
-}
-
-
void Deoptimizer::VisitAllOptimizedFunctionsForContext(
Context* context, OptimizedFunctionVisitor* visitor) {
Isolate* isolate = context->GetIsolate();
@@ -315,36 +276,151 @@ void Deoptimizer::VisitAllOptimizedFunctionsForContext(
}
-void Deoptimizer::VisitAllOptimizedFunctionsForGlobalObject(
- JSObject* object, OptimizedFunctionVisitor* visitor) {
+void Deoptimizer::VisitAllOptimizedFunctions(
+ OptimizedFunctionVisitor* visitor) {
+ AssertNoAllocation no_allocation;
+
+ // Run through the list of all native contexts and deoptimize.
+ Object* context = Isolate::Current()->heap()->native_contexts_list();
+ while (!context->IsUndefined()) {
+ VisitAllOptimizedFunctionsForContext(Context::cast(context), visitor);
+ context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
+ }
+}
+
+
+// Removes the functions selected by the given filter from the optimized
+// function list of the given context and partitions the removed functions
+// into one or more lists such that all functions in a list share the same
+// code. The head of each list is written in the deoptimizing_functions field
+// of the corresponding code object.
+// The found code objects are returned in the given zone list.
+static void PartitionOptimizedFunctions(Context* context,
+ OptimizedFunctionFilter* filter,
+ ZoneList<Code*>* partitions,
+ Zone* zone,
+ Object* undefined) {
+ AssertNoAllocation no_allocation;
+ Object* current = context->get(Context::OPTIMIZED_FUNCTIONS_LIST);
+ Object* remainder_head = undefined;
+ Object* remainder_tail = undefined;
+ ASSERT_EQ(0, partitions->length());
+ while (current != undefined) {
+ JSFunction* function = JSFunction::cast(current);
+ current = function->next_function_link();
+ if (filter->TakeFunction(function)) {
+ Code* code = function->code();
+ if (code->deoptimizing_functions() == undefined) {
+ partitions->Add(code, zone);
+ } else {
+ ASSERT(partitions->Contains(code));
+ }
+ function->set_next_function_link(code->deoptimizing_functions());
+ code->set_deoptimizing_functions(function);
+ } else {
+ if (remainder_head == undefined) {
+ remainder_head = function;
+ } else {
+ JSFunction::cast(remainder_tail)->set_next_function_link(function);
+ }
+ remainder_tail = function;
+ }
+ }
+ if (remainder_tail != undefined) {
+ JSFunction::cast(remainder_tail)->set_next_function_link(undefined);
+ }
+ context->set(Context::OPTIMIZED_FUNCTIONS_LIST, remainder_head);
+}
+
+
+class DeoptimizeAllFilter : public OptimizedFunctionFilter {
+ public:
+ virtual bool TakeFunction(JSFunction* function) {
+ return true;
+ }
+};
+
+
+class DeoptimizeWithMatchingCodeFilter : public OptimizedFunctionFilter {
+ public:
+ explicit DeoptimizeWithMatchingCodeFilter(Code* code) : code_(code) {}
+ virtual bool TakeFunction(JSFunction* function) {
+ return function->code() == code_;
+ }
+ private:
+ Code* code_;
+};
+
+
+void Deoptimizer::DeoptimizeAll() {
AssertNoAllocation no_allocation;
+ if (FLAG_trace_deopt) {
+ PrintF("[deoptimize all contexts]\n");
+ }
+
+ DeoptimizeAllFilter filter;
+ DeoptimizeAllFunctionsWith(&filter);
+}
+
+
+void Deoptimizer::DeoptimizeGlobalObject(JSObject* object) {
+ AssertNoAllocation no_allocation;
+ DeoptimizeAllFilter filter;
if (object->IsJSGlobalProxy()) {
Object* proto = object->GetPrototype();
ASSERT(proto->IsJSGlobalObject());
- VisitAllOptimizedFunctionsForContext(
- GlobalObject::cast(proto)->native_context(), visitor);
+ DeoptimizeAllFunctionsForContext(
+ GlobalObject::cast(proto)->native_context(), &filter);
} else if (object->IsGlobalObject()) {
- VisitAllOptimizedFunctionsForContext(
- GlobalObject::cast(object)->native_context(), visitor);
+ DeoptimizeAllFunctionsForContext(
+ GlobalObject::cast(object)->native_context(), &filter);
}
}
-void Deoptimizer::VisitAllOptimizedFunctions(
- OptimizedFunctionVisitor* visitor) {
+void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
+ if (!function->IsOptimized()) return;
+ Code* code = function->code();
+ Context* context = function->context()->native_context();
+ Isolate* isolate = context->GetIsolate();
+ Object* undefined = isolate->heap()->undefined_value();
+ Zone* zone = isolate->runtime_zone();
+ ZoneScope zone_scope(zone, DELETE_ON_EXIT);
+ ZoneList<Code*> codes(1, zone);
+ DeoptimizeWithMatchingCodeFilter filter(code);
+ PartitionOptimizedFunctions(context, &filter, &codes, zone, undefined);
+ ASSERT_EQ(1, codes.length());
+ DeoptimizeFunctionWithPreparedFunctionList(
+ JSFunction::cast(codes.at(0)->deoptimizing_functions()));
+ codes.at(0)->set_deoptimizing_functions(undefined);
+}
+
+
+void Deoptimizer::DeoptimizeAllFunctionsForContext(
+ Context* context, OptimizedFunctionFilter* filter) {
+ ASSERT(context->IsNativeContext());
+ Isolate* isolate = context->GetIsolate();
+ Object* undefined = isolate->heap()->undefined_value();
+ Zone* zone = isolate->runtime_zone();
+ ZoneScope zone_scope(zone, DELETE_ON_EXIT);
+ ZoneList<Code*> codes(1, zone);
+ PartitionOptimizedFunctions(context, filter, &codes, zone, undefined);
+ for (int i = 0; i < codes.length(); ++i) {
+ DeoptimizeFunctionWithPreparedFunctionList(
+ JSFunction::cast(codes.at(i)->deoptimizing_functions()));
+ codes.at(i)->set_deoptimizing_functions(undefined);
+ }
+}
+
+
+void Deoptimizer::DeoptimizeAllFunctionsWith(OptimizedFunctionFilter* filter) {
AssertNoAllocation no_allocation;
// Run through the list of all native contexts and deoptimize.
Object* context = Isolate::Current()->heap()->native_contexts_list();
while (!context->IsUndefined()) {
- // GC can happen when the context is not fully initialized,
- // so the global field of the context can be undefined.
- Object* global = Context::cast(context)->get(Context::GLOBAL_OBJECT_INDEX);
- if (!global->IsUndefined()) {
- VisitAllOptimizedFunctionsForGlobalObject(JSObject::cast(global),
- visitor);
- }
+ DeoptimizeAllFunctionsForContext(Context::cast(context), filter);
context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
}
}
@@ -1476,44 +1552,11 @@ 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);
+ Object* current = function;
while (current != undefined) {
JSFunction* func = JSFunction::cast(current);
« src/deoptimizer.h ('K') | « src/deoptimizer.h ('k') | src/ia32/deoptimizer-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698