Modified: trunk/Source/_javascript_Core/ChangeLog (93946 => 93947)
--- trunk/Source/_javascript_Core/ChangeLog 2011-08-27 21:31:09 UTC (rev 93946)
+++ trunk/Source/_javascript_Core/ChangeLog 2011-08-27 21:49:46 UTC (rev 93947)
@@ -1,3 +1,27 @@
+2011-08-27 Filip Pizlo <[email protected]>
+
+ JSC::Executable is inconsistent about using weak handle finalizers
+ and destructors for releasing memory
+ https://bugs.webkit.org/show_bug.cgi?id=67072
+
+ Reviewed by Darin Adler.
+
+ Moved more of the destruction of Executable state into the finalizer,
+ which also resulted in an opportunity to mostly combine this with
+ discardCode(). This also means that the finalizer is now enabled even
+ when the JIT is turned off. This is performance neutral on SunSpider,
+ V8, and Kraken.
+
+ * runtime/Executable.cpp:
+ (JSC::ExecutableBase::clearCode):
+ (JSC::ExecutableFinalizer::finalize):
+ (JSC::EvalExecutable::clearCode):
+ (JSC::ProgramExecutable::clearCode):
+ (JSC::FunctionExecutable::discardCode):
+ (JSC::FunctionExecutable::clearCode):
+ * runtime/Executable.h:
+ (JSC::ExecutableBase::finishCreation):
+
2011-08-26 Gavin Barraclough <[email protected]>
DFG JIT - ArithMod may clobber operands.
Modified: trunk/Source/_javascript_Core/runtime/Executable.cpp (93946 => 93947)
--- trunk/Source/_javascript_Core/runtime/Executable.cpp 2011-08-27 21:31:09 UTC (rev 93946)
+++ trunk/Source/_javascript_Core/runtime/Executable.cpp 2011-08-27 21:49:46 UTC (rev 93947)
@@ -50,7 +50,7 @@
// FIXME: No flow control yet supported, don't bother scanning the bytecode if there are any jump targets.
if (codeBlock->numberOfJumpTargets())
return false;
-#endif
+#endif // ENABLE(DFG_JIT_RESTRICTIONS)
JSGlobalData* globalData = &exec->globalData();
DFG::Graph dfg(codeBlock->m_numParameters, codeBlock->m_numVars);
@@ -68,7 +68,7 @@
// FIXME: No flow control yet supported, don't bother scanning the bytecode if there are any jump targets.
if (codeBlock->numberOfJumpTargets())
return false;
-#endif
+#endif // ENABLE(DFG_JIT_RESTRICTIONS)
JSGlobalData* globalData = &exec->globalData();
DFG::Graph dfg(codeBlock->m_numParameters, codeBlock->m_numVars);
@@ -82,16 +82,29 @@
dataFlowJIT.compileFunction(jitCode, jitCodeWithArityCheck);
return true;
}
-#else
+#else // ENABLE(DFG_JIT)
static bool tryDFGCompile(ExecState*, CodeBlock*, JITCode&) { return false; }
static bool tryDFGCompileFunction(ExecState*, ExecState*, CodeBlock*, JITCode&, MacroAssemblerCodePtr&) { return false; }
+#endif // ENABLE(DFG_JIT)
+#endif // ENABLE(JIT)
+
+void ExecutableBase::clearCode()
+{
+#if ENABLE(JIT)
+ m_jitCodeForCall.clear();
+ m_jitCodeForConstruct.clear();
+ m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
+ m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
#endif
+ m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;
+ m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
+}
class ExecutableFinalizer : public WeakHandleOwner {
virtual void finalize(Handle<Unknown> handle, void*)
{
Weak<ExecutableBase> executable(Weak<ExecutableBase>::Adopt, handle);
- executable->clearExecutableCode();
+ executable->clearCode();
}
};
@@ -100,8 +113,7 @@
DEFINE_STATIC_LOCAL(ExecutableFinalizer, finalizer, ());
return &finalizer;
}
-#endif
-
+
const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, 0 };
NativeExecutable::~NativeExecutable()
@@ -232,6 +244,15 @@
#endif
}
+void EvalExecutable::clearCode()
+{
+ if (m_evalCodeBlock) {
+ m_evalCodeBlock->clearEvalCache();
+ m_evalCodeBlock.clear();
+ }
+ Base::clearCode();
+}
+
JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
{
JSObject* exception = 0;
@@ -316,6 +337,15 @@
m_programCodeBlock->visitAggregate(visitor);
}
+void ProgramExecutable::clearCode()
+{
+ if (m_programCodeBlock) {
+ m_programCodeBlock->clearEvalCache();
+ m_programCodeBlock.clear();
+ }
+ Base::clearCode();
+}
+
JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode, ExecState* calleeArgsExec)
{
JSObject* exception = 0;
@@ -457,20 +487,21 @@
return;
if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
return;
- m_jitCodeForCall = JITCode();
- m_jitCodeForConstruct = JITCode();
- m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
- m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
#endif
- if (m_codeBlockForCall)
+ clearCode();
+}
+
+void FunctionExecutable::clearCode()
+{
+ if (m_codeBlockForCall) {
m_codeBlockForCall->clearEvalCache();
- m_codeBlockForCall.clear();
- if (m_codeBlockForConstruct)
+ m_codeBlockForCall.clear();
+ }
+ if (m_codeBlockForConstruct) {
m_codeBlockForConstruct->clearEvalCache();
- m_codeBlockForConstruct.clear();
- m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;
- m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
-
+ m_codeBlockForConstruct.clear();
+ }
+ Base::clearCode();
}
void FunctionExecutable::unlinkCalls()
Modified: trunk/Source/_javascript_Core/runtime/Executable.h (93946 => 93947)
--- trunk/Source/_javascript_Core/runtime/Executable.h 2011-08-27 21:31:09 UTC (rev 93946)
+++ trunk/Source/_javascript_Core/runtime/Executable.h 2011-08-27 21:49:46 UTC (rev 93947)
@@ -63,10 +63,8 @@
void finishCreation(JSGlobalData& globalData)
{
Base::finishCreation(globalData);
-#if ENABLE(JIT)
Weak<ExecutableBase> finalizer(globalData, this, executableFinalizer());
finalizer.leakHandle();
-#endif
}
public:
@@ -89,6 +87,8 @@
static const ClassInfo s_info;
+ virtual void clearCode();
+
protected:
static const unsigned StructureFlags = 0;
int m_numParametersForCall;
@@ -156,21 +156,15 @@
return hasJITCodeForConstruct();
}
- void clearExecutableCode()
- {
- m_jitCodeForCall.clear();
- m_jitCodeForConstruct.clear();
- }
-
protected:
JITCode m_jitCodeForCall;
JITCode m_jitCodeForConstruct;
MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
+#endif
private:
static WeakHandleOwner* executableFinalizer();
-#endif
};
class NativeExecutable : public ExecutableBase {
@@ -339,6 +333,10 @@
}
static const ClassInfo s_info;
+
+ protected:
+ virtual void clearCode();
+
private:
static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
EvalExecutable(ExecState*, const SourceCode&, bool);
@@ -392,6 +390,9 @@
}
static const ClassInfo s_info;
+
+ protected:
+ virtual void clearCode();
private:
static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
@@ -523,8 +524,10 @@
}
static const ClassInfo s_info;
+
+ protected:
+ virtual void clearCode();
- protected:
void finishCreation(JSGlobalData& globalData, const Identifier& name, int firstLine, int lastLine)
{
m_firstLine = firstLine;