Diff
Modified: trunk/JSTests/ChangeLog (246504 => 246505)
--- trunk/JSTests/ChangeLog 2019-06-17 18:44:18 UTC (rev 246504)
+++ trunk/JSTests/ChangeLog 2019-06-17 18:49:03 UTC (rev 246505)
@@ -1,3 +1,17 @@
+2019-06-17 Yusuke Suzuki <ysuz...@apple.com>
+
+ [JSC] Introduce DisposableCallSiteIndex to enforce type-safety
+ https://bugs.webkit.org/show_bug.cgi?id=197378
+
+ Reviewed by Saam Barati.
+
+ * stress/disposable-call-site-index-with-call-and-this.js: Added.
+ (foo):
+ (bar):
+ * stress/disposable-call-site-index.js: Added.
+ (foo):
+ (bar):
+
2019-06-17 Justin Michaud <justin_mich...@apple.com>
[WASM-References] Add support for Funcref in parameters and return types
Added: trunk/JSTests/stress/disposable-call-site-index-with-call-and-this.js (0 => 246505)
--- trunk/JSTests/stress/disposable-call-site-index-with-call-and-this.js (rev 0)
+++ trunk/JSTests/stress/disposable-call-site-index-with-call-and-this.js 2019-06-17 18:49:03 UTC (rev 246505)
@@ -0,0 +1,26 @@
+var ia = new Int8Array(1024);
+
+function foo(o) {
+ return o.f;
+}
+
+function bar(o) {
+
+ try {
+ o.f = 0x1;
+ Uint8Array.prototype.find.call(ia, function () {
+ o.f = 0x1;
+ }, this);
+ } catch (e) {
+ }
+
+ foo(o);
+}
+
+var o = new Object();
+o.__defineGetter__("f", function () { });
+
+for (var i = 0; i < 1000; ++i) {
+ bar({});
+ bar(o);
+}
Added: trunk/JSTests/stress/disposable-call-site-index.js (0 => 246505)
--- trunk/JSTests/stress/disposable-call-site-index.js (rev 0)
+++ trunk/JSTests/stress/disposable-call-site-index.js 2019-06-17 18:49:03 UTC (rev 246505)
@@ -0,0 +1,28 @@
+//@ runDefault("--useConcurrentJIT=0", "--useConcurrentGC=0", "--thresholdForJITAfterWarmUp=10", "--thresholdForOptimizeAfterWarmUp=100", "--thresholdForOptimizeAfterLongWarmUp=100", "--thresholdForOptimizeAfterLongWarmUp=100")
+
+var ia = new Int8Array(1024);
+
+function foo(o) {
+ return o.f;
+}
+
+function bar(o) {
+
+ try {
+ o.f = 0x1;
+ Uint8Array.prototype.find.call(ia, function () {
+ o.f = 0x1;
+ });
+ } catch (e) {
+ }
+
+ foo(o);
+}
+
+var o = new Object();
+o.__defineGetter__("f", function () { });
+
+for (var i = 0; i < 1000; ++i) {
+ bar({});
+ bar(o);
+}
Modified: trunk/Source/_javascript_Core/ChangeLog (246504 => 246505)
--- trunk/Source/_javascript_Core/ChangeLog 2019-06-17 18:44:18 UTC (rev 246504)
+++ trunk/Source/_javascript_Core/ChangeLog 2019-06-17 18:49:03 UTC (rev 246505)
@@ -1,3 +1,48 @@
+2019-06-17 Yusuke Suzuki <ysuz...@apple.com>
+
+ [JSC] Introduce DisposableCallSiteIndex to enforce type-safety
+ https://bugs.webkit.org/show_bug.cgi?id=197378
+
+ Reviewed by Saam Barati.
+
+ Some of CallSiteIndex are disposable. This is because some of CallSiteIndex are allocated and freed at runtime (not DFG/FTL compile time).
+ The example is CallSiteIndex for exception handler in GCAwareJITStubRoutineWithExceptionHandler. If we do not allocate and free CallSiteIndex,
+ we will create a new CallSiteIndex continuously and leak memory.
+
+ The other CallSiteIndex are not simply disposable because the ownership model is not unique one. They can be shared between multiple clients.
+ But not disposing them is OK because they are static one: they are allocated when compiling DFG/FTL, and we do not allocate such CallSiteIndex
+ at runtime.
+
+ To make this difference explicit and avoid disposing non-disposable CallSiteIndex accidentally, we introduce DisposableCallSiteIndex type, and
+ enforce type-safety to some degree.
+
+ We also correctly update the DisposableCallSiteIndex => CodeOrigin table when we are reusing the previously used DisposableCallSiteIndex.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::newExceptionHandlingCallSiteIndex):
+ (JSC::CodeBlock::removeExceptionHandlerForCallSite):
+ * bytecode/CodeBlock.h:
+ * bytecode/PolymorphicAccess.cpp:
+ (JSC::AccessGenerationState::callSiteIndexForExceptionHandling):
+ (JSC::PolymorphicAccess::regenerate):
+ * bytecode/PolymorphicAccess.h:
+ (JSC::AccessGenerationState::callSiteIndexForExceptionHandling): Deleted.
+ * dfg/DFGCommonData.cpp:
+ (JSC::DFG::CommonData::addUniqueCallSiteIndex):
+ (JSC::DFG::CommonData::addDisposableCallSiteIndex):
+ (JSC::DFG::CommonData::removeDisposableCallSiteIndex):
+ (JSC::DFG::CommonData::removeCallSiteIndex): Deleted.
+ * dfg/DFGCommonData.h:
+ * interpreter/CallFrame.h:
+ (JSC::DisposableCallSiteIndex::DisposableCallSiteIndex):
+ (JSC::DisposableCallSiteIndex::fromCallSiteIndex):
+ * jit/GCAwareJITStubRoutine.cpp:
+ (JSC::GCAwareJITStubRoutineWithExceptionHandler::GCAwareJITStubRoutineWithExceptionHandler):
+ (JSC::GCAwareJITStubRoutineWithExceptionHandler::observeZeroRefCount):
+ (JSC::createJITStubRoutine):
+ * jit/GCAwareJITStubRoutine.h:
+ * jit/JITInlineCacheGenerator.h:
+
2019-06-17 Justin Michaud <justin_mich...@apple.com>
[WASM-References] Add support for Funcref in parameters and return types
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (246504 => 246505)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2019-06-17 18:44:18 UTC (rev 246504)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2019-06-17 18:49:03 UTC (rev 246505)
@@ -1725,7 +1725,7 @@
return HandlerInfo::handlerForIndex(m_rareData->m_exceptionHandlers, index, requiredHandler);
}
-CallSiteIndex CodeBlock::newExceptionHandlingCallSiteIndex(CallSiteIndex originalCallSite)
+DisposableCallSiteIndex CodeBlock::newExceptionHandlingCallSiteIndex(CallSiteIndex originalCallSite)
{
#if ENABLE(DFG_JIT)
RELEASE_ASSERT(JITCode::isOptimizingJIT(jitType()));
@@ -1732,13 +1732,13 @@
RELEASE_ASSERT(canGetCodeOrigin(originalCallSite));
ASSERT(!!handlerForIndex(originalCallSite.bits()));
CodeOrigin originalOrigin = codeOrigin(originalCallSite);
- return m_jitCode->dfgCommon()->addUniqueCallSiteIndex(originalOrigin);
+ return m_jitCode->dfgCommon()->addDisposableCallSiteIndex(originalOrigin);
#else
// We never create new on-the-fly exception handling
// call sites outside the DFG/FTL inline caches.
UNUSED_PARAM(originalCallSite);
RELEASE_ASSERT_NOT_REACHED();
- return CallSiteIndex(0u);
+ return DisposableCallSiteIndex(0u);
#endif
}
@@ -1808,7 +1808,7 @@
}
}
-void CodeBlock::removeExceptionHandlerForCallSite(CallSiteIndex callSiteIndex)
+void CodeBlock::removeExceptionHandlerForCallSite(DisposableCallSiteIndex callSiteIndex)
{
RELEASE_ASSERT(m_rareData);
Vector<HandlerInfo>& exceptionHandlers = m_rareData->m_exceptionHandlers;
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (246504 => 246505)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2019-06-17 18:44:18 UTC (rev 246504)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2019-06-17 18:49:03 UTC (rev 246505)
@@ -241,7 +241,7 @@
HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset, RequiredHandler = RequiredHandler::AnyHandler);
HandlerInfo* handlerForIndex(unsigned, RequiredHandler = RequiredHandler::AnyHandler);
- void removeExceptionHandlerForCallSite(CallSiteIndex);
+ void removeExceptionHandlerForCallSite(DisposableCallSiteIndex);
unsigned lineNumberForBytecodeOffset(unsigned bytecodeOffset);
unsigned columnNumberForBytecodeOffset(unsigned bytecodeOffset);
void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot,
@@ -867,7 +867,7 @@
m_rareData->m_exceptionHandlers.append(handler);
}
- CallSiteIndex newExceptionHandlingCallSiteIndex(CallSiteIndex originalCallSite);
+ DisposableCallSiteIndex newExceptionHandlingCallSiteIndex(CallSiteIndex originalCallSite);
void ensureCatchLivenessIsComputedForBytecodeOffset(InstructionStream::Offset bytecodeOffset);
Modified: trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.cpp (246504 => 246505)
--- trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.cpp 2019-06-17 18:44:18 UTC (rev 246504)
+++ trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.cpp 2019-06-17 18:49:03 UTC (rev 246505)
@@ -163,6 +163,14 @@
return m_callSiteIndex;
}
+DisposableCallSiteIndex AccessGenerationState::callSiteIndexForExceptionHandling()
+{
+ RELEASE_ASSERT(m_calculatedRegistersForCallAndExceptionHandling);
+ RELEASE_ASSERT(m_needsToRestoreRegistersIfException);
+ RELEASE_ASSERT(m_calculatedCallSiteIndex);
+ return DisposableCallSiteIndex::fromCallSiteIndex(m_callSiteIndex);
+}
+
const HandlerInfo& AccessGenerationState::originalExceptionHandler()
{
if (!m_calculatedRegistersForCallAndExceptionHandling)
@@ -539,7 +547,7 @@
failure.append(jit.jump());
CodeBlock* codeBlockThatOwnsExceptionHandlers = nullptr;
- CallSiteIndex callSiteIndexForExceptionHandling;
+ DisposableCallSiteIndex callSiteIndexForExceptionHandling;
if (state.needsToRestoreRegistersIfException() && hasJSGetterSetterCall) {
// Emit the exception handler.
// Note that this code is only reachable when doing genericUnwind from a pure JS getter/setter .
@@ -561,7 +569,7 @@
CCallHelpers::Jump jumpToOSRExitExceptionHandler = jit.jump();
HandlerInfo oldHandler = state.originalExceptionHandler();
- CallSiteIndex newExceptionHandlingCallSite = state.callSiteIndexForExceptionHandling();
+ DisposableCallSiteIndex newExceptionHandlingCallSite = state.callSiteIndexForExceptionHandling();
jit.addLinkTask(
[=] (LinkBuffer& linkBuffer) {
linkBuffer.link(jumpToOSRExitExceptionHandler, oldHandler.nativeCode);
Modified: trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.h (246504 => 246505)
--- trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.h 2019-06-17 18:44:18 UTC (rev 246504)
+++ trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.h 2019-06-17 18:49:03 UTC (rev 246505)
@@ -241,13 +241,7 @@
const RegisterSet& liveRegistersForCall();
CallSiteIndex callSiteIndexForExceptionHandlingOrOriginal();
- CallSiteIndex callSiteIndexForExceptionHandling()
- {
- RELEASE_ASSERT(m_calculatedRegistersForCallAndExceptionHandling);
- RELEASE_ASSERT(m_needsToRestoreRegistersIfException);
- RELEASE_ASSERT(m_calculatedCallSiteIndex);
- return m_callSiteIndex;
- }
+ DisposableCallSiteIndex callSiteIndexForExceptionHandling();
const HandlerInfo& originalExceptionHandler();
@@ -271,7 +265,7 @@
RegisterSet m_liveRegistersToPreserveAtExceptionHandlingCallSite;
RegisterSet m_liveRegistersForCall;
- CallSiteIndex m_callSiteIndex { CallSiteIndex(std::numeric_limits<unsigned>::max()) };
+ CallSiteIndex m_callSiteIndex;
SpillState m_spillStateForJSGetterSetter;
bool m_calculatedRegistersForCallAndExceptionHandling : 1;
bool m_needsToRestoreRegistersIfException : 1;
Modified: trunk/Source/_javascript_Core/dfg/DFGCommonData.cpp (246504 => 246505)
--- trunk/Source/_javascript_Core/dfg/DFGCommonData.cpp 2019-06-17 18:44:18 UTC (rev 246504)
+++ trunk/Source/_javascript_Core/dfg/DFGCommonData.cpp 2019-06-17 18:49:03 UTC (rev 246505)
@@ -61,9 +61,6 @@
CallSiteIndex CommonData::addUniqueCallSiteIndex(CodeOrigin codeOrigin)
{
- if (callSiteIndexFreeList.size())
- return CallSiteIndex(callSiteIndexFreeList.takeAny());
-
codeOrigins.append(codeOrigin);
unsigned index = codeOrigins.size() - 1;
ASSERT(codeOrigins[index] == codeOrigin);
@@ -76,10 +73,26 @@
return CallSiteIndex(codeOrigins.size() - 1);
}
-void CommonData::removeCallSiteIndex(CallSiteIndex callSite)
+DisposableCallSiteIndex CommonData::addDisposableCallSiteIndex(CodeOrigin codeOrigin)
{
+ if (callSiteIndexFreeList.size()) {
+ unsigned index = callSiteIndexFreeList.takeAny();
+ codeOrigins[index] = codeOrigin;
+ return DisposableCallSiteIndex(index);
+ }
+
+ codeOrigins.append(codeOrigin);
+ unsigned index = codeOrigins.size() - 1;
+ ASSERT(codeOrigins[index] == codeOrigin);
+ return DisposableCallSiteIndex(index);
+}
+
+
+void CommonData::removeDisposableCallSiteIndex(DisposableCallSiteIndex callSite)
+{
RELEASE_ASSERT(callSite.bits() < codeOrigins.size());
callSiteIndexFreeList.add(callSite.bits());
+ codeOrigins[callSite.bits()] = CodeOrigin();
}
void CommonData::shrinkToFit()
Modified: trunk/Source/_javascript_Core/dfg/DFGCommonData.h (246504 => 246505)
--- trunk/Source/_javascript_Core/dfg/DFGCommonData.h 2019-06-17 18:44:18 UTC (rev 246504)
+++ trunk/Source/_javascript_Core/dfg/DFGCommonData.h 2019-06-17 18:49:03 UTC (rev 246505)
@@ -83,7 +83,9 @@
CallSiteIndex addCodeOrigin(CodeOrigin);
CallSiteIndex addUniqueCallSiteIndex(CodeOrigin);
CallSiteIndex lastCallSite() const;
- void removeCallSiteIndex(CallSiteIndex);
+
+ DisposableCallSiteIndex addDisposableCallSiteIndex(CodeOrigin);
+ void removeDisposableCallSiteIndex(DisposableCallSiteIndex);
void shrinkToFit();
Modified: trunk/Source/_javascript_Core/interpreter/CallFrame.h (246504 => 246505)
--- trunk/Source/_javascript_Core/interpreter/CallFrame.h 2019-06-17 18:44:18 UTC (rev 246504)
+++ trunk/Source/_javascript_Core/interpreter/CallFrame.h 2019-06-17 18:49:03 UTC (rev 246505)
@@ -43,11 +43,9 @@
typedef ExecState CallFrame;
- struct CallSiteIndex {
- CallSiteIndex()
- : m_bits(UINT_MAX)
- {
- }
+ class CallSiteIndex {
+ public:
+ CallSiteIndex() = default;
explicit CallSiteIndex(uint32_t bits)
: m_bits(bits)
@@ -64,9 +62,24 @@
inline uint32_t bits() const { return m_bits; }
private:
- uint32_t m_bits;
+ uint32_t m_bits { UINT_MAX };
};
+ class DisposableCallSiteIndex : public CallSiteIndex {
+ public:
+ DisposableCallSiteIndex() = default;
+
+ explicit DisposableCallSiteIndex(uint32_t bits)
+ : CallSiteIndex(bits)
+ {
+ }
+
+ static DisposableCallSiteIndex fromCallSiteIndex(CallSiteIndex callSiteIndex)
+ {
+ return DisposableCallSiteIndex(callSiteIndex.bits());
+ }
+ };
+
// arm64_32 expects caller frame and return pc to use 8 bytes
struct CallerFrameAndPC {
alignas(CPURegister) CallFrame* callerFrame;
Modified: trunk/Source/_javascript_Core/jit/GCAwareJITStubRoutine.cpp (246504 => 246505)
--- trunk/Source/_javascript_Core/jit/GCAwareJITStubRoutine.cpp 2019-06-17 18:44:18 UTC (rev 246504)
+++ trunk/Source/_javascript_Core/jit/GCAwareJITStubRoutine.cpp 2019-06-17 18:49:03 UTC (rev 246505)
@@ -102,7 +102,7 @@
GCAwareJITStubRoutineWithExceptionHandler::GCAwareJITStubRoutineWithExceptionHandler(
const MacroAssemblerCodeRef<JITStubRoutinePtrTag>& code, VM& vm, const JSCell* owner, const Vector<JSCell*>& cells,
- CodeBlock* codeBlockForExceptionHandlers, CallSiteIndex exceptionHandlerCallSiteIndex)
+ CodeBlock* codeBlockForExceptionHandlers, DisposableCallSiteIndex exceptionHandlerCallSiteIndex)
: MarkingGCAwareJITStubRoutine(code, vm, owner, cells)
, m_codeBlockWithExceptionHandler(codeBlockForExceptionHandlers)
, m_exceptionHandlerCallSiteIndex(exceptionHandlerCallSiteIndex)
@@ -120,7 +120,7 @@
{
#if ENABLE(DFG_JIT)
if (m_codeBlockWithExceptionHandler) {
- m_codeBlockWithExceptionHandler->jitCode()->dfgCommon()->removeCallSiteIndex(m_exceptionHandlerCallSiteIndex);
+ m_codeBlockWithExceptionHandler->jitCode()->dfgCommon()->removeDisposableCallSiteIndex(m_exceptionHandlerCallSiteIndex);
m_codeBlockWithExceptionHandler->removeExceptionHandlerForCallSite(m_exceptionHandlerCallSiteIndex);
m_codeBlockWithExceptionHandler = nullptr;
}
@@ -137,7 +137,7 @@
bool makesCalls,
const Vector<JSCell*>& cells,
CodeBlock* codeBlockForExceptionHandlers,
- CallSiteIndex exceptionHandlerCallSiteIndex)
+ DisposableCallSiteIndex exceptionHandlerCallSiteIndex)
{
if (!makesCalls)
return adoptRef(*new JITStubRoutine(code));
Modified: trunk/Source/_javascript_Core/jit/GCAwareJITStubRoutine.h (246504 => 246505)
--- trunk/Source/_javascript_Core/jit/GCAwareJITStubRoutine.h 2019-06-17 18:44:18 UTC (rev 246504)
+++ trunk/Source/_javascript_Core/jit/GCAwareJITStubRoutine.h 2019-06-17 18:49:03 UTC (rev 246505)
@@ -89,12 +89,12 @@
// The stub has exception handlers in it. So it clears itself from exception
// handling table when it dies. It also frees space in CodeOrigin table
-// for new exception handlers to use the same CallSiteIndex.
+// for new exception handlers to use the same DisposableCallSiteIndex.
class GCAwareJITStubRoutineWithExceptionHandler : public MarkingGCAwareJITStubRoutine {
public:
typedef GCAwareJITStubRoutine Base;
- GCAwareJITStubRoutineWithExceptionHandler(const MacroAssemblerCodeRef<JITStubRoutinePtrTag>&, VM&, const JSCell* owner, const Vector<JSCell*>&, CodeBlock*, CallSiteIndex);
+ GCAwareJITStubRoutineWithExceptionHandler(const MacroAssemblerCodeRef<JITStubRoutinePtrTag>&, VM&, const JSCell* owner, const Vector<JSCell*>&, CodeBlock*, DisposableCallSiteIndex);
void aboutToDie() override;
void observeZeroRefCount() override;
@@ -101,7 +101,7 @@
private:
CodeBlock* m_codeBlockWithExceptionHandler;
- CallSiteIndex m_exceptionHandlerCallSiteIndex;
+ DisposableCallSiteIndex m_exceptionHandlerCallSiteIndex;
};
// Helper for easily creating a GC-aware JIT stub routine. For the varargs,
@@ -126,7 +126,7 @@
Ref<JITStubRoutine> createJITStubRoutine(
const MacroAssemblerCodeRef<JITStubRoutinePtrTag>&, VM&, const JSCell* owner, bool makesCalls,
const Vector<JSCell*>& = { },
- CodeBlock* codeBlockForExceptionHandlers = nullptr, CallSiteIndex exceptionHandlingCallSiteIndex = CallSiteIndex(std::numeric_limits<unsigned>::max()));
+ CodeBlock* codeBlockForExceptionHandlers = nullptr, DisposableCallSiteIndex exceptionHandlingCallSiteIndex = DisposableCallSiteIndex());
} // namespace JSC
Modified: trunk/Source/_javascript_Core/jit/JITInlineCacheGenerator.h (246504 => 246505)
--- trunk/Source/_javascript_Core/jit/JITInlineCacheGenerator.h 2019-06-17 18:44:18 UTC (rev 246504)
+++ trunk/Source/_javascript_Core/jit/JITInlineCacheGenerator.h 2019-06-17 18:49:03 UTC (rev 246505)
@@ -35,11 +35,10 @@
namespace JSC {
+class CallSiteIndex;
class CodeBlock;
class StructureStubInfo;
-struct CallSiteIndex;
-
enum class AccessType : int8_t;
class JITInlineCacheGenerator {