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

Unified Diff: src/mark-compact.cc

Issue 8888011: Ensure that non-optimized code objects are not flushed for inlined functions. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 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
« no previous file with comments | « src/mark-compact.h ('k') | src/objects.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/mark-compact.cc
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 7303e3a700f7bc04d6f9fbb526d417ddfe981679..a4b8349d48ba3767ad1abdb3f472acfe224ac253 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -619,8 +619,7 @@ class CodeFlusher {
}
void AddCandidate(JSFunction* function) {
- ASSERT(function->unchecked_code() ==
- function->unchecked_shared()->unchecked_code());
+ ASSERT(function->code() == function->shared()->code());
SetNextCandidate(function, jsfunction_candidates_head_);
jsfunction_candidates_head_ = function;
@@ -640,15 +639,15 @@ class CodeFlusher {
while (candidate != NULL) {
next_candidate = GetNextCandidate(candidate);
- SharedFunctionInfo* shared = candidate->unchecked_shared();
+ SharedFunctionInfo* shared = candidate->shared();
- Code* code = shared->unchecked_code();
+ Code* code = shared->code();
MarkBit code_mark = Marking::MarkBitFrom(code);
if (!code_mark.Get()) {
shared->set_code(lazy_compile);
candidate->set_code(lazy_compile);
} else {
- candidate->set_code(shared->unchecked_code());
+ candidate->set_code(shared->code());
}
// We are in the middle of a GC cycle so the write barrier in the code
@@ -674,7 +673,7 @@ class CodeFlusher {
next_candidate = GetNextCandidate(candidate);
SetNextCandidate(candidate, NULL);
- Code* code = candidate->unchecked_code();
+ Code* code = candidate->code();
MarkBit code_mark = Marking::MarkBitFrom(code);
if (!code_mark.Get()) {
candidate->set_code(lazy_compile);
@@ -702,7 +701,7 @@ class CodeFlusher {
static SharedFunctionInfo** GetNextCandidateField(
SharedFunctionInfo* candidate) {
- Code* code = candidate->unchecked_code();
+ Code* code = candidate->code();
return reinterpret_cast<SharedFunctionInfo**>(
code->address() + Code::kNextCodeFlushingCandidateOffset);
}
@@ -1037,12 +1036,12 @@ class StaticMarkingVisitor : public StaticVisitorBase {
inline static bool IsCompiled(JSFunction* function) {
- return function->unchecked_code() !=
+ return function->code() !=
function->GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
}
inline static bool IsCompiled(SharedFunctionInfo* function) {
- return function->unchecked_code() !=
+ return function->code() !=
function->GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
}
@@ -1051,8 +1050,7 @@ class StaticMarkingVisitor : public StaticVisitorBase {
// Code is either on stack, in compilation cache or referenced
// by optimized version of function.
- MarkBit code_mark =
- Marking::MarkBitFrom(function->unchecked_code());
+ MarkBit code_mark = Marking::MarkBitFrom(function->code());
if (code_mark.Get()) {
if (!Marking::MarkBitFrom(shared_info).Get()) {
shared_info->set_code_age(0);
@@ -1061,7 +1059,7 @@ class StaticMarkingVisitor : public StaticVisitorBase {
}
// We do not flush code for optimized functions.
- if (function->code() != shared_info->unchecked_code()) {
+ if (function->code() != shared_info->code()) {
return false;
}
@@ -1072,7 +1070,7 @@ class StaticMarkingVisitor : public StaticVisitorBase {
// Code is either on stack, in compilation cache or referenced
// by optimized version of function.
MarkBit code_mark =
- Marking::MarkBitFrom(shared_info->unchecked_code());
+ Marking::MarkBitFrom(shared_info->code());
if (code_mark.Get()) {
return false;
}
@@ -1085,16 +1083,24 @@ class StaticMarkingVisitor : public StaticVisitorBase {
// We never flush code for Api functions.
Object* function_data = shared_info->function_data();
- if (function_data->IsFunctionTemplateInfo()) return false;
+ if (function_data->IsFunctionTemplateInfo()) {
+ return false;
+ }
// Only flush code for functions.
- if (shared_info->code()->kind() != Code::FUNCTION) return false;
+ if (shared_info->code()->kind() != Code::FUNCTION) {
+ return false;
+ }
// Function must be lazy compilable.
- if (!shared_info->allows_lazy_compilation()) return false;
+ if (!shared_info->allows_lazy_compilation()) {
+ return false;
+ }
// If this is a full script wrapped in a function we do no flush the code.
- if (shared_info->is_toplevel()) return false;
+ if (shared_info->is_toplevel()) {
+ return false;
+ }
// Age this shared function info.
if (shared_info->code_age() < kCodeAgeThreshold) {
@@ -1267,30 +1273,12 @@ class StaticMarkingVisitor : public StaticVisitorBase {
}
if (!flush_code_candidate) {
- Code* code = jsfunction->unchecked_shared()->unchecked_code();
+ Code* code = jsfunction->shared()->code();
MarkBit code_mark = Marking::MarkBitFrom(code);
- heap->mark_compact_collector()->MarkObject(code, code_mark);
-
- if (jsfunction->unchecked_code()->kind() == Code::OPTIMIZED_FUNCTION) {
- // For optimized functions we should retain both non-optimized version
- // of it's code and non-optimized version of all inlined functions.
- // This is required to support bailing out from inlined code.
- DeoptimizationInputData* data =
- reinterpret_cast<DeoptimizationInputData*>(
- jsfunction->unchecked_code()->unchecked_deoptimization_data());
-
- FixedArray* literals = data->UncheckedLiteralArray();
-
- for (int i = 0, count = data->InlinedFunctionCount()->value();
- i < count;
- i++) {
- JSFunction* inlined = reinterpret_cast<JSFunction*>(literals->get(i));
- Code* inlined_code = inlined->unchecked_shared()->unchecked_code();
- MarkBit inlined_code_mark =
- Marking::MarkBitFrom(inlined_code);
- heap->mark_compact_collector()->MarkObject(
- inlined_code, inlined_code_mark);
- }
+ collector->MarkObject(code, code_mark);
+
+ if (jsfunction->code()->kind() == Code::OPTIMIZED_FUNCTION) {
+ collector->MarkInlinedFunctionsCode(jsfunction->code());
}
}
@@ -1415,11 +1403,7 @@ class CodeMarkingVisitor : public ThreadVisitor {
: collector_(collector) {}
void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
- for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
- Code* code = it.frame()->unchecked_code();
- MarkBit code_bit = Marking::MarkBitFrom(code);
- collector_->MarkObject(it.frame()->unchecked_code(), code_bit);
- }
+ collector_->PrepareThreadForCodeFlushing(isolate, top);
}
private:
@@ -1441,8 +1425,8 @@ class SharedFunctionInfoMarkingVisitor : public ObjectVisitor {
if (obj->IsSharedFunctionInfo()) {
SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(obj);
MarkBit shared_mark = Marking::MarkBitFrom(shared);
- MarkBit code_mark = Marking::MarkBitFrom(shared->unchecked_code());
- collector_->MarkObject(shared->unchecked_code(), code_mark);
+ MarkBit code_mark = Marking::MarkBitFrom(shared->code());
+ collector_->MarkObject(shared->code(), code_mark);
collector_->MarkObject(shared, shared_mark);
}
}
@@ -1452,6 +1436,44 @@ class SharedFunctionInfoMarkingVisitor : public ObjectVisitor {
};
+void MarkCompactCollector::MarkInlinedFunctionsCode(Code* code) {
+ // For optimized functions we should retain both non-optimized version
+ // of it's code and non-optimized version of all inlined functions.
+ // This is required to support bailing out from inlined code.
+ DeoptimizationInputData* data =
+ DeoptimizationInputData::cast(code->deoptimization_data());
+
+ FixedArray* literals = data->LiteralArray();
+
+ for (int i = 0, count = data->InlinedFunctionCount()->value();
+ i < count;
+ i++) {
+ JSFunction* inlined = JSFunction::cast(literals->get(i));
+ Code* inlined_code = inlined->shared()->code();
+ MarkBit inlined_code_mark = Marking::MarkBitFrom(inlined_code);
+ MarkObject(inlined_code, inlined_code_mark);
+ }
+}
+
+
+void MarkCompactCollector::PrepareThreadForCodeFlushing(Isolate* isolate,
+ ThreadLocalTop* top) {
+ for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
+ // Note: for the frame that has a pending lazy deoptimization
+ // StackFrame::unchecked_code will return a non-optimized code object for
+ // the outermost function and StackFrame::LookupCode will return
+ // actual optimized code object.
+ StackFrame* frame = it.frame();
+ Code* code = frame->unchecked_code();
+ MarkBit code_mark = Marking::MarkBitFrom(code);
+ MarkObject(code, code_mark);
+ if (frame->is_optimized()) {
+ MarkInlinedFunctionsCode(frame->LookupCode());
+ }
+ }
+}
+
+
void MarkCompactCollector::PrepareForCodeFlushing() {
ASSERT(heap() == Isolate::Current()->heap());
@@ -1479,11 +1501,8 @@ void MarkCompactCollector::PrepareForCodeFlushing() {
// Make sure we are not referencing the code from the stack.
ASSERT(this == heap()->mark_compact_collector());
- for (StackFrameIterator it; !it.done(); it.Advance()) {
- Code* code = it.frame()->unchecked_code();
- MarkBit code_mark = Marking::MarkBitFrom(code);
- MarkObject(code, code_mark);
- }
+ PrepareThreadForCodeFlushing(heap()->isolate(),
+ heap()->isolate()->thread_local_top());
// Iterate the archived stacks in all threads to check if
// the code is referenced.
« no previous file with comments | « src/mark-compact.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698