+2008-12-07 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Cameron Zwarich and Sam Weinig
+
+ <rdar://problem/6309878> Need more granular control over allocation of executable memory (21783)
+ <https://bugs.webkit.org/show_bug.cgi?id=21783>
+
+ Add a new allocator for use by the JIT that provides executable pages, so
+ we can get rid of the current hack that makes the entire heap executable.
+
+ 1-2% progression on SunSpider-v8, 1% on SunSpider. Reduces memory usage as well!
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.vcproj/jsc/jsc.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * assembler/AssemblerBuffer.h:
+ (JSC::AssemblerBuffer::size):
+ (JSC::AssemblerBuffer::executableCopy):
+ * assembler/MacroAssembler.h:
+ (JSC::MacroAssembler::size):
+ (JSC::MacroAssembler::copyCode):
+ * assembler/X86Assembler.h:
+ (JSC::X86Assembler::size):
+ (JSC::X86Assembler::executableCopy):
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::~CodeBlock):
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::executablePool):
+ (JSC::CodeBlock::setExecutablePool):
+ * bytecode/Instruction.h:
+ (JSC::PolymorphicAccessStructureList::derefStructures):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::~Interpreter):
+ * interpreter/Interpreter.h:
+ * jit/ExecutableAllocator.cpp: Added.
+ * jit/ExecutableAllocator.h: Added.
+ (JSC::ExecutablePool::create):
+ (JSC::ExecutablePool::alloc):
+ (JSC::ExecutablePool::~ExecutablePool):
+ (JSC::ExecutablePool::available):
+ (JSC::ExecutablePool::ExecutablePool):
+ (JSC::ExecutablePool::poolAllocate):
+ (JSC::ExecutableAllocator::ExecutableAllocator):
+ (JSC::ExecutableAllocator::poolForSize):
+ (JSC::ExecutablePool::sizeForAllocation):
+ * jit/ExecutableAllocatorMMAP.cpp: Added.
+ (JSC::ExecutableAllocator::intializePageSize):
+ (JSC::ExecutablePool::systemAlloc):
+ (JSC::ExecutablePool::systemRelease):
+ * jit/ExecutableAllocatorWin.cpp: Added.
+ (JSC::ExecutableAllocator::intializePageSize):
+ (JSC::ExecutablePool::systemAlloc):
+ (JSC::ExecutablePool::systemRelease):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompile):
+ (JSC::JIT::privateCompileCTIMachineTrampolines):
+ * jit/JIT.h:
+ (JSC::JIT::compileCTIMachineTrampolines):
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::privateCompilePutByIdTransition):
+ (JSC::JIT::privateCompilePatchGetArrayLength):
+ (JSC::JIT::privateCompileGetByIdSelf):
+ (JSC::JIT::privateCompileGetByIdProto):
+ (JSC::JIT::privateCompileGetByIdSelfList):
+ (JSC::JIT::privateCompileGetByIdProtoList):
+ (JSC::JIT::privateCompileGetByIdChainList):
+ (JSC::JIT::privateCompileGetByIdChain):
+ (JSC::JIT::privateCompilePutByIdReplace):
+ * parser/Nodes.cpp:
+ (JSC::RegExpNode::emitBytecode):
+ * runtime/JSGlobalData.h:
+ (JSC::JSGlobalData::poolForSize):
+ * runtime/RegExp.cpp:
+ (JSC::RegExp::RegExp):
+ (JSC::RegExp::create):
+ (JSC::RegExp::~RegExp):
+ * runtime/RegExp.h:
+ * runtime/RegExpConstructor.cpp:
+ (JSC::constructRegExp):
+ * runtime/RegExpPrototype.cpp:
+ (JSC::regExpProtoFuncCompile):
+ * runtime/StringPrototype.cpp:
+ (JSC::stringProtoFuncMatch):
+ (JSC::stringProtoFuncSearch):
+ * wrec/WREC.cpp:
+ (JSC::WREC::Generator::compileRegExp):
+ * wrec/WRECGenerator.h:
+ * wtf/FastMalloc.cpp:
+ * wtf/FastMalloc.h:
+ * wtf/TCSystemAlloc.cpp:
+ (TryMmap):
+ (TryVirtualAlloc):
+ (TryDevMem):
+ (TCMalloc_SystemRelease):
+
2008-12-06 Sam Weinig <sam@webkit.org>
Fix the Gtk build.
>\r
</File>\r
<File\r
+ RelativePath="..\..\interpreter\CallFrame.cpp"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\interpreter\CallFrame.h"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath="..\..\runtime\ClassInfo.h"\r
>\r
</File>\r
>\r
</File>\r
<File\r
+ RelativePath="..\..\runtime\Completion.cpp"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath="..\..\runtime\Completion.h"\r
>\r
</File>\r
>\r
</File>\r
<File\r
- RelativePath="..\..\interpreter\CallFrame.cpp"\r
- >\r
- </File>\r
- <File\r
- RelativePath="..\..\interpreter\CallFrame.h"\r
- >\r
- </File>\r
- <File\r
RelativePath="..\..\runtime\FunctionConstructor.cpp"\r
>\r
</File>\r
>\r
</File>\r
<File\r
- RelativePath="..\..\runtime\Completion.cpp"\r
- >\r
- </File>\r
- <File\r
RelativePath="..\..\runtime\Interpreter.h"\r
>\r
</File>\r
>\r
</File>\r
<File\r
- RelativePath="..\..\jit\JIT.cpp"\r
- >\r
- <FileConfiguration\r
- Name="Release_PGO|Win32"\r
- >\r
- <Tool\r
- Name="VCCLCompilerTool"\r
- WholeProgramOptimization="false"\r
- />\r
- </FileConfiguration>\r
- </File>\r
- <File\r
- RelativePath="..\..\jit\JITCall.cpp"\r
- >\r
- <FileConfiguration\r
- Name="Release_PGO|Win32"\r
- >\r
- <Tool\r
- Name="VCCLCompilerTool"\r
- WholeProgramOptimization="false"\r
- />\r
- </FileConfiguration>\r
- </File>\r
- <File\r
- RelativePath="..\..\jit\JITPropertyAccess.cpp"\r
- >\r
- <FileConfiguration\r
- Name="Release_PGO|Win32"\r
- >\r
- <Tool\r
- Name="VCCLCompilerTool"\r
- WholeProgramOptimization="false"\r
- />\r
- </FileConfiguration>\r
- </File>\r
- <File\r
- RelativePath="..\..\jit\JITArithmetic.cpp"\r
- >\r
- <FileConfiguration\r
- Name="Release_PGO|Win32"\r
- >\r
- <Tool\r
- Name="VCCLCompilerTool"\r
- WholeProgramOptimization="false"\r
- />\r
- </FileConfiguration>\r
- </File>\r
- <File\r
- RelativePath="..\..\jit\JIT.h"\r
- >\r
- </File>\r
- <File\r
- RelativePath="..\..\jit\JITInlineMethods.h"\r
- >\r
- </File>\r
- <File\r
RelativePath="..\..\bytecode\EvalCodeCache.h"\r
>\r
</File>\r
>\r
</File>\r
<File\r
- RelativePath="..\..\runtime\JSPropertyNameIterator.cpp"\r
+ RelativePath="..\..\interpreter\Interpreter.cpp"\r
>\r
</File>\r
<File\r
- RelativePath="..\..\runtime\JSPropertyNameIterator.h"\r
+ RelativePath="..\..\interpreter\Interpreter.h"\r
>\r
</File>\r
<File\r
- RelativePath="..\..\interpreter\Interpreter.cpp"\r
+ RelativePath="..\..\runtime\JSPropertyNameIterator.cpp"\r
>\r
</File>\r
<File\r
- RelativePath="..\..\interpreter\Interpreter.h"\r
+ RelativePath="..\..\runtime\JSPropertyNameIterator.h"\r
>\r
</File>\r
<File\r
Name="assembler"\r
>\r
<File\r
- RelativePath="..\..\assembler\X86Assembler.h"\r
+ RelativePath="..\..\assembler\AssemblerBuffer.h"\r
>\r
</File>\r
<File\r
- RelativePath="..\..\assembler\AssemblerBuffer.h"\r
+ RelativePath="..\..\assembler\X86Assembler.h"\r
>\r
</File>\r
</Filter>\r
RelativePath="..\..\wrec\CharacterClass.cpp"\r
>\r
</File>\r
-\r
<File\r
- RelativePath="..\..\wrec\WRECParser.h"\r
+ RelativePath="..\..\wrec\CharacterClass.h"\r
>\r
</File>\r
-\r
<File\r
- RelativePath="..\..\wrec\WRECFunctors.cpp"\r
+ RelativePath="..\..\wrec\CharacterClassConstructor.cpp"\r
>\r
</File>\r
-\r
<File\r
- RelativePath="..\..\wrec\WRECGenerator.cpp"\r
+ RelativePath="..\..\wrec\CharacterClassConstructor.h"\r
>\r
</File>\r
-\r
<File\r
- RelativePath="..\..\wrec\CharacterClass.h"\r
+ RelativePath="..\..\wrec\Quantifier.h"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\wrec\WREC.cpp"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\wrec\WREC.h"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\wrec\WRECFunctors.cpp"\r
>\r
</File>\r
-\r
<File\r
RelativePath="..\..\wrec\WRECFunctors.h"\r
>\r
</File>\r
-\r
<File\r
- RelativePath="..\..\wrec\Quantifier.h"\r
+ RelativePath="..\..\wrec\WRECGenerator.cpp"\r
>\r
</File>\r
-\r
<File\r
RelativePath="..\..\wrec\WRECGenerator.h"\r
>\r
</File>\r
-\r
<File\r
RelativePath="..\..\wrec\WRECParser.cpp"\r
>\r
</File>\r
-\r
<File\r
- RelativePath="..\..\wrec\CharacterClassConstructor.cpp"\r
+ RelativePath="..\..\wrec\WRECParser.h"\r
>\r
</File>\r
+ </Filter>\r
+ <Filter\r
+ Name="jit"\r
+ >\r
<File\r
- RelativePath="..\..\wrec\CharacterClassConstructor.h"\r
+ RelativePath="..\..\jit\JIT.cpp"\r
>\r
+ <FileConfiguration\r
+ Name="Release_PGO|Win32"\r
+ >\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ WholeProgramOptimization="false"\r
+ />\r
+ </FileConfiguration>\r
</File>\r
<File\r
- RelativePath="..\..\wrec\WREC.cpp"\r
+ RelativePath="..\..\jit\JIT.h"\r
>\r
</File>\r
<File\r
- RelativePath="..\..\wrec\WREC.h"\r
+ RelativePath="..\..\jit\ExecutableAllocator.cpp"\r
>\r
</File>\r
+ <File\r
+ RelativePath="..\..\jit\ExecutableAllocatorWin.cpp"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\jit\ExecutableAllocator.h"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\jit\JITArithmetic.cpp"\r
+ >\r
+ <FileConfiguration\r
+ Name="Release_PGO|Win32"\r
+ >\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ WholeProgramOptimization="false"\r
+ />\r
+ </FileConfiguration>\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\jit\JITCall.cpp"\r
+ >\r
+ <FileConfiguration\r
+ Name="Release_PGO|Win32"\r
+ >\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ WholeProgramOptimization="false"\r
+ />\r
+ </FileConfiguration>\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\jit\JITInlineMethods.h"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\jit\JITPropertyAccess.cpp"\r
+ >\r
+ <FileConfiguration\r
+ Name="Release_PGO|Win32"\r
+ >\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ WholeProgramOptimization="false"\r
+ />\r
+ </FileConfiguration>\r
+ </File>\r
</Filter>\r
</Files>\r
<Globals>\r
/>\r
<Tool\r
Name="VCCLCompilerTool"\r
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../assembler/;../../wrec/;../../parser/;../../runtime/;../../VM/;../../bytecode/;../../interpreter/;../../wtf/;../../debugger/;../../bytecompiler/;"$(WebKitLibrariesDir)\include\icu";"$(WebKitLibrariesDir)\include\pthreads";../../../icu/include;"$(WebKitLibrariesDir)\include""\r
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../assembler/;../../wrec/;../../parser/;../../runtime/;../../VM/;../../bytecode/;../../interpreter/;../../wtf/;../../debugger/;../../bytecompiler/;"$(WebKitLibrariesDir)\include\icu";"$(WebKitLibrariesDir)\include\pthreads";../../../icu/include;"$(WebKitLibrariesDir)\include";../../jit/"\r
PreprocessorDefinitions="__STD_C"\r
/>\r
<Tool\r
/>\r
<Tool\r
Name="VCCLCompilerTool"\r
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../assembler/;../../wrec/;../../parser/;../../runtime/;../../VM/;../../bytecode/;../../interpreter/;../../wtf/;../../debugger/;../../bytecompiler/;"$(WebKitLibrariesDir)\include\icu";"$(WebKitLibrariesDir)\include\pthreads";../../../icu/include;"$(WebKitLibrariesDir)\include""\r
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../assembler/;../../wrec/;../../parser/;../../runtime/;../../VM/;../../bytecode/;../../interpreter/;../../wtf/;../../debugger/;../../bytecompiler/;"$(WebKitLibrariesDir)\include\icu";"$(WebKitLibrariesDir)\include\pthreads";../../../icu/include;"$(WebKitLibrariesDir)\include";../../jit/"\r
PreprocessorDefinitions="__STD_C"\r
/>\r
<Tool\r
/>\r
<Tool\r
Name="VCCLCompilerTool"\r
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../assembler/;../../wrec/;../../parser/;../../runtime/;../../VM/;../../bytecode/;../../interpreter/;../../wtf/;../../debugger/;../../bytecompiler/;"$(WebKitLibrariesDir)\include\icu";"$(WebKitLibrariesDir)\include\pthreads";../../../icu/include;"$(WebKitLibrariesDir)\include""\r
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../assembler/;../../wrec/;../../parser/;../../runtime/;../../VM/;../../bytecode/;../../interpreter/;../../wtf/;../../debugger/;../../bytecompiler/;"$(WebKitLibrariesDir)\include\icu";"$(WebKitLibrariesDir)\include\pthreads";../../../icu/include;"$(WebKitLibrariesDir)\include";../../jit/"\r
PreprocessorDefinitions="__STD_C"\r
/>\r
<Tool\r
A72700900DAC6BBC00E548D7 /* JSNotAnObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A72700780DAC605600E548D7 /* JSNotAnObject.cpp */; };
A72701B90DADE94900E548D7 /* ExceptionHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = A72701B30DADE94900E548D7 /* ExceptionHelpers.h */; };
A727FF6B0DA3092200E548D7 /* JSPropertyNameIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */; };
+ A766B44F0EE8DCD1009518CA /* ExecutableAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ A782F16E0EEC8FB20036273F /* ExecutableAllocatorMMAP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A782F16D0EEC8FB20036273F /* ExecutableAllocatorMMAP.cpp */; };
+ A7B48F490EE8936F00DCBDB6 /* ExecutableAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */; };
BC02E90D0E1839DB000F9297 /* ErrorConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9050E1839DB000F9297 /* ErrorConstructor.h */; };
BC02E90F0E1839DB000F9297 /* ErrorPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9070E1839DB000F9297 /* ErrorPrototype.h */; };
BC02E9110E1839DB000F9297 /* NativeErrorConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9090E1839DB000F9297 /* NativeErrorConstructor.h */; };
A72701B30DADE94900E548D7 /* ExceptionHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExceptionHelpers.h; sourceTree = "<group>"; };
A727FF650DA3053B00E548D7 /* JSPropertyNameIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPropertyNameIterator.h; sourceTree = "<group>"; };
A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPropertyNameIterator.cpp; sourceTree = "<group>"; };
+ A782F16D0EEC8FB20036273F /* ExecutableAllocatorMMAP.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocatorMMAP.cpp; sourceTree = "<group>"; };
+ A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutableAllocator.h; sourceTree = "<group>"; };
+ A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocator.cpp; sourceTree = "<group>"; };
A7E42C180E3938830065A544 /* JSStaticScopeObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStaticScopeObject.h; sourceTree = "<group>"; };
A7E42C190E3938830065A544 /* JSStaticScopeObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStaticScopeObject.cpp; sourceTree = "<group>"; };
A8E894310CD0602400367179 /* JSCallbackObjectFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCallbackObjectFunctions.h; sourceTree = "<group>"; };
86CC85A00EE79A4700288682 /* JITInlineMethods.h */,
1429D92D0ED22D7000B89619 /* JIT.cpp */,
1429D92E0ED22D7000B89619 /* JIT.h */,
+ A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */,
+ A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */,
+ A782F16D0EEC8FB20036273F /* ExecutableAllocatorMMAP.cpp */,
);
path = jit;
sourceTree = "<group>";
86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */,
86CC85A10EE79A4700288682 /* JITInlineMethods.h in Headers */,
BCFD8C930EEB2EE700283848 /* JumpTable.h in Headers */,
+ A766B44F0EE8DCD1009518CA /* ExecutableAllocator.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
86CC85C40EE7A89400288682 /* JITPropertyAccess.cpp in Sources */,
86A90ED00EE7D51F00AB350D /* JITArithmetic.cpp in Sources */,
BCFD8C920EEB2EE700283848 /* JumpTable.cpp in Sources */,
+ A7B48F490EE8936F00DCBDB6 /* ExecutableAllocator.cpp in Sources */,
+ A782F16E0EEC8FB20036273F /* ExecutableAllocatorMMAP.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
#if ENABLE(ASSEMBLER)
#include <string.h>
+#include <jit/ExecutableAllocator.h>
#include <wtf/Assertions.h>
#include <wtf/FastMalloc.h>
return m_buffer;
}
- int size()
+ int size() const
{
return m_size;
}
- void* executableCopy()
+ void* executableCopy(ExecutablePool* allocator)
{
if (!m_size)
return 0;
- void* result = WTF::fastMallocExecutable(m_size);
+ void* result = allocator->alloc(m_size);
if (!result)
return 0;
{
}
- void* copyCode()
+ size_t size() { return m_assembler.size(); }
+ void* copyCode(ExecutablePool* allocator)
{
- return m_assembler.executableCopy();
+ return m_assembler.executableCopy(allocator);
}
// Address:
{
}
+ size_t size() const { return m_buffer.size(); }
+
void int3()
{
m_buffer.putByte(OP_INT3);
reinterpret_cast<intptr_t*>(where)[-1] = (reinterpret_cast<intptr_t>(destination) - where);
}
- void* executableCopy()
+ void* executableCopy(ExecutablePool* allocator)
{
- void* copy = m_buffer.executableCopy();
+ void* copy = m_buffer.executableCopy(allocator);
ASSERT(copy);
return copy;
}
for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) {
derefStructures(&m_instructions[m_propertyAccessInstructions[i].bytecodeIndex]);
- if (m_propertyAccessInstructions[i].stubRoutine)
- WTF::fastFreeExecutable(m_propertyAccessInstructions[i].stubRoutine);
}
for (size_t size = m_callLinkInfos.size(), i = 0; i < size; ++i) {
#if ENABLE(JIT)
unlinkCallers();
-
- if (m_jitCode)
- WTF::fastFreeExecutable(m_jitCode);
#endif
}
#if ENABLE(JIT)
void setJITCode(void* jitCode) { m_jitCode = jitCode; }
void* jitCode() { return m_jitCode; }
+ ExecutablePool* executablePool() { return m_executablePool.get(); }
+ void setExecutablePool(ExecutablePool* pool) { m_executablePool = pool; }
#endif
ScopeNode* ownerNode() const { return m_ownerNode; }
Vector<Instruction> m_instructions;
#if ENABLE(JIT)
void* m_jitCode;
+ RefPtr<ExecutablePool> m_executablePool;
#endif
int m_thisRegister;
else
info.u.proto->deref();
}
-
- if (info.stubRoutine)
- WTF::fastFreeExecutable(info.stubRoutine);
}
}
};
Interpreter::~Interpreter()
{
-#if ENABLE(JIT)
- JIT::freeCTIMachineTrampolines(this);
-#endif
}
#ifndef NDEBUG
SamplingTool* m_sampler;
#if ENABLE(JIT)
+ RefPtr<ExecutablePool> m_executablePool;
void* m_ctiArrayLengthTrampoline;
void* m_ctiStringLengthTrampoline;
void* m_ctiVirtualCallPreLink;
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "ExecutableAllocator.h"
+
+#if ENABLE(ASSEMBLER)
+
+namespace JSC {
+
+size_t ExecutableAllocator::pageSize = 0;
+
+}
+
+#endif // HAVE(ASSEMBLER)
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ExecutableAllocator_h
+#define ExecutableAllocator_h
+
+#if ENABLE(ASSEMBLER)
+
+#include <wtf/Assertions.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+#include <limits>
+
+#define JIT_ALLOCATOR_PAGE_MASK (ExecutableAllocator::pageSize - 1)
+#define JIT_ALLOCATOR_LARGE_ALLOC_SIZE (ExecutableAllocator::pageSize * 4)
+
+namespace JSC {
+
+class ExecutablePool : public RefCounted<ExecutablePool> {
+private:
+ struct Allocation {
+ char* pages;
+ size_t size;
+ };
+ typedef Vector<Allocation, 2> AllocationList;
+
+public:
+ static PassRefPtr<ExecutablePool> create(size_t n)
+ {
+ return adoptRef(new ExecutablePool(n));
+ }
+
+ void* alloc(size_t n)
+ {
+ if (n < static_cast<size_t>(m_end - m_freePtr)) {
+ char* result = m_freePtr;
+ // ensure m_freePtr is word aligned.
+ m_freePtr += n + (sizeof(void*) - n & (sizeof(void*) - 1));
+ return result;
+ }
+
+ // Insufficient space to allocate in the existing pool
+ // so we need allocate into a new pool
+ return poolAllocate(n);
+ }
+
+ ~ExecutablePool()
+ {
+ AllocationList::const_iterator end = m_pools.end();
+ for (AllocationList::const_iterator ptr = m_pools.begin(); ptr != end; ++ptr)
+ ExecutablePool::systemRelease(*ptr);
+ }
+
+ size_t available() const { return (m_pools.size() > 1) ? 0 : m_end - m_freePtr; }
+
+private:
+ static Allocation systemAlloc(size_t n);
+ static void systemRelease(const Allocation& alloc);
+
+ ExecutablePool(size_t n)
+ {
+ size_t allocSize = sizeForAllocation(n);
+ Allocation mem = systemAlloc(allocSize);
+ m_pools.append(mem);
+ m_freePtr = mem.pages;
+ if (!m_freePtr)
+ CRASH(); // Failed to allocate
+ m_end = m_freePtr + allocSize;
+ }
+
+ static inline size_t sizeForAllocation(size_t request);
+
+ void* poolAllocate(size_t n)
+ {
+ size_t allocSize = sizeForAllocation(n);
+
+ Allocation result = systemAlloc(allocSize);
+ if (!result.pages)
+ CRASH(); // Failed to allocate
+
+ ASSERT(m_end >= m_freePtr);
+ if ((allocSize - n) > static_cast<size_t>(m_end - m_freePtr)) {
+ // Replace allocation pool
+ m_freePtr = result.pages + n;
+ m_end = result.pages + allocSize;
+ }
+
+ m_pools.append(result);
+ return result.pages;
+ }
+
+ char* m_freePtr;
+ char* m_end;
+ AllocationList m_pools;
+};
+
+class ExecutableAllocator {
+public:
+ static size_t pageSize;
+ ExecutableAllocator()
+ {
+ if (!pageSize)
+ intializePageSize();
+ m_smallAllocationPool = ExecutablePool::create(JIT_ALLOCATOR_LARGE_ALLOC_SIZE);
+ }
+
+ PassRefPtr<ExecutablePool> poolForSize(size_t n)
+ {
+ // Try to fit in the existing small allocator
+ if (n < m_smallAllocationPool->available())
+ return m_smallAllocationPool;
+
+ // If the request is large, we just provide a unshared allocator
+ if (n > JIT_ALLOCATOR_LARGE_ALLOC_SIZE)
+ return ExecutablePool::create(n);
+
+ // Create a new allocator
+ RefPtr<ExecutablePool> pool = ExecutablePool::create(JIT_ALLOCATOR_LARGE_ALLOC_SIZE);
+
+ // If the new allocator will result in more free space than in
+ // the current small allocator, then we will use it instead
+ if ((pool->available() - n) > m_smallAllocationPool->available())
+ m_smallAllocationPool = pool;
+ return pool.release();
+ }
+
+private:
+ RefPtr<ExecutablePool> m_smallAllocationPool;
+ static void intializePageSize();
+};
+
+inline size_t ExecutablePool::sizeForAllocation(size_t request)
+{
+ if ((std::numeric_limits<size_t>::max() - ExecutableAllocator::pageSize) <= request)
+ CRASH(); // Allocation is too large
+
+ // Round up to next page boundary
+ size_t size = request + JIT_ALLOCATOR_PAGE_MASK;
+ size = size & ~JIT_ALLOCATOR_PAGE_MASK;
+ ASSERT(size >= request);
+ return size;
+}
+
+}
+
+#endif // ENABLE(ASSEMBLER)
+
+#endif // !defined(ExecutableAllocator)
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "ExecutableAllocator.h"
+
+#if ENABLE(ASSEMBLER)
+
+#include <sys/mman.h>
+
+namespace JSC {
+
+void ExecutableAllocator::intializePageSize()
+{
+ ExecutableAllocator::pageSize = getpagesize();
+}
+
+ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t n)
+{
+ ExecutablePool::Allocation alloc = {reinterpret_cast<char*>(mmap(NULL, n, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0)), n};
+ return alloc;
+}
+
+void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc)
+{
+ if (munmap(alloc.pages, alloc.size))
+ ASSERT_NOT_REACHED();
+}
+
+}
+
+#endif // HAVE(ASSEMBLER)
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "ExecutableAllocator.h"
+
+#if ENABLE(ASSEMBLER)
+
+#include "windows.h"
+
+namespace JSC {
+
+void ExecutableAllocator::intializePageSize()
+{
+ SYSTEM_INFO system_info;
+ GetSystemInfo(&system_info);
+ ExecutableAllocator::pageSize = system_info.dwPageSize;
+}
+
+ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t n)
+{
+ ExecutablePool::Allocation alloc = {reinterpret_cast<char*>(VirtualAlloc(0, n, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)), n};
+ return alloc;
+}
+
+void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc)
+{
+ VirtualFree(alloc.pages, 0, MEM_RELEASE);
+}
+
+}
+
+#endif // HAVE(ASSEMBLER)
ASSERT(m_jmpTable.isEmpty());
- void* code = __ executableCopy();
+ RefPtr<ExecutablePool> allocator = m_globalData->poolForSize(__ size());
+ m_codeBlock->setExecutablePool(allocator.get());
+ void* code = __ executableCopy(allocator.get());
// Translate vPC offsets into addresses in JIT generated code, for switch tables.
for (unsigned i = 0; i < m_switches.size(); ++i) {
__ jmp_r(X86::eax);
// All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
-
- void* code = __ executableCopy();
+ m_interpreter->m_executablePool = m_globalData->poolForSize(__ size());
+ void* code = __ executableCopy(m_interpreter->m_executablePool.get());
X86Assembler::link(code, array_failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail));
X86Assembler::link(code, array_failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail));
m_interpreter->m_ctiVirtualCall = X86Assembler::getRelocatedAddress(code, virtualCallBegin);
}
-void JIT::freeCTIMachineTrampolines(Interpreter* interpreter)
-{
- WTF::fastFreeExecutable(interpreter->m_ctiArrayLengthTrampoline);
-}
-
void JIT::emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst)
{
__ movl_mr(FIELD_OFFSET(JSVariableObject, d), variableObject, dst);
JIT jit(globalData);
jit.privateCompileCTIMachineTrampolines();
}
- static void freeCTIMachineTrampolines(Interpreter*);
static void patchGetByIdSelf(CodeBlock* codeBlock, Structure* structure, size_t cachedOffset, void* returnAddress);
static void patchPutByIdReplace(CodeBlock* codeBlock, Structure* structure, size_t cachedOffset, void* returnAddress);
failureJump = __ jmp();
}
- void* code = __ executableCopy();
+ void* code = __ executableCopy(m_codeBlock->executablePool());
if (failureCases.size())
X86Assembler::link(code, failureJump, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_fail));
__ movl_rr(X86::ecx, X86::eax);
JmpSrc success = __ jmp();
- void* code = __ executableCopy();
+ void* code = __ executableCopy(m_codeBlock->executablePool());
// Use the repatch information to link the failure cases back to the original slow case routine.
void* slowCaseBegin = reinterpret_cast<char*>(info.callReturnLocation) - repatchOffsetGetByIdSlowCaseCall;
__ movl_mr(cachedOffset * sizeof(JSValue*), X86::eax, X86::eax);
__ ret();
- void* code = __ executableCopy();
+ void* code = __ executableCopy(m_codeBlock->executablePool());
X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_self_fail));
X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_self_fail));
JmpSrc success = __ jmp();
- void* code = __ executableCopy();
+ void* code = __ executableCopy(m_codeBlock->executablePool());
// Use the repatch information to link the failure cases back to the original slow case routine.
void* slowCaseBegin = reinterpret_cast<char*>(info.callReturnLocation) - repatchOffsetGetByIdSlowCaseCall;
__ ret();
- void* code = __ executableCopy();
+ void* code = __ executableCopy(m_codeBlock->executablePool());
X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail));
X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail));
__ movl_mr(cachedOffset * sizeof(JSValue*), X86::eax, X86::eax);
JmpSrc success = __ jmp();
- void* code = __ executableCopy();
+ void* code = __ executableCopy(m_codeBlock->executablePool());
ASSERT(code);
// Use the repatch information to link the failure cases back to the original slow case routine.
JmpSrc success = __ jmp();
- void* code = __ executableCopy();
+ void* code = __ executableCopy(m_codeBlock->executablePool());
// Use the repatch information to link the failure cases back to the original slow case routine.
void* lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine;
__ movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::eax);
JmpSrc success = __ jmp();
- void* code = __ executableCopy();
+ void* code = __ executableCopy(m_codeBlock->executablePool());
// Use the repatch information to link the failure cases back to the original slow case routine.
void* lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine;
__ movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::eax);
JmpSrc success = __ jmp();
- void* code = __ executableCopy();
+ void* code = __ executableCopy(m_codeBlock->executablePool());
// Use the repatch information to link the failure cases back to the original slow case routine.
void* slowCaseBegin = reinterpret_cast<char*>(info.callReturnLocation) - repatchOffsetGetByIdSlowCaseCall;
__ movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::eax);
__ ret();
- void* code = __ executableCopy();
+ void* code = __ executableCopy(m_codeBlock->executablePool());
for (unsigned i = 0; i < bucketsOfFail.size(); ++i)
X86Assembler::link(code, bucketsOfFail[i], reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail));
__ movl_rm(X86::edx, cachedOffset * sizeof(JSValue*), X86::eax);
__ ret();
- void* code = __ executableCopy();
+ void* code = __ executableCopy(m_codeBlock->executablePool());
X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_fail));
X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_fail));
RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- RefPtr<RegExp> regExp = RegExp::create(m_pattern, m_flags);
+ RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern, m_flags);
if (!regExp->isValid())
return emitThrowError(generator, SyntaxError, ("Invalid regular expression: " + UString(regExp->errorMessage())).UTF8String().c_str());
if (dst == generator.ignoredResult())
#include <wtf/HashMap.h>
#include <wtf/RefCounted.h>
#include "Collector.h"
+#include "ExecutableAllocator.h"
#include "SmallStrings.h"
struct OpaqueJSClass;
Heap heap;
+ PassRefPtr<ExecutablePool> poolForSize(size_t n) { return m_executableAllocator.poolForSize(n); }
private:
JSGlobalData(bool isShared = false);
+ ExecutableAllocator m_executableAllocator;
static JSGlobalData*& sharedInstanceInternal();
};
using namespace WREC;
#endif
-inline RegExp::RegExp(const UString& pattern)
+inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern)
: m_pattern(pattern)
, m_flagBits(0)
, m_regExp(0)
, m_numSubpatterns(0)
{
#if ENABLE(WREC)
- m_wrecFunction = Generator::compileRegExp(pattern, &m_numSubpatterns, &m_constructionError);
+ m_wrecFunction = Generator::compileRegExp(globalData, pattern, &m_numSubpatterns, &m_constructionError, m_executablePool);
if (m_wrecFunction)
return;
// Fall through to non-WREC case.
JSRegExpDoNotIgnoreCase, JSRegExpSingleLine, &m_numSubpatterns, &m_constructionError);
}
-PassRefPtr<RegExp> RegExp::create(const UString& pattern)
+PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern)
{
- return adoptRef(new RegExp(pattern));
+ return adoptRef(new RegExp(globalData, pattern));
}
-inline RegExp::RegExp(const UString& pattern, const UString& flags)
+inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags)
: m_pattern(pattern)
, m_flags(flags)
, m_flagBits(0)
}
#if ENABLE(WREC)
- m_wrecFunction = Generator::compileRegExp(pattern, &m_numSubpatterns, &m_constructionError, (m_flagBits & IgnoreCase), (m_flagBits & Multiline));
+ m_wrecFunction = Generator::compileRegExp(globalData, pattern, &m_numSubpatterns, &m_constructionError, m_executablePool, (m_flagBits & IgnoreCase), (m_flagBits & Multiline));
if (m_wrecFunction)
return;
// Fall through to non-WREC case.
ignoreCaseOption, multilineOption, &m_numSubpatterns, &m_constructionError);
}
-PassRefPtr<RegExp> RegExp::create(const UString& pattern, const UString& flags)
+PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern, const UString& flags)
{
- return adoptRef(new RegExp(pattern, flags));
+ return adoptRef(new RegExp(globalData, pattern, flags));
}
RegExp::~RegExp()
{
jsRegExpFree(m_regExp);
-#if ENABLE(WREC)
- if (m_wrecFunction)
- WTF::fastFreeExecutable(reinterpret_cast<void*>(m_wrecFunction));
-#endif
}
int RegExp::match(const UString& s, int startOffset, OwnArrayPtr<int>* ovector)
#include "UString.h"
#include "WREC.h"
+#include "ExecutableAllocator.h"
#include <wtf/Forward.h>
#include <wtf/RefCounted.h>
class RegExp : public RefCounted<RegExp> {
public:
- static PassRefPtr<RegExp> create(const UString& pattern);
- static PassRefPtr<RegExp> create(const UString& pattern, const UString& flags);
+ static PassRefPtr<RegExp> create(JSGlobalData* globalData, const UString& pattern);
+ static PassRefPtr<RegExp> create(JSGlobalData* globalData, const UString& pattern, const UString& flags);
~RegExp();
bool global() const { return m_flagBits & Global; }
unsigned numSubpatterns() const { return m_numSubpatterns; }
private:
- RegExp(const UString& pattern);
- RegExp(const UString& pattern, const UString& flags);
+ RegExp(JSGlobalData* globalData, const UString& pattern);
+ RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags);
void compile();
#if ENABLE(WREC)
WREC::CompiledRegExp m_wrecFunction;
+ RefPtr<ExecutablePool> m_executablePool;
#endif
};
UString pattern = arg0->isUndefined() ? UString("") : arg0->toString(exec);
UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec);
- RefPtr<RegExp> regExp = RegExp::create(pattern, flags);
+ RefPtr<RegExp> regExp = RegExp::create(&exec->globalData(), pattern, flags);
if (!regExp->isValid())
return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));
return new (exec) RegExpObject(exec->lexicalGlobalObject()->regExpStructure(), regExp.release());
} else {
UString pattern = args.isEmpty() ? UString("") : arg0->toString(exec);
UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec);
- regExp = RegExp::create(pattern, flags);
+ regExp = RegExp::create(&exec->globalData(), pattern, flags);
}
if (!regExp->isValid())
* If regexp is not an object whose [[Class]] property is "RegExp", it is
* replaced with the result of the expression new RegExp(regexp).
*/
- reg = RegExp::create(a0->toString(exec));
+ reg = RegExp::create(&exec->globalData(), a0->toString(exec));
}
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
int pos;
* If regexp is not an object whose [[Class]] property is "RegExp", it is
* replaced with the result of the expression new RegExp(regexp).
*/
- reg = RegExp::create(a0->toString(exec));
+ reg = RegExp::create(&exec->globalData(), a0->toString(exec));
}
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
int pos;
#include "CharacterClassConstructor.h"
#include "Interpreter.h"
+#include "JSGlobalObject.h"
+#include "RegisterFile.h"
#include "WRECFunctors.h"
#include "WRECParser.h"
#include "pcre_internal.h"
// This limit comes from the limit set in PCRE
static const int MaxPatternSize = (1 << 16);
-CompiledRegExp Generator::compileRegExp(const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, bool ignoreCase, bool multiline)
+CompiledRegExp Generator::compileRegExp(JSGlobalData* globalData, const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, RefPtr<ExecutablePool>& pool, bool ignoreCase, bool multiline)
{
if (pattern.size() > MaxPatternSize) {
*error_ptr = "Regular expression too large.";
}
*numSubpatterns_ptr = parser.numSubpatterns();
- return reinterpret_cast<CompiledRegExp>(generator.copyCode());
+ pool = globalData->poolForSize(generator.size());
+ return reinterpret_cast<CompiledRegExp>(generator.copyCode(pool.get()));
}
} } // namespace JSC::WREC
#include <wtf/unicode/Unicode.h>
#include "WREC.h"
-namespace JSC { namespace WREC {
+namespace JSC {
+
+ class JSGlobalData;
+
+ namespace WREC {
class CharacterRange;
class GenerateAtomFunctor;
enum ParenthesesType { Capturing, NonCapturing, Assertion, InvertedAssertion, Error };
- static CompiledRegExp compileRegExp(const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, bool ignoreCase = false, bool multiline = false);
-
+ static CompiledRegExp compileRegExp(JSGlobalData*, const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, RefPtr<ExecutablePool>& pool, bool ignoreCase = false, bool multiline = false);
+
Generator(Parser& parser)
: m_parser(parser)
{
return statistics;
}
-#if HAVE(VIRTUALALLOC)
-void* fastMallocExecutable(size_t n)
-{
- return VirtualAlloc(0, n, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
-}
-
-void fastFreeExecutable(void* p)
-{
- VirtualFree(p, 0, MEM_RELEASE);
-}
-#else
-void* fastMallocExecutable(size_t n)
-{
- return fastMalloc(n);
-}
-
-void fastFreeExecutable(void* p)
-{
- fastFree(p);
-}
-#endif
-
} // namespace WTF
#if PLATFORM(DARWIN)
}
}
-void* fastMallocExecutable(size_t n)
-{
- return malloc<false>(n);
-}
-
-void fastFreeExecutable(void* p)
-{
- free(p);
-}
-
#ifdef WTF_CHANGES
#undef do_malloc
#else
void fastFree(void* p);
- void* fastMallocExecutable(size_t n);
- void fastFreeExecutable(void* p);
-
#ifndef NDEBUG
void fastMallocForbid();
void fastMallocAllow();
#include "TCSpinLock.h"
#include "UnusedParam.h"
-#if HAVE(MMAP)
-static const int cProtFlags = PROT_READ | PROT_WRITE
-#if ENABLE(ASSEMBLER) && (PLATFORM(GTK) || (PLATFORM(MAC) && PLATFORM(X86_64)) || PLATFORM(QT))
- | PROT_EXEC
-#endif
- ;
-#endif
-
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
extra = alignment - pagesize;
}
void* result = mmap(NULL, size + extra,
- cProtFlags,
+ PROT_READ | PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS,
-1, 0);
if (result == reinterpret_cast<void*>(MAP_FAILED)) {
}
void* result = VirtualAlloc(NULL, size + extra,
MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN,
- PAGE_EXECUTE_READWRITE);
+ PAGE_READWRITE);
if (result == NULL) {
VirtualAlloc_failure = true;
devmem_failure = true;
return NULL;
}
- void *result = mmap(0, size + extra, cProtFlags,
+ void *result = mmap(0, size + extra, PROT_READ | PROT_WRITE,
MAP_SHARED, physmem_fd, physmem_base);
if (result == reinterpret_cast<void*>(MAP_FAILED)) {
devmem_failure = true;
#endif
#if HAVE(MMAP)
- void *newAddress = mmap(start, length, cProtFlags, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
+ void *newAddress = mmap(start, length, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
UNUSED_PARAM(newAddress);
// If the mmap failed then that's ok, we just won't return the memory to the system.
ASSERT(newAddress == start || newAddress == reinterpret_cast<void*>(MAP_FAILED));