If the top optimized code in call stack is at the point that does not support
deoptimization, then treat the maps in the code as strong pointers.
Note that other optimized code in call stack must support deoptimization
because of the call instruction with side-effects.
BUG=217858,v8:2073
R=mstarzinger@chromium.org
Review URL: https://chromiumcodereview.appspot.com/
16955008
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15452
ce2b1a6d-e550-0410-aec6-
3dcde31c8c00
"it is adjusted.")
DEFINE_bool(collect_maps, true,
"garbage collect maps from which no objects can be reached")
-DEFINE_bool(weak_embedded_maps_in_optimized_code, false,
+DEFINE_bool(weak_embedded_maps_in_optimized_code, true,
"make maps embedded in optimized code weak")
DEFINE_bool(flush_code, true,
"flush code that we expect not to use again (during full gc)")
}
+static StackFrame* TopOptimizedFrame(Isolate* isolate) {
+ for (StackFrameIterator it(isolate, isolate->thread_local_top());
+ !it.done(); it.Advance()) {
+ if (it.frame()->type() == StackFrame::JAVA_SCRIPT) {
+ return NULL;
+ }
+ if (it.frame()->type() == StackFrame::OPTIMIZED) {
+ return it.frame();
+ }
+ }
+ return NULL;
+}
+
+
+void MarkCompactCollector::ProcessTopOptimizedFrame(ObjectVisitor* visitor) {
+ StackFrame* frame = TopOptimizedFrame(isolate());
+ if (frame != NULL) {
+ Code* code = frame->LookupCode();
+ if (!code->CanDeoptAt(frame->pc())) {
+ code->CodeIterateBody(visitor);
+ }
+ ProcessMarkingDeque();
+ }
+}
+
+
void MarkCompactCollector::MarkLiveObjects() {
GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_MARK);
// The recursive GC marker detects when it is nearing stack overflow,
RootMarkingVisitor root_visitor(heap());
MarkRoots(&root_visitor);
+ ProcessTopOptimizedFrame(&root_visitor);
+
// The objects reachable from the roots are marked, yet unreachable
// objects are unmarked. Mark objects reachable due to host
// application specific logic or through Harmony weak maps.
// or implicit references' groups.
void ProcessEphemeralMarking(ObjectVisitor* visitor);
+ // If the call-site of the top optimized code was not prepared for
+ // deoptimization, then treat the maps in the code as strong pointers,
+ // otherwise a map can die and deoptimize the code.
+ void ProcessTopOptimizedFrame(ObjectVisitor* visitor);
+
// Mark objects reachable (transitively) from objects in the marking
// stack. This function empties the marking stack, but may leave
// overflowed objects in the heap, in which case the marking stack's
}
+bool Code::CanDeoptAt(Address pc) {
+ DeoptimizationInputData* deopt_data =
+ DeoptimizationInputData::cast(deoptimization_data());
+ Address code_start_address = instruction_start();
+ for (int i = 0; i < deopt_data->DeoptCount(); i++) {
+ if (deopt_data->Pc(i)->value() == -1) continue;
+ Address address = code_start_address + deopt_data->Pc(i)->value();
+ if (address == pc) return true;
+ }
+ return false;
+}
+
+
// Identify kind of code.
const char* Code::Kind2String(Kind kind) {
switch (kind) {
int GetAge();
void PrintDeoptLocation(int bailout_id);
+ bool CanDeoptAt(Address pc);
#ifdef VERIFY_HEAP
void VerifyEmbeddedMapsDependency();
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --allow-natives-syntax
+// Flags: --noanalyze_environment_liveness
var r = /r/;
-var a = "";
function f() {
- %OptimizeFunctionOnNextCall(f, "osr");
- for (var i = 0; i < 1000000; i++) {
- a += i.toString();
- r[r] = function() {};
- }
+ r[r] = function() {};
}
-f();
+for (var i = 0; i < 300000; i++) {
+ f();
+}