Changeset 228366 in webkit


Ignore:
Timestamp:
Feb 10, 2018 3:49:54 PM (6 years ago)
Author:
fpizlo@apple.com
Message:

Don't waste memory for error.stack
https://bugs.webkit.org/show_bug.cgi?id=182656

Reviewed by Saam Barati.

JSTests:

Tests the policy.

  • stress/gc-error-stack.js: Added. Shows that the GC forgets frames now.
  • stress/no-gc-error-stack.js: Added. Shows that the GC won't forget things if you ask for the stack.

Source/JavaScriptCore:

This makes the StackFrames in ErrorInstance and Exception weak. We simply forget their
contents if we GC.

This isn't going to happen under normal operation since your callees and code blocks will
still be alive when you ask for .stack.

Bug 182650 tracks improving this so that it's not lossy. For now, I think it's worth it,
since it is likely to recover 3-5 MB on membuster.

  • heap/Heap.cpp:

(JSC::Heap::finalizeUnconditionalFinalizers):

  • runtime/ErrorInstance.cpp:

(JSC::ErrorInstance::visitChildren):
(JSC::ErrorInstance::finalizeUnconditionally):

  • runtime/ErrorInstance.h:

(JSC::ErrorInstance::subspaceFor):

  • runtime/Exception.cpp:

(JSC::Exception::visitChildren):
(JSC::Exception::finalizeUnconditionally):

  • runtime/Exception.h:

(JSC::Exception::valueOffset): Deleted.
(JSC::Exception::value const): Deleted.
(JSC::Exception::stack const): Deleted.
(JSC::Exception::didNotifyInspectorOfThrow const): Deleted.
(JSC::Exception::setDidNotifyInspectorOfThrow): Deleted.

  • runtime/StackFrame.cpp:

(JSC::StackFrame::isFinalizationCandidate):
(JSC::StackFrame::finalizeUnconditionally):
(JSC::StackFrame::visitChildren): Deleted.

  • runtime/StackFrame.h:
  • runtime/VM.cpp:

(JSC::VM::VM):

  • runtime/VM.h:
Location:
trunk
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r228311 r228366  
     12018-02-09  Filip Pizlo  <fpizlo@apple.com>
     2
     3        Don't waste memory for error.stack
     4        https://bugs.webkit.org/show_bug.cgi?id=182656
     5
     6        Reviewed by Saam Barati.
     7       
     8        Tests the policy.
     9
     10        * stress/gc-error-stack.js: Added. Shows that the GC forgets frames now.
     11        * stress/no-gc-error-stack.js: Added. Shows that the GC won't forget things if you ask for the stack.
     12
    1132018-02-08  Yusuke Suzuki  <utatane.tea@gmail.com>
    214
  • trunk/Source/JavaScriptCore/ChangeLog

    r228318 r228366  
     12018-02-09  Filip Pizlo  <fpizlo@apple.com>
     2
     3        Don't waste memory for error.stack
     4        https://bugs.webkit.org/show_bug.cgi?id=182656
     5
     6        Reviewed by Saam Barati.
     7       
     8        This makes the StackFrames in ErrorInstance and Exception weak. We simply forget their
     9        contents if we GC.
     10       
     11        This isn't going to happen under normal operation since your callees and code blocks will
     12        still be alive when you ask for .stack.
     13       
     14        Bug 182650 tracks improving this so that it's not lossy. For now, I think it's worth it,
     15        since it is likely to recover 3-5 MB on membuster.
     16
     17        * heap/Heap.cpp:
     18        (JSC::Heap::finalizeUnconditionalFinalizers):
     19        * runtime/ErrorInstance.cpp:
     20        (JSC::ErrorInstance::visitChildren):
     21        (JSC::ErrorInstance::finalizeUnconditionally):
     22        * runtime/ErrorInstance.h:
     23        (JSC::ErrorInstance::subspaceFor):
     24        * runtime/Exception.cpp:
     25        (JSC::Exception::visitChildren):
     26        (JSC::Exception::finalizeUnconditionally):
     27        * runtime/Exception.h:
     28        (JSC::Exception::valueOffset): Deleted.
     29        (JSC::Exception::value const): Deleted.
     30        (JSC::Exception::stack const): Deleted.
     31        (JSC::Exception::didNotifyInspectorOfThrow const): Deleted.
     32        (JSC::Exception::setDidNotifyInspectorOfThrow): Deleted.
     33        * runtime/StackFrame.cpp:
     34        (JSC::StackFrame::isFinalizationCandidate):
     35        (JSC::StackFrame::finalizeUnconditionally):
     36        (JSC::StackFrame::visitChildren): Deleted.
     37        * runtime/StackFrame.h:
     38        * runtime/VM.cpp:
     39        (JSC::VM::VM):
     40        * runtime/VM.h:
     41
    1422018-02-09  Carlos Alberto Lopez Perez  <clopez@igalia.com>
    243
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r227738 r228366  
    580580void Heap::finalizeUnconditionalFinalizers()
    581581{
     582    finalizeMarkedUnconditionalFinalizers<ErrorInstance>(vm()->errorInstancesWithFinalizers);
     583    finalizeMarkedUnconditionalFinalizers<Exception>(vm()->exceptionsWithFinalizers);
    582584    finalizeMarkedUnconditionalFinalizers<InferredType>(vm()->inferredTypesWithFinalizers);
    583585    finalizeMarkedUnconditionalFinalizers<InferredValue>(vm()->inferredValuesWithFinalizers);
  • trunk/Source/JavaScriptCore/runtime/ErrorInstance.cpp

    r227906 r228366  
    11/*
    22 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
    3  *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
     3 *  Copyright (C) 2003-2018 Apple Inc. All rights reserved.
    44 *
    55 *  This library is free software; you can redistribute it and/or
     
    2424#include "CodeBlock.h"
    2525#include "InlineCallFrame.h"
     26#include "IsoCellSetInlines.h"
    2627#include "JSScope.h"
    2728#include "JSCInlines.h"
     
    234235    Base::visitChildren(thisObject, visitor);
    235236
     237    bool isFinalizationCandidate = false;
    236238    {
    237239        auto locker = holdLock(thisObject->cellLock());
    238240        if (thisObject->m_stackTrace) {
    239             for (StackFrame& frame : *thisObject->m_stackTrace)
    240                 frame.visitChildren(visitor);
     241            for (StackFrame& frame : *thisObject->m_stackTrace) {
     242                if (frame.isFinalizationCandidate()) {
     243                    isFinalizationCandidate = true;
     244                    break;
     245                }
     246            }
    241247        }
    242248    }
     249    if (isFinalizationCandidate)
     250        visitor.vm().errorInstancesWithFinalizers.add(thisObject);
     251}
     252
     253void ErrorInstance::finalizeUnconditionally(VM& vm)
     254{
     255    {
     256        auto locker = holdLock(cellLock());
     257        if (m_stackTrace) {
     258            for (StackFrame& frame : *m_stackTrace)
     259                frame.finalizeUnconditionally(vm);
     260        }
     261    }
     262   
     263    vm.errorInstancesWithFinalizers.remove(this);
    243264}
    244265
  • trunk/Source/JavaScriptCore/runtime/ErrorInstance.h

    r225768 r228366  
    11/*
    22 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
    3  *  Copyright (C) 2008-2017 Apple Inc. All rights reserved.
     3 *  Copyright (C) 2008-2018 Apple Inc. All rights reserved.
    44 *
    55 *  This library is free software; you can redistribute it and/or
     
    2727namespace JSC {
    2828
     29// FIXME: This should be final, but isn't because of bizarre (and mostly wrong) things done in
     30// WebAssembly.
     31// https://bugs.webkit.org/show_bug.cgi?id=182649
    2932class ErrorInstance : public JSDestructibleObject {
    3033public:
     34    template<typename CellType>
     35    static IsoSubspace* subspaceFor(VM& vm)
     36    {
     37        return &vm.errorInstanceSpace;
     38    }
     39
    3140    typedef JSDestructibleObject Base;
    3241    const static unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetPropertyNames;
     
    6978   
    7079    Vector<StackFrame>* stackTrace() { return m_stackTrace.get(); }
     80   
     81    void finalizeUnconditionally(VM&);
    7182
    7283    bool materializeErrorInfoIfNeeded(VM&);
  • trunk/Source/JavaScriptCore/runtime/Exception.cpp

    r221836 r228366  
    11/*
    2  * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2828
    2929#include "Interpreter.h"
     30#include "IsoCellSetInlines.h"
    3031#include "JSCInlines.h"
    3132
     
    5859    Base::visitChildren(thisObject, visitor);
    5960
     61    bool isFinalizationCandidate = false;
    6062    visitor.append(thisObject->m_value);
    61     for (StackFrame& frame : thisObject->m_stack)
    62         frame.visitChildren(visitor);
     63    for (StackFrame& frame : thisObject->m_stack) {
     64        if (frame.isFinalizationCandidate()) {
     65            isFinalizationCandidate = true;
     66            break;
     67        }
     68    }
     69    if (isFinalizationCandidate)
     70        visitor.vm().exceptionsWithFinalizers.add(thisObject);
     71}
     72
     73void Exception::finalizeUnconditionally(VM& vm)
     74{
     75    for (StackFrame& frame : m_stack)
     76        frame.finalizeUnconditionally(vm);
     77   
     78    vm.exceptionsWithFinalizers.remove(this);
    6379}
    6480
  • trunk/Source/JavaScriptCore/runtime/Exception.h

    r222186 r228366  
    11/*
    2  * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3232namespace JSC {
    3333   
    34 class Exception : public JSDestructibleObject {
     34class Exception final : public JSDestructibleObject {
    3535public:
     36    template<typename CellType>
     37    static IsoSubspace* subspaceFor(VM& vm)
     38    {
     39        return &vm.exceptionSpace;
     40    }
     41
    3642    typedef JSDestructibleObject Base;
    3743    static const unsigned StructureFlags = StructureIsImmortal | Base::StructureFlags;
     
    6167
    6268    ~Exception();
     69   
     70    void finalizeUnconditionally(VM&);
    6371
    6472private:
  • trunk/Source/JavaScriptCore/runtime/StackFrame.cpp

    r225378 r228366  
    11/*
    2  * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    143143}
    144144
    145 void StackFrame::visitChildren(SlotVisitor& visitor)
     145bool StackFrame::isFinalizationCandidate()
    146146{
    147     if (m_callee)
    148         visitor.append(m_callee);
    149     if (m_codeBlock)
    150         visitor.append(m_codeBlock);
     147    if (m_callee && !Heap::isMarked(m_callee.get()))
     148        return true;
     149    if (m_codeBlock && !Heap::isMarked(m_codeBlock.get()))
     150        return true;
     151    return false;
     152}
     153
     154void StackFrame::finalizeUnconditionally(VM&)
     155{
     156    // FIXME: We should do something smarter. For example, if this happens, we could stringify the
     157    // whole stack trace. The main shortcoming is that that requires doing operations that are not
     158    // currently legal during finalization. We could make this work by giving JSC a proper "second
     159    // chance" finalizer infrastructure. Or maybe there's an even easier way.
     160    // https://bugs.webkit.org/show_bug.cgi?id=182650
     161   
     162    if (m_callee && !Heap::isMarked(m_callee.get()))
     163        m_callee.clear();
     164    if (m_codeBlock && !Heap::isMarked(m_codeBlock.get()))
     165        m_codeBlock.clear();
    151166}
    152167
  • trunk/Source/JavaScriptCore/runtime/StackFrame.h

    r224272 r228366  
    11/*
    2  * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    5757    }
    5858   
    59     void visitChildren(SlotVisitor&);
     59    bool isFinalizationCandidate();
     60    void finalizeUnconditionally(VM&);
    6061
    6162private:
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r228260 r228366  
    252252#endif
    253253    , directEvalExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), DirectEvalExecutable)
     254    , errorInstanceSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), ErrorInstance)
     255    , exceptionSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), Exception)
    254256    , executableToCodeBlockEdgeSpace ISO_SUBSPACE_INIT(heap, cellHeapCellType.get(), ExecutableToCodeBlockEdge)
    255257    , functionExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), FunctionExecutable)
     
    265267    , weakSetSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), JSWeakSet)
    266268    , weakMapSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), JSWeakMap)
     269    , errorInstancesWithFinalizers(errorInstanceSpace)
     270    , exceptionsWithFinalizers(exceptionSpace)
    267271    , executableToCodeBlockEdgesWithConstraints(executableToCodeBlockEdgeSpace)
    268272    , executableToCodeBlockEdgesWithFinalizers(executableToCodeBlockEdgeSpace)
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r228260 r228366  
    340340   
    341341    IsoSubspace directEvalExecutableSpace;
     342    IsoSubspace errorInstanceSpace;
     343    IsoSubspace exceptionSpace;
    342344    IsoSubspace executableToCodeBlockEdgeSpace;
    343345    IsoSubspace functionExecutableSpace;
     
    354356    IsoSubspace weakMapSpace;
    355357   
     358    IsoCellSet errorInstancesWithFinalizers;
     359    IsoCellSet exceptionsWithFinalizers;
    356360    IsoCellSet executableToCodeBlockEdgesWithConstraints;
    357361    IsoCellSet executableToCodeBlockEdgesWithFinalizers;
Note: See TracChangeset for help on using the changeset viewer.