summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-02-03 09:55:33 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2012-02-03 09:55:33 +0100
commitcd44dc59cdfc39534aef4d417e9f3c412e3be139 (patch)
tree8d89889ba95ed6ec9322e733846cc9cce9d7dff1 /Source/JavaScriptCore
parentd11f84f5b5cdc0d92a08af01b13472fdd5f9acb9 (diff)
downloadqtwebkit-cd44dc59cdfc39534aef4d417e9f3c412e3be139.tar.gz
Imported WebKit commit fce473cb4d55aa9fe9d0b0322a2fffecb731b961 (http://svn.webkit.org/repository/webkit/trunk@106560)
Diffstat (limited to 'Source/JavaScriptCore')
-rw-r--r--Source/JavaScriptCore/API/JSObjectRef.cpp2
-rw-r--r--Source/JavaScriptCore/API/JSValueRef.cpp2
-rw-r--r--Source/JavaScriptCore/API/OpaqueJSString.h2
-rw-r--r--Source/JavaScriptCore/CMakeLists.txt11
-rw-r--r--Source/JavaScriptCore/ChangeLog3308
-rw-r--r--Source/JavaScriptCore/Configurations/Base.xcconfig11
-rw-r--r--Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig4
-rw-r--r--Source/JavaScriptCore/Configurations/JavaScriptCore.xcconfig5
-rw-r--r--Source/JavaScriptCore/Configurations/Version.xcconfig2
-rw-r--r--Source/JavaScriptCore/GNUmakefile.am1
-rw-r--r--Source/JavaScriptCore/GNUmakefile.list.am33
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.exp28
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp45
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.gypi9
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.order3
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.pri1
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.pro20
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def22
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj84
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops2
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj12
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj134
-rw-r--r--Source/JavaScriptCore/Target.pri9
-rw-r--r--Source/JavaScriptCore/assembler/ARMAssembler.cpp4
-rw-r--r--Source/JavaScriptCore/assembler/ARMAssembler.h2
-rw-r--r--Source/JavaScriptCore/assembler/ARMv7Assembler.h5
-rw-r--r--Source/JavaScriptCore/assembler/AssemblerBuffer.h4
-rw-r--r--Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h4
-rw-r--r--Source/JavaScriptCore/assembler/LinkBuffer.h21
-rw-r--r--Source/JavaScriptCore/assembler/MIPSAssembler.h4
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h6
-rw-r--r--Source/JavaScriptCore/assembler/SH4Assembler.h4
-rw-r--r--Source/JavaScriptCore/assembler/X86Assembler.h8
-rw-r--r--Source/JavaScriptCore/bytecode/CallLinkInfo.h2
-rw-r--r--Source/JavaScriptCore/bytecode/CallLinkStatus.cpp47
-rw-r--r--Source/JavaScriptCore/bytecode/CallLinkStatus.h66
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.cpp76
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.h79
-rw-r--r--Source/JavaScriptCore/bytecode/CodeOrigin.h24
-rw-r--r--Source/JavaScriptCore/bytecode/GetByIdStatus.cpp138
-rw-r--r--Source/JavaScriptCore/bytecode/GetByIdStatus.h82
-rw-r--r--Source/JavaScriptCore/bytecode/Instruction.h8
-rw-r--r--Source/JavaScriptCore/bytecode/MethodCallLinkStatus.cpp61
-rw-r--r--Source/JavaScriptCore/bytecode/MethodCallLinkStatus.h87
-rw-r--r--Source/JavaScriptCore/bytecode/Opcode.h53
-rw-r--r--Source/JavaScriptCore/bytecode/PredictedType.cpp7
-rw-r--r--Source/JavaScriptCore/bytecode/PredictedType.h61
-rw-r--r--Source/JavaScriptCore/bytecode/PutByIdStatus.cpp89
-rw-r--r--Source/JavaScriptCore/bytecode/PutByIdStatus.h106
-rw-r--r--Source/JavaScriptCore/bytecode/SamplingTool.h14
-rw-r--r--Source/JavaScriptCore/bytecode/StructureSet.h (renamed from Source/JavaScriptCore/dfg/DFGStructureSet.h)20
-rw-r--r--Source/JavaScriptCore/bytecode/StructureStubInfo.h3
-rw-r--r--Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp556
-rw-r--r--Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h182
-rw-r--r--Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp236
-rw-r--r--Source/JavaScriptCore/config.h3
-rw-r--r--Source/JavaScriptCore/debugger/Debugger.h2
-rw-r--r--Source/JavaScriptCore/debugger/DebuggerActivation.cpp4
-rw-r--r--Source/JavaScriptCore/debugger/DebuggerActivation.h8
-rw-r--r--Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp5
-rw-r--r--Source/JavaScriptCore/debugger/DebuggerCallFrame.h2
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.cpp44
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractValue.h2
-rw-r--r--Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h10
-rw-r--r--Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp329
-rw-r--r--Source/JavaScriptCore/dfg/DFGCCallHelpers.h548
-rw-r--r--Source/JavaScriptCore/dfg/DFGDriver.cpp17
-rw-r--r--Source/JavaScriptCore/dfg/DFGDriver.h10
-rw-r--r--Source/JavaScriptCore/dfg/DFGGraph.cpp6
-rw-r--r--Source/JavaScriptCore/dfg/DFGGraph.h64
-rw-r--r--Source/JavaScriptCore/dfg/DFGJITCompiler.cpp9
-rw-r--r--Source/JavaScriptCore/dfg/DFGJITCompiler.h100
-rw-r--r--Source/JavaScriptCore/dfg/DFGNode.h9
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSREntry.cpp8
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp2
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp4
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp4
-rw-r--r--Source/JavaScriptCore/dfg/DFGOperations.cpp233
-rw-r--r--Source/JavaScriptCore/dfg/DFGOperations.h4
-rw-r--r--Source/JavaScriptCore/dfg/DFGPropagator.cpp63
-rw-r--r--Source/JavaScriptCore/dfg/DFGRepatch.cpp120
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp222
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h633
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp242
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp237
-rw-r--r--Source/JavaScriptCore/dfg/DFGThunks.cpp2
-rw-r--r--Source/JavaScriptCore/heap/AllocationSpace.cpp202
-rw-r--r--Source/JavaScriptCore/heap/AllocationSpace.h132
-rw-r--r--Source/JavaScriptCore/heap/BumpBlock.h53
-rw-r--r--Source/JavaScriptCore/heap/BumpSpace.cpp49
-rw-r--r--Source/JavaScriptCore/heap/BumpSpace.h125
-rw-r--r--Source/JavaScriptCore/heap/BumpSpaceInlineMethods.h400
-rw-r--r--Source/JavaScriptCore/heap/ConservativeRoots.cpp18
-rw-r--r--Source/JavaScriptCore/heap/ConservativeRoots.h3
-rw-r--r--Source/JavaScriptCore/heap/HandleHeap.h6
-rw-r--r--Source/JavaScriptCore/heap/Heap.cpp28
-rw-r--r--Source/JavaScriptCore/heap/Heap.h85
-rw-r--r--Source/JavaScriptCore/heap/HeapBlock.h54
-rw-r--r--Source/JavaScriptCore/heap/MachineStackMarker.cpp4
-rw-r--r--Source/JavaScriptCore/heap/MachineStackMarker.h2
-rw-r--r--Source/JavaScriptCore/heap/MarkStack.cpp94
-rw-r--r--Source/JavaScriptCore/heap/MarkStack.h8
-rw-r--r--Source/JavaScriptCore/heap/MarkedBlock.cpp11
-rw-r--r--Source/JavaScriptCore/heap/MarkedBlock.h13
-rw-r--r--Source/JavaScriptCore/heap/MarkedSpace.cpp189
-rw-r--r--Source/JavaScriptCore/heap/MarkedSpace.h81
-rw-r--r--Source/JavaScriptCore/heap/SlotVisitor.h11
-rw-r--r--Source/JavaScriptCore/heap/TinyBloomFilter.h6
-rw-r--r--Source/JavaScriptCore/heap/VTableSpectrum.h2
-rw-r--r--Source/JavaScriptCore/heap/WriteBarrierSupport.h4
-rw-r--r--Source/JavaScriptCore/interpreter/AbstractPC.cpp55
-rw-r--r--Source/JavaScriptCore/interpreter/AbstractPC.h91
-rw-r--r--Source/JavaScriptCore/interpreter/CallFrame.cpp100
-rw-r--r--Source/JavaScriptCore/interpreter/CallFrame.h23
-rw-r--r--Source/JavaScriptCore/interpreter/Interpreter.cpp93
-rw-r--r--Source/JavaScriptCore/interpreter/Interpreter.h16
-rw-r--r--Source/JavaScriptCore/jit/ExecutableAllocator.cpp6
-rw-r--r--Source/JavaScriptCore/jit/ExecutableAllocator.h3
-rw-r--r--Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp9
-rw-r--r--Source/JavaScriptCore/jit/JIT.cpp7
-rw-r--r--Source/JavaScriptCore/jit/JIT.h10
-rw-r--r--Source/JavaScriptCore/jit/JITCall.cpp4
-rw-r--r--Source/JavaScriptCore/jit/JITCall32_64.cpp2
-rw-r--r--Source/JavaScriptCore/jit/JITDriver.h101
-rw-r--r--Source/JavaScriptCore/jit/JITInlineMethods.h18
-rw-r--r--Source/JavaScriptCore/jit/JITOpcodes.cpp18
-rw-r--r--Source/JavaScriptCore/jit/JITOpcodes32_64.cpp18
-rw-r--r--Source/JavaScriptCore/jit/JITPropertyAccess.cpp48
-rw-r--r--Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp57
-rw-r--r--Source/JavaScriptCore/jit/JITStubCall.h8
-rw-r--r--Source/JavaScriptCore/jit/JITStubs.cpp86
-rw-r--r--Source/JavaScriptCore/jit/JITStubs.h14
-rw-r--r--Source/JavaScriptCore/jit/SpecializedThunkJIT.h2
-rw-r--r--Source/JavaScriptCore/jit/ThunkGenerators.cpp20
-rw-r--r--Source/JavaScriptCore/jsc.cpp18
-rw-r--r--Source/JavaScriptCore/parser/ASTBuilder.h21
-rw-r--r--Source/JavaScriptCore/parser/Keywords.table4
-rw-r--r--Source/JavaScriptCore/parser/NodeConstructors.h3
-rw-r--r--Source/JavaScriptCore/parser/Nodes.h8
-rw-r--r--Source/JavaScriptCore/parser/Parser.cpp22
-rw-r--r--Source/JavaScriptCore/parser/Parser.h2
-rw-r--r--Source/JavaScriptCore/parser/ParserArena.h2
-rw-r--r--Source/JavaScriptCore/parser/SyntaxChecker.h2
-rw-r--r--Source/JavaScriptCore/profiler/Profile.h8
-rw-r--r--Source/JavaScriptCore/profiler/Profiler.cpp23
-rw-r--r--Source/JavaScriptCore/runtime/ArgList.h4
-rw-r--r--Source/JavaScriptCore/runtime/Arguments.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/ArrayPrototype.cpp20
-rw-r--r--Source/JavaScriptCore/runtime/CallData.h2
-rw-r--r--Source/JavaScriptCore/runtime/ClassInfo.h4
-rw-r--r--Source/JavaScriptCore/runtime/CommonSlowPaths.h2
-rw-r--r--Source/JavaScriptCore/runtime/Completion.cpp3
-rw-r--r--Source/JavaScriptCore/runtime/Completion.h4
-rw-r--r--Source/JavaScriptCore/runtime/ConstructData.h2
-rw-r--r--Source/JavaScriptCore/runtime/DateConstructor.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/DateInstance.h4
-rw-r--r--Source/JavaScriptCore/runtime/DatePrototype.cpp36
-rw-r--r--Source/JavaScriptCore/runtime/Error.cpp9
-rw-r--r--Source/JavaScriptCore/runtime/Error.h18
-rw-r--r--Source/JavaScriptCore/runtime/ErrorInstance.h8
-rw-r--r--Source/JavaScriptCore/runtime/ErrorPrototype.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/ExceptionHelpers.cpp8
-rw-r--r--Source/JavaScriptCore/runtime/ExceptionHelpers.h8
-rw-r--r--Source/JavaScriptCore/runtime/Executable.cpp104
-rw-r--r--Source/JavaScriptCore/runtime/Executable.h16
-rw-r--r--Source/JavaScriptCore/runtime/FunctionConstructor.cpp8
-rw-r--r--Source/JavaScriptCore/runtime/FunctionConstructor.h2
-rw-r--r--Source/JavaScriptCore/runtime/FunctionPrototype.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/GetterSetter.h4
-rw-r--r--Source/JavaScriptCore/runtime/Identifier.h16
-rw-r--r--Source/JavaScriptCore/runtime/InitializeThreading.h2
-rw-r--r--Source/JavaScriptCore/runtime/InternalFunction.h6
-rw-r--r--Source/JavaScriptCore/runtime/JSActivation.cpp8
-rw-r--r--Source/JavaScriptCore/runtime/JSActivation.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSArray.cpp297
-rw-r--r--Source/JavaScriptCore/runtime/JSArray.h39
-rw-r--r--Source/JavaScriptCore/runtime/JSBoundFunction.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/JSBoundFunction.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSByteArray.h18
-rw-r--r--Source/JavaScriptCore/runtime/JSCell.cpp9
-rw-r--r--Source/JavaScriptCore/runtime/JSCell.h22
-rw-r--r--Source/JavaScriptCore/runtime/JSFunction.cpp35
-rw-r--r--Source/JavaScriptCore/runtime/JSFunction.h16
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalData.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalData.h34
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.h28
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp15
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalThis.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSLock.h16
-rw-r--r--Source/JavaScriptCore/runtime/JSONObject.cpp22
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.cpp153
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.h140
-rw-r--r--Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSStaticScopeObject.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSString.cpp5
-rw-r--r--Source/JavaScriptCore/runtime/JSString.h26
-rw-r--r--Source/JavaScriptCore/runtime/JSValue.cpp14
-rw-r--r--Source/JavaScriptCore/runtime/JSValue.h19
-rw-r--r--Source/JavaScriptCore/runtime/JSValueInlineMethods.h1
-rw-r--r--Source/JavaScriptCore/runtime/JSVariableObject.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSVariableObject.h10
-rw-r--r--Source/JavaScriptCore/runtime/Lookup.h6
-rw-r--r--Source/JavaScriptCore/runtime/MemoryStatistics.h2
-rw-r--r--Source/JavaScriptCore/runtime/NumberPrototype.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/ObjectConstructor.cpp19
-rw-r--r--Source/JavaScriptCore/runtime/ObjectPrototype.cpp12
-rw-r--r--Source/JavaScriptCore/runtime/ObjectPrototype.h2
-rw-r--r--Source/JavaScriptCore/runtime/Operations.cpp10
-rw-r--r--Source/JavaScriptCore/runtime/Operations.h23
-rw-r--r--Source/JavaScriptCore/runtime/Options.cpp15
-rw-r--r--Source/JavaScriptCore/runtime/Options.h4
-rw-r--r--Source/JavaScriptCore/runtime/PropertyDescriptor.cpp50
-rw-r--r--Source/JavaScriptCore/runtime/PropertyDescriptor.h32
-rw-r--r--Source/JavaScriptCore/runtime/PropertyNameArray.h2
-rw-r--r--Source/JavaScriptCore/runtime/PropertySlot.h2
-rw-r--r--Source/JavaScriptCore/runtime/RegExp.cpp72
-rw-r--r--Source/JavaScriptCore/runtime/RegExp.h8
-rw-r--r--Source/JavaScriptCore/runtime/RegExpConstructor.cpp86
-rw-r--r--Source/JavaScriptCore/runtime/RegExpConstructor.h33
-rw-r--r--Source/JavaScriptCore/runtime/RegExpMatchesArray.h30
-rw-r--r--Source/JavaScriptCore/runtime/RegExpObject.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/RegExpObject.h4
-rw-r--r--Source/JavaScriptCore/runtime/RegExpPrototype.cpp6
-rw-r--r--Source/JavaScriptCore/runtime/SamplingCounter.h4
-rw-r--r--Source/JavaScriptCore/runtime/SmallStrings.h6
-rw-r--r--Source/JavaScriptCore/runtime/StringConstructor.cpp7
-rw-r--r--Source/JavaScriptCore/runtime/StringObject.h4
-rw-r--r--Source/JavaScriptCore/runtime/StringPrototype.cpp271
-rw-r--r--Source/JavaScriptCore/runtime/Structure.cpp23
-rw-r--r--Source/JavaScriptCore/runtime/Structure.h20
-rw-r--r--Source/JavaScriptCore/runtime/TimeoutChecker.h4
-rw-r--r--Source/JavaScriptCore/runtime/UString.h40
-rw-r--r--Source/JavaScriptCore/runtime/WriteBarrier.h4
-rw-r--r--Source/JavaScriptCore/tools/CodeProfile.cpp188
-rw-r--r--Source/JavaScriptCore/tools/CodeProfile.h93
-rw-r--r--Source/JavaScriptCore/tools/CodeProfiling.cpp163
-rw-r--r--Source/JavaScriptCore/tools/CodeProfiling.h85
-rw-r--r--Source/JavaScriptCore/tools/ProfileTreeNode.h123
-rw-r--r--Source/JavaScriptCore/tools/TieredMMapArray.h117
-rw-r--r--Source/JavaScriptCore/wtf/ASCIICType.h20
-rw-r--r--Source/JavaScriptCore/wtf/Alignment.h2
-rw-r--r--Source/JavaScriptCore/wtf/ArrayBufferView.h7
-rw-r--r--Source/JavaScriptCore/wtf/Assertions.cpp41
-rw-r--r--Source/JavaScriptCore/wtf/Assertions.h6
-rw-r--r--Source/JavaScriptCore/wtf/ByteArray.h2
-rw-r--r--Source/JavaScriptCore/wtf/CMakeLists.txt2
-rw-r--r--Source/JavaScriptCore/wtf/CheckedBoolean.h61
-rw-r--r--Source/JavaScriptCore/wtf/Compiler.h12
-rw-r--r--Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.h4
-rw-r--r--Source/JavaScriptCore/wtf/CurrentTime.h4
-rw-r--r--Source/JavaScriptCore/wtf/DateMath.h16
-rw-r--r--Source/JavaScriptCore/wtf/DecimalNumber.h8
-rw-r--r--Source/JavaScriptCore/wtf/DoublyLinkedList.h19
-rw-r--r--Source/JavaScriptCore/wtf/FastMalloc.cpp4
-rw-r--r--Source/JavaScriptCore/wtf/FastMalloc.h24
-rw-r--r--Source/JavaScriptCore/wtf/Forward.h2
-rw-r--r--Source/JavaScriptCore/wtf/InlineASM.h2
-rw-r--r--Source/JavaScriptCore/wtf/MD5.h6
-rw-r--r--Source/JavaScriptCore/wtf/MainThread.h18
-rw-r--r--Source/JavaScriptCore/wtf/MetaAllocator.cpp107
-rw-r--r--Source/JavaScriptCore/wtf/MetaAllocator.h59
-rw-r--r--Source/JavaScriptCore/wtf/MetaAllocatorHandle.h33
-rw-r--r--Source/JavaScriptCore/wtf/NumberOfCores.cpp75
-rw-r--r--Source/JavaScriptCore/wtf/NumberOfCores.h30
-rw-r--r--Source/JavaScriptCore/wtf/OSAllocator.h20
-rw-r--r--Source/JavaScriptCore/wtf/OSAllocatorPosix.cpp12
-rw-r--r--Source/JavaScriptCore/wtf/OwnPtrCommon.h6
-rw-r--r--Source/JavaScriptCore/wtf/PageBlock.h2
-rw-r--r--Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp48
-rw-r--r--Source/JavaScriptCore/wtf/ParallelJobsGeneric.h3
-rw-r--r--Source/JavaScriptCore/wtf/Platform.h12
-rw-r--r--Source/JavaScriptCore/wtf/PlatformEfl.cmake1
-rw-r--r--Source/JavaScriptCore/wtf/RandomNumber.h2
-rw-r--r--Source/JavaScriptCore/wtf/RedBlackTree.h135
-rw-r--r--Source/JavaScriptCore/wtf/RefCountedLeakCounter.h12
-rw-r--r--Source/JavaScriptCore/wtf/SHA1.h6
-rw-r--r--Source/JavaScriptCore/wtf/StdLibExtras.h9
-rw-r--r--Source/JavaScriptCore/wtf/Threading.cpp2
-rw-r--r--Source/JavaScriptCore/wtf/Threading.h16
-rw-r--r--Source/JavaScriptCore/wtf/ThreadingPrimitives.h22
-rw-r--r--Source/JavaScriptCore/wtf/Uint8Array.h2
-rw-r--r--Source/JavaScriptCore/wtf/Uint8ClampedArray.h104
-rw-r--r--Source/JavaScriptCore/wtf/Vector.h2
-rw-r--r--Source/JavaScriptCore/wtf/WTFThreadData.h4
-rw-r--r--Source/JavaScriptCore/wtf/dtoa.h10
-rw-r--r--Source/JavaScriptCore/wtf/efl/OwnPtrEfl.cpp7
-rw-r--r--Source/JavaScriptCore/wtf/gobject/GOwnPtr.cpp12
-rw-r--r--Source/JavaScriptCore/wtf/gobject/GOwnPtr.h2
-rw-r--r--Source/JavaScriptCore/wtf/gobject/GTypedefs.h2
-rw-r--r--Source/JavaScriptCore/wtf/text/AtomicString.cpp48
-rw-r--r--Source/JavaScriptCore/wtf/text/AtomicString.h22
-rw-r--r--Source/JavaScriptCore/wtf/text/CString.h10
-rw-r--r--Source/JavaScriptCore/wtf/text/StringBuilder.cpp14
-rw-r--r--Source/JavaScriptCore/wtf/text/StringBuilder.h147
-rw-r--r--Source/JavaScriptCore/wtf/text/StringHash.h4
-rw-r--r--Source/JavaScriptCore/wtf/text/StringImpl.cpp184
-rw-r--r--Source/JavaScriptCore/wtf/text/StringImpl.h83
-rw-r--r--Source/JavaScriptCore/wtf/text/WTFString.cpp7
-rw-r--r--Source/JavaScriptCore/wtf/text/WTFString.h14
-rw-r--r--Source/JavaScriptCore/wtf/unicode/CharacterNames.h1
-rw-r--r--Source/JavaScriptCore/wtf/unicode/Collator.h8
-rw-r--r--Source/JavaScriptCore/wtf/unicode/UTF8.h4
-rw-r--r--Source/JavaScriptCore/wtf/wtf.pri42
-rw-r--r--Source/JavaScriptCore/wtf/wtf.pro252
-rw-r--r--Source/JavaScriptCore/yarr/Yarr.h4
-rw-r--r--Source/JavaScriptCore/yarr/YarrInterpreter.cpp21
-rw-r--r--Source/JavaScriptCore/yarr/YarrJIT.cpp10
-rw-r--r--Source/JavaScriptCore/yarr/YarrPattern.h2
309 files changed, 11605 insertions, 4375 deletions
diff --git a/Source/JavaScriptCore/API/JSObjectRef.cpp b/Source/JavaScriptCore/API/JSObjectRef.cpp
index 99b41b685..cd8d7159e 100644
--- a/Source/JavaScriptCore/API/JSObjectRef.cpp
+++ b/Source/JavaScriptCore/API/JSObjectRef.cpp
@@ -274,7 +274,7 @@ void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef prope
JSValue jsValue = toJS(exec, value);
if (attributes && !jsObject->hasProperty(exec, name))
- jsObject->methodTable()->putWithAttributes(jsObject, exec, name, jsValue, attributes);
+ jsObject->methodTable()->putDirectVirtual(jsObject, exec, name, jsValue, attributes);
else {
PutPropertySlot slot;
jsObject->methodTable()->put(jsObject, exec, name, jsValue, slot);
diff --git a/Source/JavaScriptCore/API/JSValueRef.cpp b/Source/JavaScriptCore/API/JSValueRef.cpp
index c89e267a4..1b4e03bde 100644
--- a/Source/JavaScriptCore/API/JSValueRef.cpp
+++ b/Source/JavaScriptCore/API/JSValueRef.cpp
@@ -293,7 +293,7 @@ JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef*
JSValue jsValue = toJS(exec, value);
- RefPtr<OpaqueJSString> stringRef(OpaqueJSString::create(jsValue.toString(exec)));
+ RefPtr<OpaqueJSString> stringRef(OpaqueJSString::create(jsValue.toString(exec)->value(exec)));
if (exec->hadException()) {
if (exception)
*exception = toRef(exec, exec->exception());
diff --git a/Source/JavaScriptCore/API/OpaqueJSString.h b/Source/JavaScriptCore/API/OpaqueJSString.h
index 5c24f7510..1c63150cf 100644
--- a/Source/JavaScriptCore/API/OpaqueJSString.h
+++ b/Source/JavaScriptCore/API/OpaqueJSString.h
@@ -46,7 +46,7 @@ struct OpaqueJSString : public ThreadSafeRefCounted<OpaqueJSString> {
return adoptRef(new OpaqueJSString(characters, length));
}
- static PassRefPtr<OpaqueJSString> create(const JSC::UString&);
+ JS_EXPORT_PRIVATE static PassRefPtr<OpaqueJSString> create(const JSC::UString&);
UChar* characters() { return this ? m_characters : 0; }
unsigned length() { return this ? m_length : 0; }
diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt
index 00e0296c0..a620c5a52 100644
--- a/Source/JavaScriptCore/CMakeLists.txt
+++ b/Source/JavaScriptCore/CMakeLists.txt
@@ -14,6 +14,7 @@ SET(JavaScriptCore_INCLUDE_DIRECTORIES
"${JAVASCRIPTCORE_DIR}/parser"
"${JAVASCRIPTCORE_DIR}/profiler"
"${JAVASCRIPTCORE_DIR}/runtime"
+ "${JAVASCRIPTCORE_DIR}/tools"
"${JAVASCRIPTCORE_DIR}/yarr"
"${JAVASCRIPTCORE_DIR}/wtf"
"${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}"
@@ -35,12 +36,16 @@ SET(JavaScriptCore_SOURCES
API/OpaqueJSString.cpp
bytecode/CallLinkInfo.cpp
+ bytecode/CallLinkStatus.cpp
bytecode/CodeBlock.cpp
bytecode/DFGExitProfile.cpp
+ bytecode/GetByIdStatus.cpp
bytecode/JumpTable.cpp
bytecode/MethodCallLinkInfo.cpp
+ bytecode/MethodCallLinkStatus.cpp
bytecode/Opcode.cpp
bytecode/PredictedType.cpp
+ bytecode/PutByIdStatus.cpp
bytecode/SamplingTool.cpp
bytecode/StructureStubInfo.cpp
bytecode/ValueProfile.cpp
@@ -69,7 +74,7 @@ SET(JavaScriptCore_SOURCES
dfg/DFGSpeculativeJIT64.cpp
dfg/DFGThunks.cpp
- heap/AllocationSpace.cpp
+ heap/BumpSpace.cpp
heap/DFGCodeBlocks.cpp
heap/Heap.cpp
heap/HandleHeap.cpp
@@ -84,6 +89,7 @@ SET(JavaScriptCore_SOURCES
debugger/DebuggerActivation.cpp
debugger/DebuggerCallFrame.cpp
+ interpreter/AbstractPC.cpp
interpreter/CallFrame.cpp
interpreter/Interpreter.cpp
interpreter/RegisterFile.cpp
@@ -195,6 +201,9 @@ SET(JavaScriptCore_SOURCES
runtime/TimeoutChecker.cpp
runtime/UString.cpp
+ tools/CodeProfile.cpp
+ tools/CodeProfiling.cpp
+
yarr/YarrPattern.cpp
yarr/YarrInterpreter.cpp
yarr/YarrJIT.cpp
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index c8b43b41c..1f53cd789 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,3311 @@
+2012-02-01 Michael Saboff <msaboff@apple.com>
+
+ Yarr crash with regexp replace
+ https://bugs.webkit.org/show_bug.cgi?id=67454
+
+ Reviewed by Gavin Barraclough.
+
+ Properly handle the case of a back reference to an unmatched
+ subpattern by always matching without consuming any characters.
+
+ * yarr/YarrInterpreter.cpp:
+ (JSC::Yarr::Interpreter::matchBackReference):
+ (JSC::Yarr::Interpreter::backtrackBackReference):
+
+2012-02-01 Gavin Barraclough <barraclough@apple.com>
+
+ calling function on catch block scope containing an eval result in wrong this value being passed
+ https://bugs.webkit.org/show_bug.cgi?id=77581
+
+ Reviewed by Oliver Hunt.
+
+ javascript:function F(){ return 'F' in this; }; try { throw F; } catch (e) { eval(""); alert(e()); }
+
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::TryNode::emitBytecode):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::execute):
+ * parser/ASTBuilder.h:
+ (JSC::ASTBuilder::createTryStatement):
+ * parser/NodeConstructors.h:
+ (JSC::TryNode::TryNode):
+ * parser/Nodes.h:
+ (TryNode):
+ * parser/Parser.cpp:
+ (JSC::::parseTryStatement):
+ * parser/SyntaxChecker.h:
+ (JSC::SyntaxChecker::createTryStatement):
+ * runtime/JSObject.h:
+ (JSObject):
+ (JSC::JSObject::isStaticScopeObject):
+ (JSC):
+
+2012-02-01 Oliver Hunt <oliver@apple.com>
+
+ Add support for inferred function names
+ https://bugs.webkit.org/show_bug.cgi?id=77579
+
+ Reviewed by Gavin Barraclough.
+
+ Add new "inferred" names to function expressions, getters, and setters.
+ This property is not exposed to JS, so is only visible in the debugger
+ and profiler.
+
+ * JavaScriptCore.exp:
+ * bytecompiler/BytecodeGenerator.h:
+ (JSC::BytecodeGenerator::makeFunction):
+ * debugger/DebuggerCallFrame.cpp:
+ (JSC::DebuggerCallFrame::calculatedFunctionName):
+ * parser/ASTBuilder.h:
+ (JSC::ASTBuilder::createAssignResolve):
+ (JSC::ASTBuilder::createGetterOrSetterProperty):
+ (JSC::ASTBuilder::createProperty):
+ (JSC::ASTBuilder::makeAssignNode):
+ * parser/Nodes.h:
+ (JSC::FunctionBodyNode::setInferredName):
+ (JSC::FunctionBodyNode::inferredName):
+ (FunctionBodyNode):
+ * profiler/Profiler.cpp:
+ (JSC):
+ (JSC::Profiler::createCallIdentifier):
+ (JSC::createCallIdentifierFromFunctionImp):
+ * runtime/Executable.cpp:
+ (JSC::FunctionExecutable::FunctionExecutable):
+ (JSC::FunctionExecutable::fromGlobalCode):
+ * runtime/Executable.h:
+ (JSC::FunctionExecutable::create):
+ (JSC::FunctionExecutable::inferredName):
+ (FunctionExecutable):
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::calculatedDisplayName):
+ (JSC):
+ (JSC::getCalculatedDisplayName):
+ * runtime/JSFunction.h:
+ (JSC):
+
+2012-02-01 Filip Pizlo <fpizlo@apple.com>
+
+ DFG should fold double-to-int conversions
+ https://bugs.webkit.org/show_bug.cgi?id=77532
+
+ Reviewed by Oliver Hunt.
+
+ Performance neutral on major benchmarks. But it makes calling V8's
+ Math.random() 4x faster.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC):
+ (JSC::CodeBlock::addOrFindConstant):
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::addConstant):
+ (CodeBlock):
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::toInt32):
+ (ByteCodeParser):
+ (JSC::DFG::ByteCodeParser::getJSConstantForValue):
+ (JSC::DFG::ByteCodeParser::isInt32Constant):
+ * dfg/DFGGraph.h:
+ (JSC::DFG::Graph::addShouldSpeculateInteger):
+ (Graph):
+ (JSC::DFG::Graph::addImmediateShouldSpeculateInteger):
+ * dfg/DFGPropagator.cpp:
+ (JSC::DFG::Propagator::propagateNodePredictions):
+ (JSC::DFG::Propagator::doRoundOfDoubleVoting):
+ (JSC::DFG::Propagator::fixupNode):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileAdd):
+ (DFG):
+ (JSC::DFG::SpeculativeJIT::compileArithSub):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::valueOfNumberConstantAsInt32):
+ (SpeculativeJIT):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * runtime/JSValueInlineMethods.h:
+ (JSC::JSValue::asDouble):
+
+2012-02-01 Filip Pizlo <fpizlo@apple.com>
+
+ DFG graph dump for GetScopedVar should show the correct prediction
+ https://bugs.webkit.org/show_bug.cgi?id=77530
+
+ Reviewed by Geoff Garen.
+
+ GetScopedVar has a heap prediction, not a variable prediction. But it does
+ have a variable. Hence we need to check for heap predictions before checking
+ for variable predictions.
+
+ * dfg/DFGGraph.cpp:
+ (JSC::DFG::Graph::dump):
+
+2012-02-01 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ Replace JSArray destructor with finalizer
+ https://bugs.webkit.org/show_bug.cgi?id=77488
+
+ Reviewed by Geoffrey Garen.
+
+ * JavaScriptCore.exp:
+ * runtime/JSArray.cpp:
+ (JSC::JSArray::finalize): Added finalizer.
+ (JSC::JSArray::allocateSparseMap): Factored out code for allocating new sparse maps.
+ (JSC):
+ (JSC::JSArray::deallocateSparseMap): Factored out code for deallocating sparse maps.
+ (JSC::JSArray::enterDictionaryMode): Renamed enterSparseMode to enterDictionaryMode
+ because the old name was confusing because we could have a sparse array that never
+ called enterSparseMode.
+ (JSC::JSArray::defineOwnNumericProperty):
+ (JSC::JSArray::setLengthWritable):
+ (JSC::JSArray::putByIndexBeyondVectorLength):
+ (JSC::JSArray::setLength):
+ (JSC::JSArray::pop):
+ (JSC::JSArray::sort):
+ (JSC::JSArray::compactForSorting):
+ * runtime/JSArray.h:
+ (JSArray):
+
+2012-02-01 Andy Wingo <wingo@igalia.com>
+
+ Refactor identifier resolution in BytecodeGenerator
+ https://bugs.webkit.org/show_bug.cgi?id=76285
+
+ Reviewed by Geoffrey Garen.
+
+ * bytecompiler/BytecodeGenerator.h:
+ (JSC::ResolveResult): New class, to describe the storage
+ location corresponding to an identifier in a program.
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::resolve): New function, replacing
+ findScopedProperty.
+ (JSC::BytecodeGenerator::resolveConstDecl): New function,
+ encapsulating what ConstDeclNode::emitBytecode used to do.
+ (JSC::BytecodeGenerator::emitGetStaticVar):
+ (JSC::BytecodeGenerator::emitPutStaticVar): New functions,
+ corresponding to the old emitGetScopedVar and emitPutScopedVar.
+ (JSC::BytecodeGenerator::registerFor): Remove version that took an
+ Identifier&; replaced by ResolveResult::local().
+ (JSC::BytecodeGenerator::emitResolve):
+ (JSC::BytecodeGenerator::emitResolveBase):
+ (JSC::BytecodeGenerator::emitResolveBaseForPut):
+ (JSC::BytecodeGenerator::emitResolveWithBase):
+ (JSC::BytecodeGenerator::emitResolveWithThis): Change to accept a
+ "resolveResult" argument. This is more clear, and reduces the
+ amount of double analysis happening at compile-time.
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::ResolveNode::emitBytecode):
+ (JSC::EvalFunctionCallNode::emitBytecode):
+ (JSC::FunctionCallResolveNode::emitBytecode):
+ (JSC::PostfixResolveNode::emitBytecode):
+ (JSC::DeleteResolveNode::emitBytecode):
+ (JSC::TypeOfResolveNode::emitBytecode):
+ (JSC::PrefixResolveNode::emitBytecode):
+ (JSC::ReadModifyResolveNode::emitBytecode):
+ (JSC::AssignResolveNode::emitBytecode):
+ (JSC::ConstDeclNode::emitCodeSingle):
+ (JSC::ForInNode::emitBytecode): Refactor to use the new
+ ResolveResult structure.
+
+2012-02-01 Csaba Osztrogonác <ossy@webkit.org>
+
+ Implement Error.stack
+ https://bugs.webkit.org/show_bug.cgi?id=66994
+
+ Unreviewed, rolling out r106407.
+
+ * JavaScriptCore.exp:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
+ * interpreter/AbstractPC.cpp:
+ (JSC::AbstractPC::AbstractPC):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::throwException):
+ * interpreter/Interpreter.h:
+ (JSC):
+ (Interpreter):
+ * jsc.cpp:
+ (GlobalObject::finishCreation):
+ * parser/Parser.h:
+ (JSC::::parse):
+ * runtime/CommonIdentifiers.h:
+ * runtime/Error.cpp:
+ (JSC::addErrorInfo):
+ * runtime/Error.h:
+ (JSC):
+
+2012-01-31 Hajime Morrita <morrita@chromium.org>
+
+ Add missing JS_PRIVATE_EXPORTs
+ https://bugs.webkit.org/show_bug.cgi?id=77507
+
+ Reviewed by Kevin Ollivier.
+
+ * heap/MarkedSpace.h:
+ (MarkedSpace):
+ * interpreter/Interpreter.h:
+ (Interpreter):
+ * runtime/JSValue.h:
+ (JSValue):
+ * wtf/text/AtomicString.h:
+ (WTF::AtomicString::add):
+ * wtf/text/WTFString.h:
+ (WTF):
+
+2012-01-31 Geoffrey Garen <ggaren@apple.com>
+
+ Stop using -fomit-frame-pointer
+ https://bugs.webkit.org/show_bug.cgi?id=77403
+
+ Reviewed by Filip Pizlo.
+
+ JavaScriptCore is too fast. I'm just the man to fix it.
+
+ * Configurations/JavaScriptCore.xcconfig:
+
+2012-01-31 Michael Saboff <msaboff@apple.com>
+
+ StringProtoFuncToUpperCase should call StringImpl::upper similar to StringProtoToLowerCase
+ https://bugs.webkit.org/show_bug.cgi?id=76647
+
+ Reviewed by Darin Adler.
+
+ Changed stringProtoFuncToUpperCase to call StringImpl::upper() in a manor similar
+ to stringProtoFuncToLowerCase(). Fixed StringImpl::upper() to handle to special
+ cases. One case is s-sharp (0xdf) which converts to "SS". The other case is
+ for characters which become 16 bit values when converted to upper case. For
+ those, we up convert the the source string and use the 16 bit path.
+
+ * runtime/StringPrototype.cpp:
+ (JSC::stringProtoFuncToUpperCase):
+ * wtf/text/StringImpl.cpp:
+ (WTF::StringImpl::upper):
+ * wtf/unicode/CharacterNames.h:
+ (smallLetterSharpS): New constant
+
+2012-01-31 Oliver Hunt <oliver@apple.com>
+
+ Remove unneeded sourceId property
+ https://bugs.webkit.org/show_bug.cgi?id=77495
+
+ Reviewed by Filip Pizlo.
+
+ sourceId isn't used anymore, so we'll just remove it.
+
+ * runtime/Error.cpp:
+ (JSC):
+ (JSC::addErrorInfo):
+ (JSC::hasErrorInfo):
+
+2012-01-31 Oliver Hunt <oliver@apple.com>
+
+ Implement Error.stack
+ https://bugs.webkit.org/show_bug.cgi?id=66994
+
+ Reviewed by Gavin Barraclough.
+
+ Original patch by Juan Carlos Montemayor Elosua:
+ This patch utilizes topCallFrame to create a stack trace when
+ an error is thrown. Users will also be able to use the stack()
+ command in jsc to get arrays with stack trace information.
+
+ Modified to be correct on ToT, with a variety of correctness,
+ performance, and security improvements.
+
+ * JavaScriptCore.exp:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
+ * interpreter/Interpreter.cpp:
+ (JSC::getCallerLine):
+ (JSC::getSourceURLFromCallFrame):
+ (JSC::getStackFrameCodeType):
+ (JSC::Interpreter::getStackTrace):
+ (JSC::Interpreter::throwException):
+ * interpreter/Interpreter.h:
+ (JSC::StackFrame::toString):
+ * jsc.cpp:
+ (GlobalObject::finishCreation):
+ (functionJSCStack):
+ * parser/Parser.h:
+ (JSC::Parser::parse):
+ * runtime/CommonIdentifiers.h:
+ * runtime/Error.cpp:
+ (JSC::addErrorInfo):
+ * runtime/Error.h:
+
+2012-01-31 Scott Graham <scottmg@chromium.org>
+
+ [Chromium] Remove references to gyp cygwin build target
+ https://bugs.webkit.org/show_bug.cgi?id=77253
+
+ Reviewed by Julien Chaffraix.
+
+ Target dependency is no longer required, it's done earlier in the
+ build process.
+
+ * JavaScriptCore.gyp/JavaScriptCore.gyp:
+
+2012-01-31 Michael Saboff <msaboff@apple.com>
+
+ ASSERT(m_jumpsToLink.isEmpty()) failing in ARMv7Assembler dtor
+ https://bugs.webkit.org/show_bug.cgi?id=77443
+
+ Reviewed by Gavin Barraclough.
+
+ Removed failing ASSERT() and thus destructor. The ASSERT isn't needed.
+ We are hitting it in the YARR JIT case where we bail out and go to the
+ interpreter with a partially JIT'ed function. Since we haven't linked
+ the JIT'ed code, there is likely to be some unresolved jumps in the vector
+ when the ARMv7Assembler destructor is called. For the case where we
+ complete the JIT process, we clear the vector at the end of
+ LinkBuffer::linkCode (LinkBuffer.h:292).
+
+ * assembler/ARMv7Assembler.h:
+ (ARMv7Assembler):
+
+2012-01-31 Anders Carlsson <andersca@apple.com>
+
+ Vector<T>::operator== shouldn't require T to have operator!=
+ https://bugs.webkit.org/show_bug.cgi?id=77448
+
+ Reviewed by Andreas Kling.
+
+ Change VectorComparer::compare to use !(a == b) instead of a != b since
+ it makes more sense for Vector::operator== to use the element's operator==.
+
+ * wtf/Vector.h:
+
+2012-01-30 Oliver Hunt <oliver@apple.com>
+
+ get_by_val_arguments is broken in the interpreter
+ https://bugs.webkit.org/show_bug.cgi?id=77389
+
+ Reviewed by Gavin Barraclough.
+
+ When get_by_val had wad a value profile added, the same slot was not added to
+ get_by_val_arguments. This broke the interpreter as the interpreter falls
+ back on its regular get_by_val implementation.
+
+ No tests are added as the interpreter is fairly broken in its
+ current state (multiple tests fail due to this bug).
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::dump):
+ * bytecode/Opcode.h:
+ (JSC):
+ ():
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::emitGetArgumentByVal):
+
+2012-01-30 Oliver Hunt <oliver@apple.com>
+
+ Unexpected syntax error
+ https://bugs.webkit.org/show_bug.cgi?id=77340
+
+ Reviewed by Gavin Barraclough.
+
+ Function calls and new expressions have the same semantics for
+ assignment, so should simply share their lhs handling.
+
+ * parser/Parser.cpp:
+ (JSC::::parseMemberExpression):
+
+2012-01-30 Gavin Barraclough <barraclough@apple.com>
+
+ Unreviewed ARMv7 build fix.
+
+ * tools/CodeProfiling.cpp:
+ (JSC):
+ (JSC::setProfileTimer):
+ (JSC::CodeProfiling::begin):
+ (JSC::CodeProfiling::end):
+
+2012-01-30 David Levin <levin@chromium.org>
+
+ Using OS(WIN) or OS(MAC) should cause a build error.
+ https://bugs.webkit.org/show_bug.cgi?id=77162
+
+ Reviewed by Darin Adler.
+
+ * wtf/Platform.h: Expand them into something that will
+ cause a compile error.
+
+2012-01-30 Yong Li <yoli@rim.com>
+
+ [BlackBerry] OS(QNX) also has TM_GMTOFF, TM_ZONE, and TIMEGM
+ https://bugs.webkit.org/show_bug.cgi?id=77360
+
+ Reviewed by Rob Buis.
+
+ Turn on HAVE(TM_GMTOFF), HAVE(TM_ZONE), and HAVE(TIMEGM)
+ for OS(QNX).
+
+ * wtf/Platform.h:
+
+2012-01-30 Gavin Barraclough <barraclough@apple.com>
+
+ Speculative Windows build fix.
+
+ * assembler/MacroAssemblerCodeRef.h:
+ (FunctionPtr):
+
+2012-01-30 Gavin Barraclough <barraclough@apple.com>
+
+ https://bugs.webkit.org/show_bug.cgi?id=77163
+ MacroAssemblerCodeRef.h uses OS(WIN) instead of OS(WINDOWS)
+
+ Rubber stamped by Geoff Garen
+
+ * assembler/MacroAssemblerCodeRef.h:
+
+2012-01-30 Gavin Barraclough <barraclough@apple.com>
+
+ Unreviewed build fix for interpreter builds.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::CodeBlock):
+ * bytecode/CodeBlock.h:
+ (CodeBlock):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+ * tools/CodeProfile.cpp:
+ (JSC::CodeProfile::sample):
+
+2012-01-30 Gavin Barraclough <barraclough@apple.com>
+
+ Unreviewed build fix following bug#76855
+
+ * JavaScriptCore.exp:
+
+2012-01-30 Michael Saboff <msaboff@apple.com>
+
+ CaseFoldingHash::hash() doesn't handle 8 bit strings directly
+ https://bugs.webkit.org/show_bug.cgi?id=76652
+
+ Reviewed by Andreas Kling.
+
+ * wtf/text/StringHash.h:
+ (WTF::CaseFoldingHash::hash): Added 8 bit string code path.
+
+2012-01-30 Michael Saboff <msaboff@apple.com>
+
+ stringProtoFuncReplace converts 8 bit strings to 16 bit during replacement
+ https://bugs.webkit.org/show_bug.cgi?id=76651
+
+ Reviewed by Geoffrey Garen.
+
+ Made local function substituteBackreferencesSlow a template function
+ based on character width. Cleaned up getCharacters() in both UString
+ and StringImpl. Changed getCharacters<UChar> to up convert an 8 bit
+ string to 16 bits if necessary.
+
+ * runtime/StringPrototype.cpp:
+ (JSC::substituteBackreferencesSlow):
+ (JSC::substituteBackreferences):
+ * runtime/UString.h:
+ (JSC::LChar):
+ (JSC::UChar):
+ * wtf/text/StringImpl.h:
+ (WTF::UChar):
+
+2012-01-30 Gavin Barraclough <barraclough@apple.com>
+
+ Clean up putDirect
+ https://bugs.webkit.org/show_bug.cgi?id=76232
+
+ Reviewed by Sam Weinig.
+
+ Part 3 - merge op_put_getter & op_put_setter.
+
+ Putting these separately is inefficient (and makes future optimiation,
+ e.g. making GetterSetter immutable) harder. Change to emit a single
+ op_put_getter_setter bytecode op. Ultimately we should probably be
+ able to merge this with put direct, to create a common op to initialize
+ object literal properties.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::dump):
+ * bytecode/Opcode.h:
+ (JSC):
+ ():
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::emitPutGetterSetter):
+ * bytecompiler/BytecodeGenerator.h:
+ (BytecodeGenerator):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::PropertyListNode::emitBytecode):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ * jit/JIT.h:
+ (JIT):
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emit_op_put_getter_setter):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::emit_op_put_getter_setter):
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+ * jit/JITStubs.h:
+ ():
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::putDirectVirtual):
+ (JSC::JSObject::putDirectAccessor):
+ (JSC):
+ (JSC::putDescriptor):
+ (JSC::JSObject::defineOwnProperty):
+ * runtime/JSObject.h:
+ ():
+ (JSC::JSObject::putDirectInternal):
+ (JSC::JSObject::putDirect):
+ (JSC::JSObject::putDirectWithoutTransition):
+
+2012-01-30 Michael Saboff <msaboff@apple.com>
+
+ Dromaeo tests call parseSimpleLengthValue() on 8 bit strings
+ https://bugs.webkit.org/show_bug.cgi?id=76649
+
+ Reviewed by Geoffrey Garen.
+
+ * JavaScriptCore.exp: Added export for charactersToDouble.
+
+2012-01-30 Michael Saboff <msaboff@apple.com>
+
+ WebCore decodeEscapeSequences unnecessarily converts 8 bit strings to 16 bit when decoding.
+ https://bugs.webkit.org/show_bug.cgi?id=76648
+
+ Reviewed by Geoffrey Garen.
+
+ Added a new overloaded append member that takes a String& argument, an offest
+ and a length to do direct sub string appending to a StringBuilder.
+
+ * wtf/text/StringBuilder.h:
+ (WTF::StringBuilder::append):
+
+2012-01-29 Zoltan Herczeg <zherczeg@webkit.org>
+
+ Custom written CSS lexer
+ https://bugs.webkit.org/show_bug.cgi?id=70107
+
+ Reviewed by Antti Koivisto and Oliver Hunt.
+
+ Add new helper functions for the custom written CSS lexer.
+
+ * wtf/ASCIICType.h:
+ (WTF::toASCIILowerUnchecked):
+ (WTF):
+ (WTF::isASCIIAlphaCaselessEqual):
+
+2012-01-29 Filip Pizlo <fpizlo@apple.com>
+
+ REGRESSION (r105576-r105582): Web Inspector Crash in JSC::JSValue::toString(JSC::ExecState*) const
+ https://bugs.webkit.org/show_bug.cgi?id=77146
+ <rdar://problem/10770586>
+
+ Reviewed by Oliver Hunt.
+
+ The old JIT expects that the result of the last operation is in the lastResultRegister. The DFG JIT is
+ designed to correctly track the lastResultRegister by looking at SetLocal nodes. However, when the DFG
+ JIT inlines a code block, it forgets that the inlined code block's result would have been placed in the
+ lastResultRegister. Hence if we OSR exit on the first node following the end of an inlined code block
+ that had a return value, and that first node uses the return value, the old JIT will get massively
+ confused. This patch takes a surgical approach: instead of making the DFG smarter, it makes the old
+ JIT slightly dumber.
+
+ * jit/JITCall.cpp:
+ (JSC::JIT::emit_op_call_put_result):
+
+2012-01-29 Filip Pizlo <fpizlo@apple.com>
+
+ Build fix for Mac non-x64 platforms.
+
+ * tools/CodeProfiling.cpp:
+ (JSC):
+
+2012-01-28 Gavin Barraclough <barraclough@apple.com>
+
+ Reserve 'let'
+ https://bugs.webkit.org/show_bug.cgi?id=77293
+
+ Rubber stamped by Oliver Hunt.
+
+ 'let' may become a keyword in ES6. We're going to try experimentally reserving it,
+ to see if this breaks the web.
+
+ * parser/Keywords.table:
+
+2012-01-27 Gavin Barraclough <barraclough@apple.com>
+
+ Implement a JIT-code aware sampling profiler for JSC
+ https://bugs.webkit.org/show_bug.cgi?id=76855
+
+ Reviewed by Oliver Hunt.
+
+ To enable the profiler, set the JSC_CODE_PROFILING environment variable to
+ 1 (no tracing the C stack), 2 (trace one level of C code) or 3 (recursively
+ trace all samples).
+
+ The profiler requires -fomit-frame-pointer to be removed from the build flags.
+
+ * JavaScriptCore.exp:
+ - Removed an export.
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ - Added new files
+ * bytecode/CodeBlock.cpp:
+ - For baseline codeblocks, cache the result of canCompileWithDFG.
+ * bytecode/CodeBlock.h:
+ - For baseline codeblocks, cache the result of canCompileWithDFG.
+ * jit/ExecutableAllocator.cpp:
+ (JSC::ExecutableAllocator::initializeAllocator):
+ - Notify the profiler when the allocator is created.
+ (JSC::ExecutableAllocator::allocate):
+ - Inform the allocated of the ownerUID.
+ * jit/ExecutableAllocatorFixedVMPool.cpp:
+ (JSC::ExecutableAllocator::initializeAllocator):
+ - Notify the profiler when the allocator is created.
+ (JSC::ExecutableAllocator::allocate):
+ - Inform the allocated of the ownerUID.
+ * jit/JITStubs.cpp:
+ - If profiling, don't mask the return address in JIT code.
+ (We do so to provide nicer backtraces in debug builds).
+ * runtime/Completion.cpp:
+ (JSC::evaluate):
+ - Notify the profiler of script evaluations.
+ * tools: Added.
+ * tools/CodeProfile.cpp: Added.
+ (JSC::symbolName):
+ - Helper function to get the name of a symbol in the framework.
+ (JSC::truncateTrace):
+ - Helper to truncate traces into methods know to have uninformatively deep stacks.
+ (JSC::CodeProfile::sample):
+ - Record a stack trace classifying samples.
+ (JSC::CodeProfile::report):
+ - {Print profiler output.
+ * tools/CodeProfile.h: Added.
+ - new class, captures a set of samples associated with an evaluated script,
+ and nested to record samples from subscripts.
+ * tools/CodeProfiling.cpp: Added.
+ (JSC::CodeProfiling::profilingTimer):
+ - callback fired then a timer event occurs.
+ (JSC::CodeProfiling::notifyAllocator):
+ - called when the executable allocator is constructed.
+ (JSC::CodeProfiling::getOwnerUIDForPC):
+ - helper to lookup the codeblock from an address in JIT code
+ (JSC::CodeProfiling::begin):
+ - enter a profiling scope.
+ (JSC::CodeProfiling::end):
+ - exit a profiling scope.
+ * tools/CodeProfiling.h: Added.
+ - new class, instantialed from Completion to define a profiling scope.
+ * tools/ProfileTreeNode.h: Added.
+ - new class, used to construct a tree of samples.
+ * tools/TieredMMapArray.h: Added.
+ - new class, a malloc-free vector (can be used while the main thread is suspended,
+ possibly holding the malloc heap lock).
+ * wtf/MetaAllocator.cpp:
+ (WTF::MetaAllocatorHandle::MetaAllocatorHandle):
+ (WTF::MetaAllocator::allocate):
+ - Allow allocation handles to track information about their owner.
+ * wtf/MetaAllocator.h:
+ (MetaAllocator):
+ - Allow allocation handles to track information about their owner.
+ * wtf/MetaAllocatorHandle.h:
+ (MetaAllocatorHandle):
+ (WTF::MetaAllocatorHandle::ownerUID):
+ - Allow allocation handles to track information about their owner.
+ * wtf/OSAllocator.h:
+ (WTF::OSAllocator::reallocateCommitted):
+ - reallocate an existing, committed memory allocation.
+
+2012-01-28 Sheriff Bot <webkit.review.bot@gmail.com>
+
+ Unreviewed, rolling out r106187.
+ http://trac.webkit.org/changeset/106187
+ https://bugs.webkit.org/show_bug.cgi?id=77276
+
+ The last rollout was a false charge. (Requested by morrita on
+ #webkit).
+
+ * runtime/ExceptionHelpers.h:
+ (InterruptedExecutionError):
+ * runtime/JSBoundFunction.h:
+ (JSBoundFunction):
+ * runtime/RegExp.h:
+ (RegExp):
+ * runtime/RegExpMatchesArray.h:
+ (RegExpMatchesArray):
+
+2012-01-28 Sheriff Bot <webkit.review.bot@gmail.com>
+
+ Unreviewed, rolling out r106151.
+ http://trac.webkit.org/changeset/106151
+ https://bugs.webkit.org/show_bug.cgi?id=77275
+
+ may break windows build (Requested by morrita on #webkit).
+
+ * runtime/ExceptionHelpers.h:
+ (InterruptedExecutionError):
+ * runtime/JSBoundFunction.h:
+ (JSBoundFunction):
+ * runtime/RegExp.h:
+ (RegExp):
+ * runtime/RegExpMatchesArray.h:
+ (RegExpMatchesArray):
+
+2012-01-28 Filip Pizlo <fpizlo@apple.com>
+
+ GC invoked while doing an old JIT property storage reallocation may lead
+ to an object that refers to a dead structure
+ https://bugs.webkit.org/show_bug.cgi?id=77273
+ <rdar://problem/10770565>
+
+ Reviewed by Gavin Barraclough.
+
+ The put_by_id transition was already saving the old structure by virtue of
+ having the object on the stack, so that wasn't going to get deleted. But the
+ new structure was unprotected in the transition. I've now changed the
+ transition code to save the new structure, ensuring that the GC will know it
+ to be marked if invoked from within put_by_id_transition_realloc.
+
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::privateCompilePutByIdTransition):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::privateCompilePutByIdTransition):
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+ * jit/JITStubs.h:
+ (JSC):
+ ():
+
+2012-01-27 Sheriff Bot <webkit.review.bot@gmail.com>
+
+ Unreviewed, rolling out r106167.
+ http://trac.webkit.org/changeset/106167
+ https://bugs.webkit.org/show_bug.cgi?id=77264
+
+ broke LayoutTests/fast/js/string-capitalization.html
+ (Requested by msaboff on #webkit).
+
+ * runtime/StringPrototype.cpp:
+ (JSC::stringProtoFuncToLowerCase):
+ (JSC::stringProtoFuncToUpperCase):
+ * wtf/text/StringImpl.cpp:
+ (WTF::StringImpl::upper):
+
+2012-01-27 Filip Pizlo <fpizlo@apple.com>
+
+ Build fix for interpreter platforms.
+
+ * interpreter/AbstractPC.cpp:
+ (JSC::AbstractPC::AbstractPC):
+
+2012-01-27 Michael Saboff <msaboff@apple.com>
+
+ StringProtoFuncToUpperCase should call StringImpl::upper similar to StringProtoToLowerCase
+ https://bugs.webkit.org/show_bug.cgi?id=76647
+
+ Reviewed by Geoffrey Garen.
+
+ Changed stringProtoFuncToUpperCase to call StringImpl::upper() is a manor similar
+ to stringProtoFuncToLowerCase(). Fixed StringImpl::upper() to handle the two
+ 8 bit characters that when converted to upper case become 16 bit characters.
+
+ * runtime/StringPrototype.cpp:
+ (JSC::stringProtoFuncToLowerCase): Removed extra trailing whitespace.
+ (JSC::stringProtoFuncToUpperCase):
+ * wtf/text/StringImpl.cpp:
+ (WTF::StringImpl::upper):
+
+2012-01-27 Hajime Morita <morrita@google.com>
+
+ [JSC] ThunkGenerators.cpp should hide its asm-defined symbols
+ https://bugs.webkit.org/show_bug.cgi?id=77244
+
+ Reviewed by Filip Pizlo.
+
+ * jit/ThunkGenerators.cpp: Added HIDE_SYMBOLS()
+ * wtf/InlineASM.h: Moved some duplicated macros from ThunkGenerators.cpp
+
+2012-01-27 Simon Hausmann <simon.hausmann@nokia.com>
+
+ [JSC] Asm-originated symbols should be marked as hidden
+ https://bugs.webkit.org/show_bug.cgi?id=77150
+
+ Reviewed by Filip Pizlo.
+
+ * dfg/DFGOperations.cpp: The HIDE_SYMBOLS macros were present in the CPU(ARM) preprocessor branches,
+ but they were missing in the CPU(X86) and the CPU(X86_64) cases.
+
+2012-01-27 MORITA Hajime <morrita@google.com>
+
+ [JSC] Some JS_EXPORTDATA may not be necessary.
+ https://bugs.webkit.org/show_bug.cgi?id=77145
+
+ Reviewed by Darin Adler.
+
+ Removed JS_EXPORTDATA attributes whose attributing symbols are
+ not exported on Mac port.
+
+ * runtime/ExceptionHelpers.h:
+ (InterruptedExecutionError):
+ * runtime/JSBoundFunction.h:
+ (JSBoundFunction):
+ * runtime/RegExp.h:
+ (RegExp):
+ * runtime/RegExpMatchesArray.h:
+ (RegExpMatchesArray):
+
+2012-01-27 MORITA Hajime <morrita@google.com>
+
+ [WTF] WTFString.h has some extra JS_EXPORT_PRIVATEs
+ https://bugs.webkit.org/show_bug.cgi?id=77113
+
+ Reviewed by Darin Adler.
+
+ * wtf/text/WTFString.h: Removed some WTF_EXPORT_PRIVATE attributes which we don't need to export.
+
+2012-01-27 Zeno Albisser <zeno@webkit.org>
+
+ [Qt][Mac] Build fails after adding ICU support (r105997).
+ https://bugs.webkit.org/show_bug.cgi?id=77118
+
+ Use Apple code path for unicode date formats on mac.
+
+ Reviewed by Tor Arne Vestbø.
+
+ * runtime/DatePrototype.cpp:
+ ():
+
+2012-01-27 Carlos Garcia Campos <cgarcia@igalia.com>
+
+ [GTK] Add a GKeyFile especialization to GOwnPtr
+ https://bugs.webkit.org/show_bug.cgi?id=77191
+
+ Reviewed by Martin Robinson.
+
+ * wtf/gobject/GOwnPtr.cpp:
+ (WTF::GKeyFile): Implement freeOwnedGPtr for GKeyFile.
+ * wtf/gobject/GOwnPtr.h: Add GKeyFile template.
+ * wtf/gobject/GTypedefs.h: Add forward declaration for GKeyFile.
+
+2012-01-25 Yury Semikhatsky <yurys@chromium.org>
+
+ Web Inspector: should be possible to open function declaration from script popover
+ https://bugs.webkit.org/show_bug.cgi?id=76913
+
+ Added display function name and source location to the popover in scripts panel.
+ Now when a function is hovered user can navigate to its definition.
+
+ Reviewed by Pavel Feldman.
+
+ * JavaScriptCore/JavaScriptCore.exp
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
+ * runtime/JSFunction.h:
+ (JSFunction):
+
+2012-01-26 Kevin Ollivier <kevino@theolliviers.com>
+
+ [wx] Unreviewed. Build fix, wx uses the Mac ICU headers so we must match Mac behavior.
+
+ * runtime/DatePrototype.cpp:
+ ():
+
+2012-01-26 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ Merge AllocationSpace into MarkedSpace
+ https://bugs.webkit.org/show_bug.cgi?id=77116
+
+ Reviewed by Geoffrey Garen.
+
+ Merging AllocationSpace and MarkedSpace in preparation for future refactoring/enhancement to
+ MarkedSpace allocation.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.exp:
+ * JavaScriptCore.gypi:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * heap/AllocationSpace.cpp: Removed.
+ * heap/AllocationSpace.h: Removed.
+ * heap/BumpSpace.h:
+ (BumpSpace):
+ * heap/Heap.h:
+ (JSC::Heap::objectSpace):
+ (Heap):
+ ():
+ * heap/HeapBlock.h:
+ ():
+ * heap/MarkedSpace.cpp:
+ (JSC::MarkedSpace::tryAllocateHelper):
+ (JSC):
+ (JSC::MarkedSpace::tryAllocate):
+ (JSC::MarkedSpace::allocateSlowCase):
+ (JSC::MarkedSpace::allocateBlock):
+ (JSC::MarkedSpace::freeBlocks):
+ (TakeIfUnmarked):
+ (JSC::TakeIfUnmarked::TakeIfUnmarked):
+ (JSC::TakeIfUnmarked::operator()):
+ (JSC::TakeIfUnmarked::returnValue):
+ (JSC::MarkedSpace::shrink):
+ (GatherDirtyCells):
+ (JSC::GatherDirtyCells::returnValue):
+ (JSC::GatherDirtyCells::GatherDirtyCells):
+ (JSC::GatherDirtyCells::operator()):
+ (JSC::MarkedSpace::gatherDirtyCells):
+ * heap/MarkedSpace.h:
+ (MarkedSpace):
+ (JSC::MarkedSpace::blocks):
+ (JSC::MarkedSpace::forEachCell):
+ (JSC):
+ (JSC::MarkedSpace::allocate):
+
+2012-01-26 Oliver Hunt <oliver@apple.com>
+
+ MSVC bug fix.
+ <rdar://problem/10703671> MSVC generates bad code for enum compare.
+
+ RS=Geoff
+
+ Make bitfield large enough to work around MSVC's desire to make enums
+ signed types.
+
+ * bytecode/CallLinkInfo.h:
+ (CallLinkInfo):
+
+2012-01-26 Filip Pizlo <fpizlo@apple.com>
+
+ All DFG helpers that may call out to arbitrary JS code must know where they
+ were called from due to inlining and call stack walking
+ https://bugs.webkit.org/show_bug.cgi?id=77070
+ <rdar://problem/10750834>
+
+ Reviewed by Geoff Garen.
+
+ Changed the DFG to always record a code origin index in the tag of the argument
+ count (which we previously left blank for the benefit of LLInt, but is still
+ otherwise unused by the DFG), so that if we ever need to walk the stack accurately
+ we know where to start. In particular, if the current ExecState* points several
+ semantic call frames away from the true semantic call frame because we had
+ performed inlining, having the code origin index recorded means that we can reify
+ those call frames as necessary to give runtime/library code an accurate view of
+ the current JS state.
+
+ This required several large but mechanical changes:
+
+ - Calling a function from the DFG now plants a store32 instruction to store the
+ code origin index. But the indices of code origins were previously picked by
+ the DFG::JITCompiler after code generation completed. I changed this somewhat;
+ even though the code origins are put into the CodeBlock after code gen, the
+ code gen now knows a priori what their indices will be. Extensive assertions
+ are in place to ensure that the two don't get out of sync, in the form of the
+ DFG::CallBeginToken. Note that this mechanism has almost no effect on JS calls;
+ those don't need the code origin index set in the call frame because we can get
+ it by doing a binary search on the return PC.
+
+ - Stack walking now always calls trueCallFrame() first before beginning the walk,
+ since even the top call frame may be wrong. It still calls trueCallerFrame() as
+ before to get to the next frame, though trueCallerFrame() is now mostly a
+ wrapper around callerFrame()->trueCallFrame().
+
+ - Because the mechanism for getting the code origin of a call frame is bimodal
+ (either the call frame knows its code origin because the code origin index was
+ set, or it's necessary to use the callee frame's return PC), I put in extra
+ mechanisms to determine whether your caller, or your callee, corresponds to
+ a call out of C++ code. Previously we just had the host call flag, but this is
+ insufficient as it does not cover the case of someone calling JSC::call(). But
+ luckily we can determine this just by looking at the return PC: if the return
+ PC is in range of the ctiTrampiline, then two things are true: this call
+ frame's PC will tell you nothing about where you came from in your caller, and
+ the caller already knows where it's at because it must have set the code origin
+ index (unless it's not DFG code, in which case we don't care because there is
+ no inlining to worry about).
+
+ - During testing this revealed a simple off-by-one goof in DFG::ByteCodeParser's
+ inlining code, so I fixed it.
+
+ - Finally because I was tired of doing random #if's for checking if I should be
+ passing around an Instruction* or a ReturnAddressPtr, I created a class called
+ AbstractPC that holds whatever notion of a PC is appropriate for the current
+ execution environment. It's designed to work gracefully even if both the
+ interpreter and the JIT are compiled in, and should integrate nicely with the
+ LLInt.
+
+ This is neutral on all benchmarks and fixes some nasty corner-case regressions of
+ evil code that uses combinations of getters/setters and function.arguments.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.exp:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::codeOrigin):
+ (CodeBlock):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleInlining):
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::link):
+ * dfg/DFGJITCompiler.h:
+ (CallBeginToken):
+ (JSC::DFG::CallBeginToken::CallBeginToken):
+ (JSC::DFG::CallBeginToken::assertCodeOriginIndex):
+ (JSC::DFG::CallBeginToken::assertNoCodeOriginIndex):
+ (DFG):
+ (JSC::DFG::CallExceptionRecord::CallExceptionRecord):
+ (CallExceptionRecord):
+ (JSC::DFG::JITCompiler::JITCompiler):
+ (JITCompiler):
+ (JSC::DFG::JITCompiler::nextCallBeginToken):
+ (JSC::DFG::JITCompiler::beginCall):
+ (JSC::DFG::JITCompiler::notifyCall):
+ (JSC::DFG::JITCompiler::addExceptionCheck):
+ (JSC::DFG::JITCompiler::addFastExceptionCheck):
+ * dfg/DFGOperations.cpp:
+ ():
+ * dfg/DFGRepatch.cpp:
+ (JSC::DFG::tryBuildGetByIDList):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::appendCallWithExceptionCheck):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::emitCall):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::emitCall):
+ * interpreter/AbstractPC.cpp: Added.
+ (JSC):
+ (JSC::AbstractPC::AbstractPC):
+ * interpreter/AbstractPC.h: Added.
+ (JSC):
+ (AbstractPC):
+ (JSC::AbstractPC::AbstractPC):
+ (JSC::AbstractPC::hasJITReturnAddress):
+ (JSC::AbstractPC::jitReturnAddress):
+ (JSC::AbstractPC::hasInterpreterReturnAddress):
+ (JSC::AbstractPC::interpreterReturnAddress):
+ (JSC::AbstractPC::isSet):
+ (JSC::AbstractPC::operator!):
+ ():
+ * interpreter/CallFrame.cpp:
+ (JSC):
+ (JSC::CallFrame::trueCallFrame):
+ (JSC::CallFrame::trueCallerFrame):
+ * interpreter/CallFrame.h:
+ (JSC::ExecState::abstractReturnPC):
+ (JSC::ExecState::codeOriginIndexForDFGWithInlining):
+ (ExecState):
+ (JSC::ExecState::trueCallFrame):
+ (JSC::ExecState::trueCallFrameFromVMCode):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::retrieveArgumentsFromVMCode):
+ (JSC::Interpreter::retrieveCallerFromVMCode):
+ (JSC::Interpreter::findFunctionCallFrameFromVMCode):
+ * interpreter/Interpreter.h:
+ (Interpreter):
+ ():
+ * jit/JITStubs.cpp:
+ (JSC):
+ ():
+ * jit/JITStubs.h:
+ (JSC):
+ (JSC::returnAddressIsInCtiTrampoline):
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::argumentsGetter):
+ (JSC::JSFunction::callerGetter):
+ (JSC::JSFunction::getOwnPropertyDescriptor):
+
+2012-01-26 Peter Varga <pvarga@webkit.org>
+
+ Fix build when VERBOSE_SPECULATION_FAILURE is enabled in DFG
+ https://bugs.webkit.org/show_bug.cgi?id=77104
+
+ Reviewed by Filip Pizlo.
+
+ * dfg/DFGOperations.cpp:
+ ():
+
+2012-01-26 Michael Saboff <msaboff@apple.com>
+
+ String::latin1() should take advantage of 8 bit strings
+ https://bugs.webkit.org/show_bug.cgi?id=76646
+
+ Reviewed by Geoffrey Garen.
+
+ * wtf/text/WTFString.cpp:
+ (WTF::String::latin1): For 8 bit strings, use existing buffer
+ without conversion.
+
+2012-01-26 Michael Saboff <msaboff@apple.com>
+
+ Dromaeo tests usage of StringImpl find routines cause 8->16 bit conversions
+ https://bugs.webkit.org/show_bug.cgi?id=76645
+
+ Reviewed by Geoffrey Garen.
+
+ * wtf/text/StringImpl.cpp:
+ (WTF::equalIgnoringCase): New LChar version.
+ (WTF::findInner): New helper function.
+ (WTF::StringImpl::find): Added 8 bit path.
+ (WTF::reverseFindInner): New helper funciton.
+ (WTF::StringImpl::reverseFind): Added 8 bit path.
+ (WTF::StringImpl::reverseFindIgnoringCase): Added 8 bit path.
+ * wtf/text/StringImpl.h:
+ (WTF):
+
+2012-01-26 Csaba Osztrogonác <ossy@webkit.org>
+
+ [Qt][Win] One more speculative buildfix after r105970.
+
+ * JavaScriptCore.pri:
+
+2012-01-26 Csaba Osztrogonác <ossy@webkit.org>
+
+ [Qt][Win] Speculative buildfix after r105970.
+
+ * JavaScriptCore.pri: Link lgdi for DeleteObject() and DeleteDC().
+
+2012-01-26 Sheriff Bot <webkit.review.bot@gmail.com>
+
+ Unreviewed, rolling out r105982.
+ http://trac.webkit.org/changeset/105982
+ https://bugs.webkit.org/show_bug.cgi?id=77090
+
+ breaks the world (Requested by WildFox on #webkit).
+
+ * wtf/MainThread.cpp:
+ (WTF):
+ * wtf/Platform.h:
+ * wtf/mac/MainThreadMac.mm:
+ (WTF):
+ (WTF::registerGCThread):
+ (WTF::isMainThreadOrGCThread):
+
+2012-01-26 Roland Takacs <takacs.roland@stud.u-szeged.hu>
+
+ [Qt] GC should be parallel on Qt platform
+ https://bugs.webkit.org/show_bug.cgi?id=73309
+
+ Reviewed by Zoltan Herczeg.
+
+ These changes made the parallel gc feature available for Qt port.
+ The implementation of "registerGCThread" and "isMainThreadOrGCThread"
+ is moved from MainThreadMac.mm to the common MainThread.cpp to make
+ them available for other platforms.
+
+ Measurement results:
+ V8 speed-up: 1.071x as fast [From: 746.1ms To: 696.4ms ]
+ WindScorpion speed-up: 1.082x as fast [From: 3490.4ms To: 3226.7ms]
+ V8 Splay speed-up: 1.158x as fast [From: 145.8ms To: 125.9ms ]
+
+ Tested on Intel(R) Core(TM) i5-2320 CPU @ 3.00GHz with 4-core.
+
+ * wtf/MainThread.cpp:
+ (WTF):
+ (WTF::registerGCThread):
+ (WTF::isMainThreadOrGCThread):
+ * wtf/Platform.h:
+ * wtf/mac/MainThreadMac.mm:
+
+2012-01-26 Andy Estes <aestes@apple.com>
+
+ REGRESSION (r105555): Incorrect use of OS() macro breaks OwnPtr when used with Win32 data types
+ https://bugs.webkit.org/show_bug.cgi?id=77073
+
+ Reviewed by Ryosuke Niwa.
+
+ r105555 changed PLATFORM(WIN) to OS(WIN), but WTF_OS_WIN isn't defined.
+ This should have been changed to OS(WINDOWS). This causes the
+ preprocessor to strip out Win32 data type overrides for deleteOwnedPtr,
+ causing allocations made by Win32 to be deleted by fastmalloc.
+
+ * wtf/OwnPtrCommon.h:
+ (WTF): Use OS(WINDOWS) instead of OS(WIN).
+
+2012-01-25 Mark Rowe <mrowe@apple.com>
+
+ Attempted Mac build fix after r105939.
+
+ * runtime/DatePrototype.cpp: Don't #include unicode/udat.h on Mac or iOS.
+ It isn't used on these platforms and isn't available in the ICU headers
+ for Mac.
+
+2012-01-25 Mark Rowe <mrowe@apple.com>
+
+ Build in to an alternate location when USE_STAGING_INSTALL_PATH is set.
+
+ <rdar://problem/10609417> Adopt USE_STAGING_INSTALL_PATH
+
+ Reviewed by David Kilzer.
+
+ * Configurations/Base.xcconfig: Define NORMAL_JAVASCRIPTCORE_FRAMEWORKS_DIR, which contains
+ the path where JavaScriptCore is normally installed. Update JAVASCRIPTCORE_FRAMEWORKS_DIR
+ to point to the staged frameworks directory when USE_STAGING_INSTALL_PATH is set.
+ * Configurations/JavaScriptCore.xcconfig: Always set the framework's install name based on
+ the normal framework location. This prevents an incorrect install name from being used when
+ installing in to the staged frameworks directory.
+
+2012-01-25 Eli Fidler <efidler@rim.com>
+
+ Implement Date.toLocaleString() using ICU
+ https://bugs.webkit.org/show_bug.cgi?id=76714
+
+ Reviewed by Darin Adler.
+
+ * runtime/DatePrototype.cpp:
+ (JSC::formatLocaleDate):
+
+2012-01-25 Hajime Morita <morrita@google.com>
+
+ ENABLE_SHADOW_DOM should be available via build-webkit --shadow-dom
+ https://bugs.webkit.org/show_bug.cgi?id=76863
+
+ Reviewed by Dimitri Glazkov.
+
+ Added a feature flag.
+
+ * Configurations/FeatureDefines.xcconfig:
+
+2012-01-25 Yong Li <yoli@rim.com>
+
+ [BlackBerry] Implement OSAllocator::commit/decommit.
+ BlackBerry port should support virtual memory decommiting.
+ https://bugs.webkit.org/show_bug.cgi?id=77013
+
+ Reviewed by Rob Buis.
+
+ * wtf/OSAllocatorPosix.cpp:
+ (WTF::OSAllocator::reserveUncommitted):
+ (WTF::OSAllocator::commit):
+ (WTF::OSAllocator::decommit):
+ * wtf/Platform.h:
+
+2012-01-24 Oliver Hunt <oliver@apple.com>
+
+ Make DFG update topCallFrame
+ https://bugs.webkit.org/show_bug.cgi?id=76969
+
+ Reviewed by Filip Pizlo.
+
+ Add NativeCallFrameTracer to manage topCallFrame assignment
+ in the DFG operations, and make use of it.
+
+ * dfg/DFGOperations.cpp:
+ (JSC::DFG::operationPutByValInternal):
+ ():
+ * interpreter/Interpreter.h:
+ (JSC):
+ (NativeCallFrameTracer):
+ (JSC::NativeCallFrameTracer::NativeCallFrameTracer):
+
+2012-01-24 Filip Pizlo <fpizlo@apple.com>
+
+ Inlining breaks call frame walking when the walking is done from outside the inlinee,
+ but inside a code block that had inlining
+ https://bugs.webkit.org/show_bug.cgi?id=76978
+ <rdar://problem/10720904>
+
+ Reviewed by Oliver Hunt.
+
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::codeOriginForReturn):
+ * interpreter/CallFrame.cpp:
+ (JSC::CallFrame::trueCallerFrame):
+
+2012-01-24 Gavin Barraclough <barraclough@apple.com>
+
+ https://bugs.webkit.org/show_bug.cgi?id=76855
+ Implement a JIT-code aware sampling profiler for JSC
+
+ Reviewed by Oliver Hunt.
+
+ Add support to MetaAllocator.cpp to track all live handles in a map,
+ allowing lookup based on any address within the allocation.
+
+ * wtf/MetaAllocator.cpp:
+ (WTF::MetaAllocatorTracker::notify):
+ (WTF::MetaAllocatorTracker::release):
+ - Track live handle objects in a map.
+ (WTF::MetaAllocator::release):
+ - Removed support for handles with null m_allocator (no longer used).
+ - Notify the tracker of handles being released.
+ (WTF::MetaAllocatorHandle::~MetaAllocatorHandle):
+ - Moved functionality out into MetaAllocator::release.
+ (WTF::MetaAllocatorHandle::shrink):
+ - Removed support for handles with null m_allocator (no longer used).
+ (WTF::MetaAllocator::MetaAllocator):
+ - Initialize m_tracker.
+ (WTF::MetaAllocator::allocate):
+ - Notify the tracker of new allocations.
+ * wtf/MetaAllocator.h:
+ (WTF::MetaAllocatorTracker::find):
+ - Lookup a MetaAllocatorHandle based on an address inside the allocation.
+ (WTF::MetaAllocator::trackAllocations):
+ - Register a callback object to track allocation state.
+ * wtf/MetaAllocatorHandle.h:
+ - Remove unused createSelfManagedHandle/constructor.
+ (WTF::MetaAllocatorHandle::key):
+ - Added, for use in RedBlackTree.
+
+2012-01-24 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ Use copying collector for out-of-line JSObject property storage
+ https://bugs.webkit.org/show_bug.cgi?id=76665
+
+ Reviewed by Geoffrey Garen.
+
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::visitChildren): Changed to use copyAndAppend whenever the property storage is out-of-line.
+ Also added a temporary variable to avoid warnings from GCC.
+ (JSC::JSObject::allocatePropertyStorage): Changed to use tryAllocateStorage/tryReallocateStorage as opposed to
+ operator new. Also added a temporary variable to avoid warnings from GCC.
+ * runtime/JSObject.h:
+
+2012-01-24 Geoffrey Garen <ggaren@apple.com>
+
+ JSValue::toString() should return a JSString* instead of a UString
+ https://bugs.webkit.org/show_bug.cgi?id=76861
+
+ Fixed two failing layout tests after my last patch.
+
+ Reviewed by Gavin Barraclough.
+
+ * runtime/ArrayPrototype.cpp:
+ (JSC::arrayProtoFuncSort): Call value() after calling toString(), as
+ in all other cases.
+
+ I missed this case because the JSString* type has a valid operator<,
+ so the compiler didn't complain.
+
+2012-01-24 Kenichi Ishibashi <bashi@chromium.org>
+
+ [V8] Add Uint8ClampedArray support
+ https://bugs.webkit.org/show_bug.cgi?id=76803
+
+ Reviewed by Kenneth Russell.
+
+ * wtf/ArrayBufferView.h:
+ (WTF::ArrayBufferView::isUnsignedByteClampedArray): Added.
+ * wtf/Uint8ClampedArray.h:
+ (WTF::Uint8ClampedArray::isUnsignedByteClampedArray): Overridden to return true.
+
+2012-01-23 Carlos Garcia Campos <cgarcia@igalia.com>
+
+ [GTK] Add WebKitDownload to WebKit2 GTK+ API
+ https://bugs.webkit.org/show_bug.cgi?id=72949
+
+ Reviewed by Martin Robinson.
+
+ * wtf/gobject/GOwnPtr.cpp:
+ (WTF::GTimer): Use g_timer_destroy() to free a GTimer.
+ * wtf/gobject/GOwnPtr.h: Add GTimer template.
+ * wtf/gobject/GTypedefs.h: Add GTimer forward declaration.
+
+2012-01-24 Ilya Tikhonovsky <loislo@chromium.org>
+
+ Unreviewed build fix for Qt LinuxSH4 build after r105698.
+
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+
+2012-01-23 Geoffrey Garen <ggaren@apple.com>
+
+ JSValue::toString() should return a JSString* instead of a UString
+ https://bugs.webkit.org/show_bug.cgi?id=76861
+
+ Reviewed by Gavin Barraclough.
+
+ This makes the common case -- toString() on a string -- faster and
+ inline-able. (Not a measureable speedup, but we can now remove a bunch
+ of duplicate hand-rolled code for this optimization.)
+
+ This also clarifies the boundary between "C++ strings" and "JS strings".
+
+ In all cases other than true, false, null, undefined, and multi-digit
+ numbers, the JS runtime was just retrieving a UString from a JSString,
+ so returning a JSString* is strictly better. In the other cases, we can
+ optimize to avoid creating a new JSString if we care to, but it doesn't
+ seem to be a big deal.
+
+ * JavaScriptCore.exp: Export!
+
+ * jsc.cpp:
+ (functionPrint):
+ (functionDebug):
+ (functionRun):
+ (functionLoad):
+ (functionCheckSyntax):
+ (runWithScripts):
+ (runInteractive):
+ * API/JSValueRef.cpp:
+ (JSValueToStringCopy):
+ * bytecode/CodeBlock.cpp:
+ (JSC::valueToSourceString): Call value() after calling toString(), to
+ convert from "JS string" (JSString*) to "C++ string" (UString), since
+ toString() no longer returns a "C++ string".
+
+ * dfg/DFGOperations.cpp:
+ (JSC::DFG::operationValueAddNotNumber):
+ * jit/JITStubs.cpp:
+ (op_add): Updated for removal of toPrimitiveString():
+ all '+' operands can use toString(), except for object operands, which
+ need to take a slow path to call toPrimitive().
+
+ * runtime/ArrayPrototype.cpp:
+ (JSC::arrayProtoFuncToString):
+ (JSC::arrayProtoFuncToLocaleString):
+ (JSC::arrayProtoFuncJoin):
+ (JSC::arrayProtoFuncPush):
+ * runtime/CommonSlowPaths.h:
+ (JSC::CommonSlowPaths::opIn):
+ * runtime/DateConstructor.cpp:
+ (JSC::dateParse):
+ * runtime/DatePrototype.cpp:
+ (JSC::formatLocaleDate): Call value() after calling toString(), as above.
+
+ * runtime/ErrorInstance.h:
+ (JSC::ErrorInstance::create): Simplified down to one canonical create()
+ function, to make string handling easier.
+
+ * runtime/ErrorPrototype.cpp:
+ (JSC::errorProtoFuncToString):
+ * runtime/ExceptionHelpers.cpp:
+ (JSC::createInvalidParamError):
+ (JSC::createNotAConstructorError):
+ (JSC::createNotAFunctionError):
+ (JSC::createNotAnObjectError):
+ * runtime/FunctionConstructor.cpp:
+ (JSC::constructFunctionSkippingEvalEnabledCheck):
+ * runtime/FunctionPrototype.cpp:
+ (JSC::functionProtoFuncBind):
+ * runtime/JSArray.cpp:
+ (JSC::JSArray::sort): Call value() after calling toString(), as above.
+
+ * runtime/JSCell.cpp:
+ * runtime/JSCell.h: Removed JSCell::toString() because JSValue does this
+ job now. Doing it in JSCell is slower (requires extra type checking), and
+ creates the misimpression that language-defined toString() behavior is
+ an implementation detail of JSCell.
+
+ * runtime/JSGlobalObjectFunctions.cpp:
+ (JSC::encode):
+ (JSC::decode):
+ (JSC::globalFuncEval):
+ (JSC::globalFuncParseInt):
+ (JSC::globalFuncParseFloat):
+ (JSC::globalFuncEscape):
+ (JSC::globalFuncUnescape): Call value() after calling toString(), as above.
+
+ * runtime/JSONObject.cpp:
+ (JSC::unwrapBoxedPrimitive):
+ (JSC::Stringifier::Stringifier):
+ (JSC::JSONProtoFuncParse): Removed some manual optimization that toString()
+ takes care of.
+
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::toString):
+ * runtime/JSObject.h: Updated to return JSString*.
+
+ * runtime/JSString.cpp:
+ * runtime/JSString.h:
+ (JSC::JSValue::toString): Removed, since I removed JSCell::toString().
+
+ * runtime/JSValue.cpp:
+ (JSC::JSValue::toStringSlowCase): Removed toPrimitiveString(), and re-
+ spawned toStringSlowCase() from its zombie corpse, since toPrimitiveString()
+ basically did what we want all the time. (Note that the toPrimitive()
+ preference changes from NoPreference to PreferString, because that's
+ how ToString is defined in the language. op_add does not want this behavior.)
+
+ * runtime/NumberPrototype.cpp:
+ (JSC::numberProtoFuncToString):
+ (JSC::numberProtoFuncToLocaleString): A little simpler, now that toString()
+ returns a JSString*.
+
+ * runtime/ObjectConstructor.cpp:
+ (JSC::objectConstructorGetOwnPropertyDescriptor):
+ (JSC::objectConstructorDefineProperty):
+ * runtime/ObjectPrototype.cpp:
+ (JSC::objectProtoFuncHasOwnProperty):
+ (JSC::objectProtoFuncDefineGetter):
+ (JSC::objectProtoFuncDefineSetter):
+ (JSC::objectProtoFuncLookupGetter):
+ (JSC::objectProtoFuncLookupSetter):
+ (JSC::objectProtoFuncPropertyIsEnumerable): More calls to value(), as above.
+
+ * runtime/Operations.cpp:
+ (JSC::jsAddSlowCase): Need to check for object before taking the toString()
+ fast path becuase adding an object to a string requires calling toPrimitive()
+ on the object, not toString(). (They differ in their preferred conversion
+ type.)
+
+ * runtime/Operations.h:
+ (JSC::jsString):
+ (JSC::jsStringFromArguments): This code gets simpler, now that toString()
+ does the right thing.
+
+ (JSC::jsAdd): Now checks for object, just like jsAddSlowCase().
+
+ * runtime/RegExpConstructor.cpp:
+ (JSC::setRegExpConstructorInput):
+ (JSC::constructRegExp):
+ * runtime/RegExpObject.cpp:
+ (JSC::RegExpObject::match):
+ * runtime/RegExpPrototype.cpp:
+ (JSC::regExpProtoFuncCompile):
+ (JSC::regExpProtoFuncToString): More calls to value(), as above.
+
+ * runtime/StringConstructor.cpp:
+ (JSC::constructWithStringConstructor):
+ (JSC::callStringConstructor): This code gets simpler, now that toString()
+ does the right thing.
+
+ * runtime/StringPrototype.cpp:
+ (JSC::replaceUsingRegExpSearch):
+ (JSC::replaceUsingStringSearch):
+ (JSC::stringProtoFuncReplace):
+ (JSC::stringProtoFuncCharAt):
+ (JSC::stringProtoFuncCharCodeAt):
+ (JSC::stringProtoFuncConcat):
+ (JSC::stringProtoFuncIndexOf):
+ (JSC::stringProtoFuncLastIndexOf):
+ (JSC::stringProtoFuncMatch):
+ (JSC::stringProtoFuncSearch):
+ (JSC::stringProtoFuncSlice):
+ (JSC::stringProtoFuncSplit):
+ (JSC::stringProtoFuncSubstr):
+ (JSC::stringProtoFuncSubstring):
+ (JSC::stringProtoFuncToLowerCase):
+ (JSC::stringProtoFuncToUpperCase):
+ (JSC::stringProtoFuncLocaleCompare):
+ (JSC::stringProtoFuncBig):
+ (JSC::stringProtoFuncSmall):
+ (JSC::stringProtoFuncBlink):
+ (JSC::stringProtoFuncBold):
+ (JSC::stringProtoFuncFixed):
+ (JSC::stringProtoFuncItalics):
+ (JSC::stringProtoFuncStrike):
+ (JSC::stringProtoFuncSub):
+ (JSC::stringProtoFuncSup):
+ (JSC::stringProtoFuncFontcolor):
+ (JSC::stringProtoFuncFontsize):
+ (JSC::stringProtoFuncAnchor):
+ (JSC::stringProtoFuncLink):
+ (JSC::trimString): Some of this code gets simpler, now that toString()
+ does the right thing. More calls to value(), as above.
+
+2012-01-23 Luke Macpherson <macpherson@chromium.org>
+
+ Unreviewed, rolling out r105676.
+ http://trac.webkit.org/changeset/105676
+ https://bugs.webkit.org/show_bug.cgi?id=76665
+
+ Breaks build on max due to compile warnings.
+
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::finalize):
+ (JSC::JSObject::visitChildren):
+ (JSC::JSObject::allocatePropertyStorage):
+ * runtime/JSObject.h:
+
+2012-01-23 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ Use copying collector for out-of-line JSObject property storage
+ https://bugs.webkit.org/show_bug.cgi?id=76665
+
+ Reviewed by Geoffrey Garen.
+
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::visitChildren): Changed to use copyAndAppend whenever the property storage is out-of-line.
+ (JSC::JSObject::allocatePropertyStorage): Changed to use tryAllocateStorage/tryReallocateStorage as opposed to
+ operator new.
+ * runtime/JSObject.h:
+
+2012-01-23 Brian Weinstein <bweinstein@apple.com>
+
+ More build fixing after r105646.
+
+ * JavaScriptCore.exp:
+
+2012-01-23 Gavin Barraclough <barraclough@apple.com>
+
+ https://bugs.webkit.org/show_bug.cgi?id=76855
+ Implement a JIT-code aware sampling profiler for JSC
+
+ Reviewed by Geoff Garen.
+
+ Step 2: generalize RedBlackTree. The profiler is going to want tio use
+ a RedBlackTree, allow this class to work with subclasses of
+ RedBlackTree::Node, Node should not need to know the names of the m_key
+ and m_value fields (the subclass can provide a key() accessor), and
+ RedBlackTree does not need to know anything about ValueType.
+
+ * JavaScriptCore.exp:
+ * wtf/MetaAllocator.cpp:
+ (WTF::MetaAllocator::findAndRemoveFreeSpace):
+ (WTF::MetaAllocator::debugFreeSpaceSize):
+ (WTF::MetaAllocator::addFreeSpace):
+ * wtf/MetaAllocator.h:
+ (WTF::MetaAllocator::FreeSpaceNode::FreeSpaceNode):
+ (WTF::MetaAllocator::FreeSpaceNode::key):
+ * wtf/MetaAllocatorHandle.h:
+ (WTF::MetaAllocatorHandle::key):
+ * wtf/RedBlackTree.h:
+ (WTF::RedBlackTree::Node::successor):
+ (WTF::RedBlackTree::Node::predecessor):
+ (WTF::RedBlackTree::Node::parent):
+ (WTF::RedBlackTree::Node::setParent):
+ (WTF::RedBlackTree::Node::left):
+ (WTF::RedBlackTree::Node::setLeft):
+ (WTF::RedBlackTree::Node::right):
+ (WTF::RedBlackTree::Node::setRight):
+ (WTF::RedBlackTree::insert):
+ (WTF::RedBlackTree::remove):
+ (WTF::RedBlackTree::findExact):
+ (WTF::RedBlackTree::findLeastGreaterThanOrEqual):
+ (WTF::RedBlackTree::findGreatestLessThanOrEqual):
+ (WTF::RedBlackTree::first):
+ (WTF::RedBlackTree::last):
+ (WTF::RedBlackTree::size):
+ (WTF::RedBlackTree::treeMinimum):
+ (WTF::RedBlackTree::treeMaximum):
+ (WTF::RedBlackTree::treeInsert):
+ (WTF::RedBlackTree::leftRotate):
+ (WTF::RedBlackTree::rightRotate):
+ (WTF::RedBlackTree::removeFixup):
+
+2012-01-23 Andy Estes <aestes@apple.com>
+
+ Fix the build after r105635.
+
+ * JavaScriptCore.exp:
+
+2012-01-23 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ Remove StackBounds from JSGlobalData
+ https://bugs.webkit.org/show_bug.cgi?id=76310
+
+ Reviewed by Sam Weinig.
+
+ Removed StackBounds and the stack() function from JSGlobalData since it no
+ longer accessed any members of JSGlobalData.
+
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::BytecodeGenerator):
+ * heap/MachineStackMarker.cpp:
+ (JSC::MachineThreads::addCurrentThread):
+ (JSC::MachineThreads::gatherFromCurrentThread):
+ * parser/Parser.cpp:
+ (JSC::::Parser):
+ * runtime/JSGlobalData.cpp:
+ (JSC::JSGlobalData::JSGlobalData):
+ * runtime/JSGlobalData.h:
+
+2012-01-23 Gavin Barraclough <barraclough@apple.com>
+
+ Implement a JIT-code aware sampling profiler for JSC
+ https://bugs.webkit.org/show_bug.cgi?id=76855
+
+ Rubber stanmped by Geoff Garen.
+
+ Mechanical change - pass CodeBlock through to the executable allocator,
+ such that we will be able to map ranges of JIT code back to their owner.
+
+ * assembler/ARMAssembler.cpp:
+ (JSC::ARMAssembler::executableCopy):
+ * assembler/ARMAssembler.h:
+ * assembler/AssemblerBuffer.h:
+ (JSC::AssemblerBuffer::executableCopy):
+ * assembler/AssemblerBufferWithConstantPool.h:
+ (JSC::AssemblerBufferWithConstantPool::executableCopy):
+ * assembler/LinkBuffer.h:
+ (JSC::LinkBuffer::LinkBuffer):
+ (JSC::LinkBuffer::linkCode):
+ * assembler/MIPSAssembler.h:
+ (JSC::MIPSAssembler::executableCopy):
+ * assembler/SH4Assembler.h:
+ (JSC::SH4Assembler::executableCopy):
+ * assembler/X86Assembler.h:
+ (JSC::X86Assembler::executableCopy):
+ (JSC::X86Assembler::X86InstructionFormatter::executableCopy):
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::compile):
+ (JSC::DFG::JITCompiler::compileFunction):
+ * dfg/DFGOSRExitCompiler.cpp:
+ * dfg/DFGRepatch.cpp:
+ (JSC::DFG::generateProtoChainAccessStub):
+ (JSC::DFG::tryCacheGetByID):
+ (JSC::DFG::tryBuildGetByIDList):
+ (JSC::DFG::tryCachePutByID):
+ * dfg/DFGThunks.cpp:
+ (JSC::DFG::osrExitGenerationThunkGenerator):
+ * jit/ExecutableAllocator.cpp:
+ (JSC::ExecutableAllocator::allocate):
+ * jit/ExecutableAllocator.h:
+ * jit/ExecutableAllocatorFixedVMPool.cpp:
+ (JSC::ExecutableAllocator::allocate):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompile):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::privateCompileCTIMachineTrampolines):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::privateCompileCTIMachineTrampolines):
+ (JSC::JIT::privateCompileCTINativeCall):
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::stringGetByValStubGenerator):
+ (JSC::JIT::privateCompilePutByIdTransition):
+ (JSC::JIT::privateCompilePatchGetArrayLength):
+ (JSC::JIT::privateCompileGetByIdProto):
+ (JSC::JIT::privateCompileGetByIdSelfList):
+ (JSC::JIT::privateCompileGetByIdProtoList):
+ (JSC::JIT::privateCompileGetByIdChainList):
+ (JSC::JIT::privateCompileGetByIdChain):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::stringGetByValStubGenerator):
+ (JSC::JIT::privateCompilePutByIdTransition):
+ (JSC::JIT::privateCompilePatchGetArrayLength):
+ (JSC::JIT::privateCompileGetByIdProto):
+ (JSC::JIT::privateCompileGetByIdSelfList):
+ (JSC::JIT::privateCompileGetByIdProtoList):
+ (JSC::JIT::privateCompileGetByIdChainList):
+ (JSC::JIT::privateCompileGetByIdChain):
+ * jit/JITStubs.cpp:
+ * jit/SpecializedThunkJIT.h:
+ (JSC::SpecializedThunkJIT::finalize):
+ * yarr/YarrJIT.cpp:
+ (JSC::Yarr::YarrGenerator::compile):
+
+2012-01-23 Xianzhu Wang <wangxianzhu@chromium.org>
+
+ Basic enhancements to StringBuilder
+ https://bugs.webkit.org/show_bug.cgi?id=67081
+
+ This change contains the following enhancements to StringBuilder,
+ for convenience, performance, testability, etc.:
+ - Change toStringPreserveCapacity() to const
+ - new public methods: capacity(), swap(), toAtomicString(), canShrink()
+ and append(const StringBuilder&)
+ - == and != opearators to compare StringBuilders and a StringBuilder/String
+
+ Unit tests: Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp
+
+ Reviewed by Darin Adler.
+
+ * JavaScriptCore.exp:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
+ * wtf/text/AtomicString.cpp:
+ (WTF::SubstringTranslator::hash):
+ (WTF::SubstringTranslator::equal):
+ (WTF::SubstringTranslator::translate):
+ (WTF::AtomicString::add):
+ (WTF::AtomicString::addSlowCase):
+ * wtf/text/AtomicString.h:
+ (WTF::AtomicString::AtomicString):
+ (WTF::AtomicString::add):
+ * wtf/text/StringBuilder.cpp:
+ (WTF::StringBuilder::reifyString):
+ (WTF::StringBuilder::resize):
+ (WTF::StringBuilder::canShrink):
+ (WTF::StringBuilder::shrinkToFit):
+ * wtf/text/StringBuilder.h:
+ (WTF::StringBuilder::append):
+ (WTF::StringBuilder::toString):
+ (WTF::StringBuilder::toStringPreserveCapacity):
+ (WTF::StringBuilder::toAtomicString):
+ (WTF::StringBuilder::isEmpty):
+ (WTF::StringBuilder::capacity):
+ (WTF::StringBuilder::is8Bit):
+ (WTF::StringBuilder::swap):
+ (WTF::equal):
+ (WTF::operator==):
+ (WTF::operator!=):
+ * wtf/text/StringImpl.h:
+
+2012-01-23 Carlos Garcia Campos <cgarcia@igalia.com>
+
+ Unreviewed. Fix make distcheck.
+
+ * GNUmakefile.list.am: Add missing files, remove deleted files and
+ fix indentation.
+
+2012-01-22 Filip Pizlo <fpizlo@apple.com>
+
+ Build fix for non-DFG platforms that error out on warn-unused-parameter.
+
+ * bytecode/CallLinkStatus.cpp:
+ (JSC::CallLinkStatus::computeFor):
+ * bytecode/GetByIdStatus.cpp:
+ (JSC::GetByIdStatus::computeFor):
+ * bytecode/MethodCallLinkStatus.cpp:
+ (JSC::MethodCallLinkStatus::computeFor):
+ * bytecode/PutByIdStatus.cpp:
+ (JSC::PutByIdStatus::computeFor):
+
+2012-01-22 Filip Pizlo <fpizlo@apple.com>
+
+ Build fix for non-DFG platforms.
+
+ * bytecode/CallLinkStatus.cpp:
+ (JSC::CallLinkStatus::computeFor):
+ * bytecode/GetByIdStatus.cpp:
+ (JSC::GetByIdStatus::computeFor):
+ * bytecode/MethodCallLinkStatus.cpp:
+ (JSC::MethodCallLinkStatus::computeFor):
+ * bytecode/PutByIdStatus.cpp:
+ (JSC::PutByIdStatus::computeFor):
+
+2012-01-20 Filip Pizlo <fpizlo@apple.com>
+
+ DFG should not have code that directly decodes the states of old JIT inline
+ cache data structures
+ https://bugs.webkit.org/show_bug.cgi?id=76768
+
+ Reviewed by Sam Weinig.
+
+ Introduced new classes (like GetByIdStatus) that encapsulate the set of things
+ that the DFG would like to know about property accesses and calls. Whereas it
+ previously got this information by directly decoding the data structures used
+ by the old JIT for inline caching, it now uses these classes, which do the work
+ for it. This should make it somewhat more straight forward to introduce new
+ ways of profiling the same information.
+
+ Also hoisted StructureSet into bytecode/ from dfg/, because it's now used by
+ code in bytecode/.
+
+ Making this work right involved carefully ensuring that the heuristics for
+ choosing how to handle property accesses was at least as good as what we had
+ before, since I completely restructured that code. Currently the performance
+ looks neutral. Since I rewrote the code I did change some things that I never
+ liked before, like previously if a put_bu_id had executed exactly once then
+ we'd compile it as if it had taken slow-path. Executing once is special because
+ then the inline cache is not baked in, so there is no information about how the
+ DFG should optimize the code. Now this is rationalized: if the put_by_id does
+ not offer enough information to be optimized (i.e. had executed 0 or 1 times)
+ then we turn it into a forced OSR exit (i.e. a patch point). However, get_by_id
+ still has the old behavior; I left it that way because I didn't want to make
+ too many changes at once.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * bytecode/CallLinkStatus.cpp: Added.
+ (JSC::CallLinkStatus::computeFor):
+ * bytecode/CallLinkStatus.h: Added.
+ (JSC::CallLinkStatus::CallLinkStatus):
+ (JSC::CallLinkStatus::isSet):
+ (JSC::CallLinkStatus::operator!):
+ (JSC::CallLinkStatus::couldTakeSlowPath):
+ (JSC::CallLinkStatus::callTarget):
+ * bytecode/GetByIdStatus.cpp: Added.
+ (JSC::GetByIdStatus::computeFor):
+ * bytecode/GetByIdStatus.h: Added.
+ (JSC::GetByIdStatus::GetByIdStatus):
+ (JSC::GetByIdStatus::state):
+ (JSC::GetByIdStatus::isSet):
+ (JSC::GetByIdStatus::operator!):
+ (JSC::GetByIdStatus::isSimpleDirect):
+ (JSC::GetByIdStatus::takesSlowPath):
+ (JSC::GetByIdStatus::makesCalls):
+ (JSC::GetByIdStatus::structureSet):
+ (JSC::GetByIdStatus::offset):
+ * bytecode/MethodCallLinkStatus.cpp: Added.
+ (JSC::MethodCallLinkStatus::computeFor):
+ * bytecode/MethodCallLinkStatus.h: Added.
+ (JSC::MethodCallLinkStatus::MethodCallLinkStatus):
+ (JSC::MethodCallLinkStatus::isSet):
+ (JSC::MethodCallLinkStatus::operator!):
+ (JSC::MethodCallLinkStatus::needsPrototypeCheck):
+ (JSC::MethodCallLinkStatus::structure):
+ (JSC::MethodCallLinkStatus::prototypeStructure):
+ (JSC::MethodCallLinkStatus::function):
+ (JSC::MethodCallLinkStatus::prototype):
+ * bytecode/PutByIdStatus.cpp: Added.
+ (JSC::PutByIdStatus::computeFor):
+ * bytecode/PutByIdStatus.h: Added.
+ (JSC::PutByIdStatus::PutByIdStatus):
+ (JSC::PutByIdStatus::state):
+ (JSC::PutByIdStatus::isSet):
+ (JSC::PutByIdStatus::operator!):
+ (JSC::PutByIdStatus::isSimpleReplace):
+ (JSC::PutByIdStatus::isSimpleTransition):
+ (JSC::PutByIdStatus::takesSlowPath):
+ (JSC::PutByIdStatus::oldStructure):
+ (JSC::PutByIdStatus::newStructure):
+ (JSC::PutByIdStatus::structureChain):
+ (JSC::PutByIdStatus::offset):
+ * bytecode/StructureSet.h: Added.
+ (JSC::StructureSet::StructureSet):
+ (JSC::StructureSet::clear):
+ (JSC::StructureSet::add):
+ (JSC::StructureSet::addAll):
+ (JSC::StructureSet::remove):
+ (JSC::StructureSet::contains):
+ (JSC::StructureSet::isSubsetOf):
+ (JSC::StructureSet::isSupersetOf):
+ (JSC::StructureSet::size):
+ (JSC::StructureSet::at):
+ (JSC::StructureSet::operator[]):
+ (JSC::StructureSet::last):
+ (JSC::StructureSet::predictionFromStructures):
+ (JSC::StructureSet::operator==):
+ (JSC::StructureSet::dump):
+ * dfg/DFGAbstractValue.h:
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleCall):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGStructureSet.h: Removed.
+
+2012-01-20 Filip Pizlo <fpizlo@apple.com>
+
+ JIT compilation should not require ExecState
+ https://bugs.webkit.org/show_bug.cgi?id=76729
+ <rdar://problem/10731545>
+
+ Reviewed by Gavin Barraclough.
+
+ Changed the relevant JIT driver functions to take JSGlobalData& instead of
+ ExecState*, since really they just needed the global data.
+
+ * dfg/DFGDriver.cpp:
+ (JSC::DFG::compile):
+ (JSC::DFG::tryCompile):
+ (JSC::DFG::tryCompileFunction):
+ * dfg/DFGDriver.h:
+ (JSC::DFG::tryCompile):
+ (JSC::DFG::tryCompileFunction):
+ * jit/JITDriver.h:
+ (JSC::jitCompileIfAppropriate):
+ (JSC::jitCompileFunctionIfAppropriate):
+ * runtime/Executable.cpp:
+ (JSC::EvalExecutable::compileInternal):
+ (JSC::ProgramExecutable::compileInternal):
+ (JSC::FunctionExecutable::compileForCallInternal):
+ (JSC::FunctionExecutable::compileForConstructInternal):
+
+2012-01-20 David Levin <levin@chromium.org>
+
+ Make OwnPtr<HDC> work for the Chromium Windows port.
+ https://bugs.webkit.org/show_bug.cgi?id=76738
+
+ Reviewed by Jian Li.
+
+ * JavaScriptCore.gyp/JavaScriptCore.gyp: Added OwnPtrWin.cpp to the
+ Chromium Windows build.
+ * wtf/OwnPtrCommon.h: Changed from platform WIN to OS WIN for
+ OwnPtr<HDC> and similar constructs.
+
+2012-01-19 Geoffrey Garen <ggaren@apple.com>
+
+ Removed some regexp entry boilerplate code
+ https://bugs.webkit.org/show_bug.cgi?id=76687
+
+ Reviewed by Darin Adler.
+
+ 1% - 2% speedup on regexp tests, no change overall.
+
+ * runtime/RegExp.cpp:
+ (JSC::RegExp::match):
+ - ASSERT that our startIndex is non-negative, because anything less
+ would be uncivilized.
+
+ - ASSERT that our input is not the null string for the same reason.
+
+ - No need to test for startOffset being past the end of the string,
+ since the regular expression engine will do this test for us.
+
+ - No need to initialize the output vector, since the regular expression
+ engine will fill it in for us.
+
+ * yarr/YarrInterpreter.cpp:
+ (JSC::Yarr::Interpreter::interpret):
+ * yarr/YarrJIT.cpp:
+ (JSC::Yarr::YarrGenerator::compile):
+
+ RegExp used to do these jobs for us, but now we do them for ourselves
+ because it's a better separation of concerns, and the JIT can do them
+ more efficiently than C++ code:
+
+ - Test for "past the end" before doing any matching -- otherwise
+ a* will match with zero length past the end of the string, which is wrong.
+
+ - Initialize the output vector before doing any matching.
+
+2012-01-20 Filip Pizlo <fpizlo@apple.com>
+
+ Build fix for no-DFG configuration.
+ Needed for <rdar://problem/10727689>.
+
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::emitProfiledOpcode):
+ * jit/JIT.h:
+ (JSC::JIT::emitValueProfilingSite):
+
+2012-01-19 Filip Pizlo <fpizlo@apple.com>
+
+ Bytecode instructions that may have value profiling should have a direct inline
+ link to the ValueProfile instance
+ https://bugs.webkit.org/show_bug.cgi?id=76682
+ <rdar://problem/10727689>
+
+ Reviewed by Sam Weinig.
+
+ Each opcode that gets value profiled now has a link to its ValueProfile. This
+ required rationalizing the emission of value profiles for opcode combos, like
+ op_method_check/op_get_by_id and op_call/op_call_put_result. It only makes
+ sense for one of them to have a value profile link, and it makes most sense
+ for it to be the one that actually sets the result. The previous behavior was
+ to have op_method_check profile for op_get_by_id when they were used together,
+ but otherwise for op_get_by_id to have its own profiles. op_call already did
+ the right thing; all profiling was done by op_call_put_result.
+
+ But rationalizing this code required breaking some of the natural boundaries
+ that the code had; for instance the code in DFG that emits a GetById in place
+ of both op_method_check and op_get_by_id must now know that it's the latter of
+ those that has the value profile, while the first of those constitutes the OSR
+ target. Hence each CodeOrigin must now have two bytecode indices - one for
+ OSR exit and one for profiling.
+
+ Finally this change required some refiddling of our optimization heuristics,
+ because now all code blocks have "more instructions" due to the value profile
+ slots.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::printGetByIdOp):
+ (JSC::CodeBlock::dump):
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::valueProfileForBytecodeOffset):
+ * bytecode/CodeOrigin.h:
+ (JSC::CodeOrigin::CodeOrigin):
+ (JSC::CodeOrigin::bytecodeIndexForValueProfile):
+ * bytecode/Instruction.h:
+ (JSC::Instruction::Instruction):
+ * bytecode/Opcode.h:
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::emitProfiledOpcode):
+ (JSC::BytecodeGenerator::emitResolve):
+ (JSC::BytecodeGenerator::emitGetScopedVar):
+ (JSC::BytecodeGenerator::emitResolveBase):
+ (JSC::BytecodeGenerator::emitResolveBaseForPut):
+ (JSC::BytecodeGenerator::emitResolveWithBase):
+ (JSC::BytecodeGenerator::emitResolveWithThis):
+ (JSC::BytecodeGenerator::emitGetById):
+ (JSC::BytecodeGenerator::emitGetByVal):
+ (JSC::BytecodeGenerator::emitCall):
+ (JSC::BytecodeGenerator::emitCallVarargs):
+ (JSC::BytecodeGenerator::emitConstruct):
+ * bytecompiler/BytecodeGenerator.h:
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::ByteCodeParser):
+ (JSC::DFG::ByteCodeParser::currentCodeOrigin):
+ (JSC::DFG::ByteCodeParser::addCall):
+ (JSC::DFG::ByteCodeParser::getPredictionWithoutOSRExit):
+ (JSC::DFG::ByteCodeParser::getPrediction):
+ (JSC::DFG::ByteCodeParser::handleCall):
+ (JSC::DFG::ByteCodeParser::handleInlining):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ (JSC::DFG::ByteCodeParser::parse):
+ * dfg/DFGGraph.h:
+ (JSC::DFG::Graph::valueProfileFor):
+ * jit/JIT.h:
+ (JSC::JIT::emitValueProfilingSite):
+ * jit/JITCall.cpp:
+ (JSC::JIT::emit_op_call_put_result):
+ * jit/JITCall32_64.cpp:
+ (JSC::JIT::emit_op_call_put_result):
+ * jit/JITInlineMethods.h:
+ (JSC::JIT::emitValueProfilingSite):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_resolve):
+ (JSC::JIT::emit_op_resolve_base):
+ (JSC::JIT::emit_op_resolve_skip):
+ (JSC::JIT::emit_op_resolve_global):
+ (JSC::JIT::emitSlow_op_resolve_global):
+ (JSC::JIT::emit_op_resolve_with_base):
+ (JSC::JIT::emit_op_resolve_with_this):
+ (JSC::JIT::emitSlow_op_resolve_global_dynamic):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_resolve):
+ (JSC::JIT::emit_op_resolve_base):
+ (JSC::JIT::emit_op_resolve_skip):
+ (JSC::JIT::emit_op_resolve_global):
+ (JSC::JIT::emitSlow_op_resolve_global):
+ (JSC::JIT::emit_op_resolve_with_base):
+ (JSC::JIT::emit_op_resolve_with_this):
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emit_op_get_by_val):
+ (JSC::JIT::emitSlow_op_get_by_val):
+ (JSC::JIT::emit_op_method_check):
+ (JSC::JIT::emitSlow_op_method_check):
+ (JSC::JIT::emit_op_get_by_id):
+ (JSC::JIT::emitSlow_op_get_by_id):
+ (JSC::JIT::emit_op_get_scoped_var):
+ (JSC::JIT::emit_op_get_global_var):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::emit_op_method_check):
+ (JSC::JIT::emitSlow_op_method_check):
+ (JSC::JIT::emit_op_get_by_val):
+ (JSC::JIT::emitSlow_op_get_by_val):
+ (JSC::JIT::emit_op_get_by_id):
+ (JSC::JIT::emitSlow_op_get_by_id):
+ (JSC::JIT::emit_op_get_scoped_var):
+ (JSC::JIT::emit_op_get_global_var):
+ * jit/JITStubCall.h:
+ (JSC::JITStubCall::callWithValueProfiling):
+ * runtime/Options.cpp:
+ (JSC::Options::initializeOptions):
+
+2012-01-20 ChangSeok Oh <shivamidow@gmail.com>
+
+ undefined reference to symbol eina_module_free
+ https://bugs.webkit.org/show_bug.cgi?id=76681
+
+ Reviewed by Martin Robinson.
+
+ eina_module_free has been used without including eina libraries after r104936.
+
+ * wtf/PlatformEfl.cmake: Add EINA_LIBRARIES.
+
+2012-01-19 Tony Chang <tony@chromium.org>
+
+ [chromium] Remove an obsolete comment about features.gypi
+ https://bugs.webkit.org/show_bug.cgi?id=76643
+
+ There can be only one features.gypi.
+
+ Reviewed by James Robinson.
+
+ * JavaScriptCore.gyp/JavaScriptCore.gyp:
+
+2012-01-19 Geoffrey Garen <ggaren@apple.com>
+
+ Implicit creation of a regular expression should eagerly check for syntax errors
+ https://bugs.webkit.org/show_bug.cgi?id=76642
+
+ Reviewed by Oliver Hunt.
+
+ This is a correctness fix and a slight optimization.
+
+ * runtime/StringPrototype.cpp:
+ (JSC::stringProtoFuncMatch):
+ (JSC::stringProtoFuncSearch): Check for syntax errors because that's the
+ correct behavior.
+
+ * runtime/RegExp.cpp:
+ (JSC::RegExp::match): ASSERT that we aren't a syntax error. (One line
+ of code change, many lines of indentation change.)
+
+ Since we have no clients that try to match a RegExp that is a syntax error,
+ let's optimize out the check.
+
+2012-01-19 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ Implement a new allocator for backing stores
+ https://bugs.webkit.org/show_bug.cgi?id=75181
+
+ Reviewed by Filip Pizlo.
+
+ We want to move away from using fastMalloc for the backing stores for
+ some of our objects (e.g. JSArray, JSObject, JSString, etc). These backing
+ stores have a nice property in that they only have a single owner (i.e. a
+ single pointer to them at any one time). One way that we can take advantage
+ of this property is to implement a simple bump allocator/copying collector,
+ which will run alongside our normal mark/sweep collector, that only needs to
+ update the single owner pointer rather than having to redirect an arbitrary
+ number of pointers in from-space to to-space.
+
+ This plan can give us a number of benefits. We can beat fastMalloc in terms
+ of both performance and memory usage, we can track how much memory we're using
+ far more accurately than our rough estimation now through the use of
+ reportExtraMemoryCost, and we can allocate arbitrary size objects (as opposed
+ to being limited to size classes like we have been historically). This is also
+ another step toward moving away from lazy destruction, which will improve our memory footprint.
+
+ We start by creating said allocator and moving the ArrayStorage for JSArray
+ to use it rather than fastMalloc.
+
+ The design of the collector is as follows:
+ Allocation:
+ -The collector allocates 64KB chunks from the OS to use for object allocation.
+ -Each chunk contains an offset, a flag indicating if the block has been pinned,
+ and a payload, along with next and prev pointers so that they can be put in DoublyLinkedLists.
+ -Any allocation greater than 64KB gets its own separate oversize block, which
+ is managed separately from the rest.
+ -If the allocator receives a request for more than the remaining amount in the
+ current block, it grabs a fresh block.
+ -Grabbing a fresh block means grabbing one off of the global free list (which is now
+ shared between the mark/sweep allocator and the bump allocator) if there is one.
+ If there isn't a new one we do one of two things: allocate a new block from the OS
+ if we're not ready for a GC yet, or run a GC and then try again. If we still don't
+ have enough space after the GC, we allocate a new block from the OS.
+
+ Garbage collection:
+ -At the start of garbage collection during conservative stack scanning, if we encounter
+ what appears to be a pointer to a bump-allocated block of memory, we pin that block so
+ that it will not be copied for this round of collection.
+ -We also pin any oversize blocks that we encounter, which effectively doubles as a
+ "mark bit" for that block. Any oversize blocks that aren't pinned at the end of copying
+ are given back to the OS.
+ -Marking threads are now also responsible for copying bump-allocated objects to newSpace
+ -Each marking thread has a private 64KB block into which it copies bump-allocated objects that it encounters.
+ -When that block fills up, the marking thread gives it back to the allocator and requests a new one.
+ -When all marking has concluded, each thread gives back its copy block, even if it isn't full.
+ -At the conclusion of copying (which is done by the end of the marking phase), we un-pin
+ any pinned blocks and give any blocks left in from-space to the global free list.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.gypi:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * heap/AllocationSpace.cpp:
+ (JSC::AllocationSpace::allocateSlowCase):
+ (JSC::AllocationSpace::allocateBlock):
+ (JSC::AllocationSpace::freeBlocks):
+ * heap/AllocationSpace.h:
+ (JSC::AllocationSpace::waterMark):
+ * heap/BumpBlock.h: Added.
+ (JSC::BumpBlock::BumpBlock):
+ * heap/BumpSpace.cpp: Added.
+ (JSC::BumpSpace::tryAllocateSlowCase):
+ * heap/BumpSpace.h: Added.
+ (JSC::BumpSpace::isInCopyPhase):
+ (JSC::BumpSpace::totalMemoryAllocated):
+ (JSC::BumpSpace::totalMemoryUtilized):
+ * heap/BumpSpaceInlineMethods.h: Added.
+ (JSC::BumpSpace::BumpSpace):
+ (JSC::BumpSpace::init):
+ (JSC::BumpSpace::contains):
+ (JSC::BumpSpace::pin):
+ (JSC::BumpSpace::startedCopying):
+ (JSC::BumpSpace::doneCopying):
+ (JSC::BumpSpace::doneFillingBlock):
+ (JSC::BumpSpace::recycleBlock):
+ (JSC::BumpSpace::getFreshBlock):
+ (JSC::BumpSpace::borrowBlock):
+ (JSC::BumpSpace::addNewBlock):
+ (JSC::BumpSpace::allocateNewBlock):
+ (JSC::BumpSpace::fitsInBlock):
+ (JSC::BumpSpace::fitsInCurrentBlock):
+ (JSC::BumpSpace::tryAllocate):
+ (JSC::BumpSpace::tryAllocateOversize):
+ (JSC::BumpSpace::allocateFromBlock):
+ (JSC::BumpSpace::tryReallocate):
+ (JSC::BumpSpace::tryReallocateOversize):
+ (JSC::BumpSpace::isOversize):
+ (JSC::BumpSpace::isPinned):
+ (JSC::BumpSpace::oversizeBlockFor):
+ (JSC::BumpSpace::blockFor):
+ * heap/ConservativeRoots.cpp:
+ (JSC::ConservativeRoots::ConservativeRoots):
+ (JSC::ConservativeRoots::genericAddPointer):
+ (JSC::ConservativeRoots::add):
+ * heap/ConservativeRoots.h:
+ * heap/Heap.cpp:
+ (JSC::Heap::Heap):
+ (JSC::Heap::blockFreeingThreadMain):
+ (JSC::Heap::reportExtraMemoryCostSlowCase):
+ (JSC::Heap::getConservativeRegisterRoots):
+ (JSC::Heap::markRoots):
+ (JSC::Heap::collect):
+ (JSC::Heap::releaseFreeBlocks):
+ * heap/Heap.h:
+ (JSC::Heap::waterMark):
+ (JSC::Heap::highWaterMark):
+ (JSC::Heap::setHighWaterMark):
+ (JSC::Heap::tryAllocateStorage):
+ (JSC::Heap::tryReallocateStorage):
+ * heap/HeapBlock.h: Added.
+ (JSC::HeapBlock::HeapBlock):
+ * heap/MarkStack.cpp:
+ (JSC::MarkStackThreadSharedData::MarkStackThreadSharedData):
+ (JSC::SlotVisitor::drain):
+ (JSC::SlotVisitor::drainFromShared):
+ (JSC::SlotVisitor::startCopying):
+ (JSC::SlotVisitor::allocateNewSpace):
+ (JSC::SlotVisitor::copy):
+ (JSC::SlotVisitor::copyAndAppend):
+ (JSC::SlotVisitor::doneCopying):
+ * heap/MarkStack.h:
+ * heap/MarkedBlock.cpp:
+ (JSC::MarkedBlock::recycle):
+ (JSC::MarkedBlock::MarkedBlock):
+ * heap/MarkedBlock.h:
+ * heap/MarkedSpace.cpp:
+ (JSC::MarkedSpace::MarkedSpace):
+ * heap/MarkedSpace.h:
+ (JSC::MarkedSpace::allocate):
+ (JSC::MarkedSpace::forEachBlock):
+ (JSC::MarkedSpace::SizeClass::resetAllocator):
+ * heap/SlotVisitor.h:
+ (JSC::SlotVisitor::SlotVisitor):
+ * heap/TinyBloomFilter.h:
+ (JSC::TinyBloomFilter::reset):
+ * runtime/JSArray.cpp:
+ (JSC::JSArray::JSArray):
+ (JSC::JSArray::finishCreation):
+ (JSC::JSArray::tryFinishCreationUninitialized):
+ (JSC::JSArray::~JSArray):
+ (JSC::JSArray::enterSparseMode):
+ (JSC::JSArray::defineOwnNumericProperty):
+ (JSC::JSArray::setLengthWritable):
+ (JSC::JSArray::getOwnPropertySlotByIndex):
+ (JSC::JSArray::getOwnPropertyDescriptor):
+ (JSC::JSArray::putByIndexBeyondVectorLength):
+ (JSC::JSArray::deletePropertyByIndex):
+ (JSC::JSArray::getOwnPropertyNames):
+ (JSC::JSArray::increaseVectorLength):
+ (JSC::JSArray::unshiftCountSlowCase):
+ (JSC::JSArray::setLength):
+ (JSC::JSArray::pop):
+ (JSC::JSArray::unshiftCount):
+ (JSC::JSArray::visitChildren):
+ (JSC::JSArray::sortNumeric):
+ (JSC::JSArray::sort):
+ (JSC::JSArray::compactForSorting):
+ (JSC::JSArray::subclassData):
+ (JSC::JSArray::setSubclassData):
+ (JSC::JSArray::checkConsistency):
+ * runtime/JSArray.h:
+ (JSC::JSArray::inSparseMode):
+ (JSC::JSArray::isLengthWritable):
+ * wtf/CheckedBoolean.h: Added.
+ (CheckedBoolean::CheckedBoolean):
+ (CheckedBoolean::~CheckedBoolean):
+ (CheckedBoolean::operator bool):
+ * wtf/DoublyLinkedList.h:
+ (WTF::::push):
+ * wtf/StdLibExtras.h:
+ (WTF::isPointerAligned):
+
+2012-01-19 Joi Sigurdsson <joi@chromium.org>
+
+ Enable use of precompiled headers in Chromium port on Windows.
+
+ Bug 76381 - Use precompiled headers in Chromium port on Windows
+ https://bugs.webkit.org/show_bug.cgi?id=76381
+
+ Reviewed by Tony Chang.
+
+ * JavaScriptCore.gyp/JavaScriptCore.gyp: Include WinPrecompile.gypi.
+
+2012-01-18 Roland Takacs <takacs.roland@stud.u-szeged.hu>
+
+ Cross-platform processor core counter fix
+ https://bugs.webkit.org/show_bug.cgi?id=76540
+
+ Reviewed by Zoltan Herczeg.
+
+ I attached "OS(FREEBSD)" to "#if OS(DARWIN) || OS(OPENBSD) || OS(NETBSD)"
+ and I removed the OS checking macros from ParallelJobsGeneric.cpp because
+ the NumberOfCores.cpp contains them for counting CPU cores.
+ The processor core counter patch located at
+ https://bugs.webkit.org/show_bug.cgi?id=76530
+
+ * wtf/NumberOfCores.cpp:
+ * wtf/ParallelJobsGeneric.cpp:
+
+2012-01-18 Csaba Osztrogonác <ossy@webkit.org>
+
+ Cross-platform processor core counter
+ https://bugs.webkit.org/show_bug.cgi?id=76530
+
+ Unreviewed cross-MinGW buildfix after r105270.
+
+ * wtf/NumberOfCores.cpp: Use windows.h instead of Windows.h.
+
+2012-01-18 Roland Takacs <takacs.roland@stud.u-szeged.hu>
+
+ Cross-platform processor core counter
+ https://bugs.webkit.org/show_bug.cgi?id=76530
+
+ Reviewed by Zoltan Herczeg.
+
+ Two files have been created that include the processor core counter function.
+ It used to be in ParallelJobsGeneric.h/cpp before.
+
+ * GNUmakefile.list.am:
+ * JavaScriptCore.gypi:
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * runtime/Options.cpp:
+ (JSC::Options::initializeOptions):
+ * wtf/CMakeLists.txt:
+ * wtf/NumberOfCores.cpp: Added.
+ (WTF::numberOfProcessorCores):
+ * wtf/NumberOfCores.h: Added.
+ * wtf/ParallelJobsGeneric.cpp:
+ (WTF::ParallelEnvironment::ParallelEnvironment):
+ * wtf/ParallelJobsGeneric.h:
+
+2012-01-18 Balazs Kelemen <kbalazs@webkit.org>
+
+ [Qt] Consolidate layout test crash logging
+ https://bugs.webkit.org/show_bug.cgi?id=75088
+
+ Reviewed by Simon Hausmann.
+
+ Move backtrace generating logic into WTFReportBacktrace
+ and add a way to deinstall signal handlers if we know
+ that we have already printed the backtrace.
+
+ * JavaScriptCore.exp:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
+ * wtf/Assertions.cpp:
+ (WTFLogLocker::WTFReportBacktrace):
+ (WTFLogLocker::WTFSetCrashHook):
+ (WTFLogLocker::WTFInvokeCrashHook):
+ * wtf/Assertions.h:
+
+2012-01-17 Geoffrey Garen <ggaren@apple.com>
+
+ Factored out some code into a helper function.
+
+ I think this might help getting rid of omit-frame-pointer.
+
+ Reviewed by Sam Weinig.
+
+ No benchmark change.
+
+ * runtime/StringPrototype.cpp:
+ (JSC::removeUsingRegExpSearch): Moved to here...
+ (JSC::replaceUsingRegExpSearch): ...from here.
+
+2012-01-17 Caio Marcelo de Oliveira Filho <caio.oliveira@openbossa.org>
+
+ Uint8ClampedArray support
+ https://bugs.webkit.org/show_bug.cgi?id=74455
+
+ Reviewed by Filip Pizlo.
+
+ * GNUmakefile.list.am:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * bytecode/PredictedType.cpp:
+ (JSC::predictionToString):
+ (JSC::predictionFromClassInfo):
+ * bytecode/PredictedType.h:
+ (JSC::isUint8ClampedArrayPrediction):
+ (JSC::isActionableMutableArrayPrediction):
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::initialize):
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::shouldSpeculateUint8ClampedArray):
+ * dfg/DFGPropagator.cpp:
+ (JSC::DFG::Propagator::propagateNodePredictions):
+ (JSC::DFG::Propagator::fixupNode):
+ (JSC::DFG::Propagator::performNodeCSE):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::checkArgumentTypes):
+ (JSC::DFG::clampDoubleToByte):
+ (JSC::DFG::compileClampIntegerToByte):
+ (JSC::DFG::SpeculativeJIT::compilePutByValForByteArray):
+ (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
+ (JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):
+ * dfg/DFGSpeculativeJIT.h:
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * runtime/JSCell.h:
+ * runtime/JSGlobalData.h:
+ * wtf/Forward.h:
+ * wtf/Uint8Array.h:
+ * wtf/Uint8ClampedArray.h: Added.
+ (WTF::Uint8ClampedArray::set):
+ (WTF::Uint8ClampedArray::create):
+ (WTF::Uint8ClampedArray::Uint8ClampedArray):
+ (WTF::Uint8ClampedArray::subarray):
+
+2012-01-17 Sam Weinig <sam@webkit.org>
+
+ Add helper macro for forward declaring objective-c classes
+ https://bugs.webkit.org/show_bug.cgi?id=76485
+
+ Reviewed by Anders Carlsson.
+
+ * wtf/Compiler.h:
+ Add OBJC_CLASS macro which helps reduce code when forward declaring an
+ objective-c class in a header which can be included from both Objective-C
+ and non-Objective-C files.
+
+2012-01-17 Filip Pizlo <fpizlo@apple.com>
+
+ DFG should be able to do JS and custom getter caching
+ https://bugs.webkit.org/show_bug.cgi?id=76361
+
+ Reviewed by Csaba Osztrogonác.
+
+ Fix for 32-bit.
+
+ * dfg/DFGRepatch.cpp:
+ (JSC::DFG::tryBuildGetByIDList):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+
+2012-01-15 Filip Pizlo <fpizlo@apple.com>
+
+ DFG should be able to do JS and custom getter caching
+ https://bugs.webkit.org/show_bug.cgi?id=76361
+ <rdar://problem/10698060>
+
+ Reviewed by Geoff Garen.
+
+ Added the ability to cache JS getter calls and custom getter calls in the DFG.
+ Most of this is pretty mundane, since the old JIT supported this functionality
+ as well. But a couple interesting things had to happen:
+
+ - There are now two variants of GetById: GetById, which works as before, and
+ GetByIdFlush, which flushes registers prior to doing the GetById. Only
+ GetByIdFlush can be used for caching getters. We detect which GetById style
+ to use by looking at the inline caches of the old JIT.
+
+ - Exception handling for getter calls planted in stubs uses a separate lookup
+ handler routine, which uses the CodeOrigin stored in the StructureStubInfo.
+
+ This is a 40% speed-up in the Dromaeo DOM Traversal average. It removes all of
+ the DFG regressions we saw in Dromaeo. This is neutral on SunSpider, V8, and
+ Kraken.
+
+ * bytecode/StructureStubInfo.h:
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGAssemblyHelpers.h:
+ (JSC::DFG::AssemblyHelpers::emitExceptionCheck):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::willNeedFlush):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGCCallHelpers.h:
+ (JSC::DFG::CCallHelpers::setupResults):
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::link):
+ * dfg/DFGJITCompiler.h:
+ (JSC::DFG::PropertyAccessRecord::PropertyAccessRecord):
+ (JSC::DFG::JITCompiler::addExceptionCheck):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::hasIdentifier):
+ (JSC::DFG::Node::hasHeapPrediction):
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGPropagator.cpp:
+ (JSC::DFG::Propagator::propagateNodePredictions):
+ * dfg/DFGRepatch.cpp:
+ (JSC::DFG::tryCacheGetByID):
+ (JSC::DFG::tryBuildGetByIDList):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::appendCallWithExceptionCheckSetResult):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::cachedGetById):
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::cachedGetById):
+ (JSC::DFG::SpeculativeJIT::compile):
+
+2012-01-16 Jon Lee <jonlee@apple.com>
+
+ Build fix for r105086.
+
+ * Configurations/FeatureDefines.xcconfig:
+ * wtf/Platform.h:
+
+2012-01-16 Jon Lee <jonlee@apple.com>
+
+ Remove HTML notifications support on Mac
+ https://bugs.webkit.org/show_bug.cgi?id=76401
+ <rdar://problem/10589881>
+
+ Reviewed by Sam Weinig.
+
+ * wtf/Platform.h: Define ENABLE_HTML_NOTIFICATIONS macro.
+
+2012-01-16 Zeno Albisser <zeno@webkit.org>
+
+ [Qt] Fix QT_VERSION related warnings when building on Mac OS X
+ https://bugs.webkit.org/show_bug.cgi?id=76340
+
+ This bug was caused by r104826.
+ As already mentioned for https://bugs.webkit.org/show_bug.cgi?id=57239
+ we should not use "using namespace WebCore" in header files,
+ because it might cause ambiguous references.
+ This patch reverts the changes from r104826 and r104981
+ and removes the "using namespace WebCore" statement from
+ two header files.
+
+ Reviewed by Tor Arne Vestbø.
+
+ * wtf/Platform.h:
+
+2012-01-16 Carlos Garcia Campos <cgarcia@igalia.com>
+
+ Unreviewed. Fix make distcheck.
+
+ * GNUmakefile.list.am: Fix typo.
+
+2012-01-16 Pavel Heimlich <tropikhajma@gmail.com>
+
+ Solaris Studio supports alignment macros too
+ https://bugs.webkit.org/show_bug.cgi?id=75453
+
+ Reviewed by Hajime Morita.
+
+ * wtf/Alignment.h:
+
+2012-01-16 Yuqiang Xian <yuqiang.xian@intel.com>
+
+ Build fix on 32bit if verbose debug is enabled in DFG
+ https://bugs.webkit.org/show_bug.cgi?id=76351
+
+ Reviewed by Hajime Morita.
+
+ Mostly change "%lu" to "%zu" to print a "size_t" variable.
+
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::endBasicBlock):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleCall):
+ (JSC::DFG::ByteCodeParser::handleInlining):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ (JSC::DFG::ByteCodeParser::parseCodeBlock):
+ * dfg/DFGGraph.cpp:
+ (JSC::DFG::Graph::predictArgumentTypes):
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::link):
+ * dfg/DFGOSREntry.cpp:
+ (JSC::DFG::prepareOSREntry):
+
+2012-01-15 Filip Pizlo <fpizlo@apple.com>
+
+ The C calling convention logic in DFG::SpeculativeJIT should be available even
+ when not generating code for the DFG speculative path
+ https://bugs.webkit.org/show_bug.cgi?id=76355
+
+ Reviewed by Dan Bernstein.
+
+ Moved all of the logic for placing C call arguments into the right place (stack
+ or registers) into a new class, DFG::CCallHelpers. This class inherits from
+ AssemblyHelpers, another DFG grab-bag of helper functions. I could have moved
+ this code into AssemblyHelpers, but decided against it, because I wanted to
+ limit the number of methods each class in the JIT has. Hence now we have a
+ slightly odd organization of JIT classes in DFG: MacroAssembler (basic instruction
+ emission) <= AssemblyHelpers (some additional JS smarts) <= CCallHelpers
+ (understands calls to C functions) <= JITCompiler (can compile a graph to machine
+ code). Each of these except for JITCompiler can be reused for stub compilation.
+
+ * GNUmakefile.list.am:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * dfg/DFGCCallHelpers.h: Added.
+ (JSC::DFG::CCallHelpers::CCallHelpers):
+ (JSC::DFG::CCallHelpers::resetCallArguments):
+ (JSC::DFG::CCallHelpers::addCallArgument):
+ (JSC::DFG::CCallHelpers::setupArguments):
+ (JSC::DFG::CCallHelpers::setupArgumentsExecState):
+ (JSC::DFG::CCallHelpers::setupArgumentsWithExecState):
+ (JSC::DFG::CCallHelpers::setupTwoStubArgs):
+ (JSC::DFG::CCallHelpers::setupStubArguments):
+ * dfg/DFGJITCompiler.h:
+ (JSC::DFG::JITCompiler::JITCompiler):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::callOperation):
+
+2012-01-15 Pablo Flouret <pablof@motorola.com>
+
+ Fix compilation errors on build-webkit --debug --no-video on mac.
+ https://bugs.webkit.org/show_bug.cgi?id=75867
+
+ Reviewed by Philippe Normand.
+
+ Make ENABLE_VIDEO_TRACK conditional on ENABLE_VIDEO, video track feature
+ doesn't build without video.
+
+ * wtf/Platform.h:
+
+2012-01-14 David Levin <levin@chromium.org>
+
+ HWndDC should be in platform/win instead of wtf.
+ https://bugs.webkit.org/show_bug.cgi?id=76314
+
+ Reviewed by Sam Weinig.
+
+ * JavaScriptCore.gyp/JavaScriptCore.gyp:
+ * JavaScriptCore.gypi:
+
+2012-01-13 David Levin <levin@chromium.org>
+
+ check-webkit-style: should encourage the use of Own* classes for Windows DC.
+ https://bugs.webkit.org/show_bug.cgi?id=76227
+
+ Reviewed by Dirk Pranke.
+
+ * wtf/win/HWndDCWin.h:
+ (WTF::HwndDC::HwndDC): Add a way to do GetDCEx.
+ There are no users, but I want to catch this in check-webkit-style
+ and tell any users to use HwndDC to avoid leaks.
+
+2012-01-13 David Levin <levin@chromium.org>
+
+ Header file is missing header guard.
+
+ Reviewed by Dirk Pranke.
+
+ * wtf/win/HWndDCWin.h: Added the guards.
+
+2012-01-13 Andy Wingo <wingo@igalia.com>
+
+ Eval in strict mode does not need dynamic checks
+ https://bugs.webkit.org/show_bug.cgi?id=76286
+
+ Reviewed by Oliver Hunt.
+
+ * runtime/JSActivation.cpp (JSC::JSActivation::JSActivation):
+ Eval in strict mode cannot introduce variables, so it not impose
+ the need for dynamic checks.
+
+2012-01-13 David Levin <levin@chromium.org>
+
+ HWndDC is a better name than HwndDC.
+ https://bugs.webkit.org/show_bug.cgi?id=76281
+
+ Reviewed by Darin Adler.
+
+ * JavaScriptCore.gyp/JavaScriptCore.gyp:
+ * JavaScriptCore.gypi:
+ * wtf/win/HWndDCWin.h: Renamed from Source/JavaScriptCore/wtf/win/HwndDCWin.h.
+ (WTF::HWndDC::HWndDC):
+ (WTF::HWndDC::~HWndDC):
+ (WTF::HWndDC::operator HDC):
+
+2012-01-13 YoungTaeck Song <youngtaeck.song@samsung.com>
+
+ [EFL] Add OwnPtr specialization for Eina_Module.
+ https://bugs.webkit.org/show_bug.cgi?id=76255
+
+ Reviewed by Andreas Kling.
+
+ Add an overload for deleteOwnedPtr(Eina_Module*) on EFL port.
+
+ * wtf/OwnPtrCommon.h:
+ * wtf/efl/OwnPtrEfl.cpp:
+ (WTF::deleteOwnedPtr):
+
+2012-01-13 Yuqiang Xian <yuqiang.xian@intel.com>
+
+ Unreviewed build fix after r104787 if JIT_VERBOSE_OSR is defined
+
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+
+2012-01-12 Hajime Morrita <morrita@chromium.org>
+
+ JavaScriptCore: Mark all exported symbols in the header file automatically.
+ https://bugs.webkit.org/show_bug.cgi?id=72855
+
+ Reviewed by Darin Adler.
+
+ Added WTF_EXPORT_PRIVATE and JS_EXPORT_PRIVATE based on JavaScriptCore.exp files.
+ The change is generated by a tool calledListExportables (https://github.com/omo/ListExportables)
+
+ * API/OpaqueJSString.h:
+ * bytecode/CodeBlock.h:
+ * bytecode/SamplingTool.h:
+ * debugger/Debugger.h:
+ * debugger/DebuggerActivation.h:
+ * debugger/DebuggerCallFrame.h:
+ * heap/AllocationSpace.h:
+ * heap/HandleHeap.h:
+ * heap/Heap.h:
+ * heap/MachineStackMarker.h:
+ * heap/MarkStack.h:
+ * heap/VTableSpectrum.h:
+ * heap/WriteBarrierSupport.h:
+ * parser/Nodes.h:
+ * parser/ParserArena.h:
+ * profiler/Profile.h:
+ * runtime/ArgList.h:
+ * runtime/CallData.h:
+ * runtime/Completion.h:
+ * runtime/ConstructData.h:
+ * runtime/DateInstance.h:
+ * runtime/Error.h:
+ * runtime/ExceptionHelpers.h:
+ * runtime/FunctionConstructor.h:
+ * runtime/Identifier.h:
+ * runtime/InitializeThreading.h:
+ * runtime/InternalFunction.h:
+ * runtime/JSArray.h:
+ * runtime/JSByteArray.h:
+ * runtime/JSCell.h:
+ * runtime/JSFunction.h:
+ * runtime/JSGlobalData.cpp:
+ * runtime/JSGlobalData.h:
+ * runtime/JSGlobalObject.h:
+ * runtime/JSGlobalThis.h:
+ * runtime/JSLock.h:
+ * runtime/JSObject.h:
+ * runtime/JSString.h:
+ * runtime/JSValue.h:
+ * runtime/JSVariableObject.h:
+ * runtime/Lookup.h:
+ * runtime/MemoryStatistics.h:
+ * runtime/ObjectPrototype.h:
+ * runtime/Options.h:
+ * runtime/PropertyDescriptor.h:
+ * runtime/PropertyNameArray.h:
+ * runtime/PropertySlot.h:
+ * runtime/RegExp.h:
+ * runtime/RegExpObject.h:
+ * runtime/SamplingCounter.h:
+ * runtime/SmallStrings.h:
+ * runtime/StringObject.h:
+ * runtime/Structure.h:
+ * runtime/TimeoutChecker.h:
+ * runtime/UString.h:
+ * runtime/WriteBarrier.h:
+ * wtf/ArrayBufferView.h:
+ * wtf/ByteArray.h:
+ * wtf/CryptographicallyRandomNumber.h:
+ * wtf/CurrentTime.h:
+ * wtf/DateMath.h:
+ * wtf/DecimalNumber.h:
+ * wtf/FastMalloc.cpp:
+ * wtf/FastMalloc.h:
+ * wtf/MD5.h:
+ * wtf/MainThread.h:
+ * wtf/MetaAllocator.h:
+ * wtf/MetaAllocatorHandle.h:
+ * wtf/OSAllocator.h:
+ * wtf/PageBlock.h:
+ * wtf/RandomNumber.h:
+ * wtf/RefCountedLeakCounter.h:
+ * wtf/SHA1.h:
+ * wtf/Threading.cpp:
+ * wtf/Threading.h:
+ * wtf/ThreadingPrimitives.h:
+ * wtf/WTFThreadData.h:
+ * wtf/dtoa.h:
+ * wtf/text/AtomicString.h:
+ * wtf/text/CString.h:
+ * wtf/text/StringBuilder.h:
+ * wtf/text/StringImpl.h:
+ * wtf/text/WTFString.h:
+ * wtf/unicode/Collator.h:
+ * wtf/unicode/UTF8.h:
+ * yarr/Yarr.h:
+ * yarr/YarrPattern.h:
+
+2012-01-12 MORITA Hajime <morrita@google.com>
+
+ [Chromium] JSExportMacros.h should be visible.
+ https://bugs.webkit.org/show_bug.cgi?id=76147
+
+ Reviewed by Tony Chang.
+
+ * config.h:
+
+2012-01-12 David Levin <levin@chromium.org>
+
+ HwndDC is a better name than OwnGetDC.
+ https://bugs.webkit.org/show_bug.cgi?id=76235
+
+ Reviewed by Dmitry Titov.
+
+ This is a better name for two reasons:
+ 1. "Own" implies "delete". In this case, the final call is a release (ReleaseDC).
+ 2. "Ref" would be a better name due to the release but the RefPtr (and OwnPtr)
+ classes always take something to hold on to. In this case, the object (the DC)
+ is created by the class once it is given a Window to ensure that the HDC
+ was actually created using GetDC.
+
+ * JavaScriptCore.gyp/JavaScriptCore.gyp:
+ * JavaScriptCore.gypi:
+ * wtf/win/HwndDCWin.h: Renamed from Source/JavaScriptCore/wtf/win/OwnGetDCWin.h.
+ (WTF::HwndDC::HwndDC):
+ (WTF::HwndDC::~HwndDC):
+ (WTF::HwndDC::operator HDC):
+
+2012-01-12 Gavin Barraclough <barraclough@apple.com>
+
+ Clean up putDirect (part 2)
+ https://bugs.webkit.org/show_bug.cgi?id=76232
+
+ Reviewed by Sam Weinig.
+
+ Rename putWithAttributes to putDirectVirtual, to identify that this
+ has the same unchecked-DefineOwnProperty behaviour, change putDirectInternal
+ to be templated on an enum indicating which behaviour it is supposed to be
+ implementing, and change clients that are defining properties to call
+ putDirectInternal correctly.
+
+ * API/JSObjectRef.cpp:
+ (JSObjectSetProperty):
+ * JavaScriptCore.exp:
+ * debugger/DebuggerActivation.cpp:
+ (JSC::DebuggerActivation::putDirectVirtual):
+ * debugger/DebuggerActivation.h:
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::execute):
+ * runtime/ClassInfo.h:
+ * runtime/Error.cpp:
+ (JSC::addErrorInfo):
+ * runtime/JSActivation.cpp:
+ (JSC::JSActivation::putDirectVirtual):
+ * runtime/JSActivation.h:
+ * runtime/JSCell.cpp:
+ (JSC::JSCell::putDirectVirtual):
+ * runtime/JSCell.h:
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::putDirectVirtual):
+ * runtime/JSGlobalObject.h:
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::put):
+ (JSC::JSObject::putDirectVirtual):
+ (JSC::JSObject::defineGetter):
+ (JSC::JSObject::initializeGetterSetterProperty):
+ (JSC::JSObject::defineSetter):
+ (JSC::putDescriptor):
+ * runtime/JSObject.h:
+ (JSC::JSObject::putDirectInternal):
+ (JSC::JSObject::putOwnDataProperty):
+ (JSC::JSObject::putDirect):
+ * runtime/JSStaticScopeObject.cpp:
+ (JSC::JSStaticScopeObject::putDirectVirtual):
+ * runtime/JSStaticScopeObject.h:
+ * runtime/JSVariableObject.cpp:
+ (JSC::JSVariableObject::putDirectVirtual):
+ * runtime/JSVariableObject.h:
+
+2012-01-12 Gavin Barraclough <barraclough@apple.com>
+
+ Clean up putDirect (part 1)
+ https://bugs.webkit.org/show_bug.cgi?id=76232
+
+ Reviewed by Sam Weinig.
+
+ putDirect has ambiguous semantics, clean these up a bit.
+
+ putDirect generally behaves a bit like a fast defineOwnProperty, but one that
+ always creates the property, with no checking to validate the put it permitted.
+
+ It also encompasses two slightly different behaviors.
+ (1) a fast form of put for JSActivation, which doesn't have to handle searching
+ the prototype chain, getter/setter properties, or the magic __proto__ value.
+ Break this out as a new method, 'putOwnDataProperty'.
+ (2) the version of putDirect on JSValue will also check for overwriting ReadOnly
+ values, in strict mode. This is, however, not so smart on a few level, since
+ it is only called from op_put_by_id with direct set, which is only used with
+ an object as the base, and is only used to put new properties onto objects.
+
+ * dfg/DFGOperations.cpp:
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+ * runtime/JSActivation.cpp:
+ (JSC::JSActivation::put):
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::getOwnPropertySlot):
+ * runtime/JSObject.h:
+ (JSC::JSObject::putOwnDataProperty):
+ * runtime/JSValue.h:
+
+2012-01-12 Gavin Barraclough <barraclough@apple.com>
+
+ https://bugs.webkit.org/show_bug.cgi?id=76141
+ defineSetter/defineGetter may fail to update Accessor attribute
+
+ Reviewed by Oliver Hunt.
+
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::defineGetter):
+ (JSC::JSObject::initializeGetterSetterProperty):
+ (JSC::JSObject::defineSetter):
+ * runtime/Structure.cpp:
+ (JSC::Structure::attributeChangeTransition):
+ * runtime/Structure.h:
+
+2012-01-12 David Levin <levin@chromium.org>
+
+ [chromium] Fix DC leak in WebScreenInfoFactory.
+ https://bugs.webkit.org/show_bug.cgi?id=76203
+
+ Reviewed by Dmitry Titov.
+
+ * JavaScriptCore.gyp/JavaScriptCore.gyp: Added OwnGetDCWin.h
+ * JavaScriptCore.gypi: Added OwnGetDCWin.h
+ * JavaScriptCore/wtf/win/OwnGetDCWin.h: Made an owner class for GetDC which needs ReleaseDC as opposed to DeleteDC.
+
+2012-01-11 Gavin Barraclough <barraclough@apple.com>
+
+ Allow accessor get/set property to be set to undefined
+ https://bugs.webkit.org/show_bug.cgi?id=76148
+
+ Reviewed by Oliver Hunt.
+
+ AccessorDescriptor properties may have their get & set properties defined to reference a function
+ (Callable object) or be set to undefined. Valid PropertyDescriptors created by toPropertyDescriptor
+ (defined from JS code via Object.defineProperty, etc) have get and set properties that are in one of
+ three states (1) nonexistent, (2) set to undefined, or (3) a function (any Callable object).
+
+ On the PropertyDescriptor object these three states are represneted by JSValue(), jsUndefined(), and
+ any JSObject* (with a constraint that this must be callable).
+
+ Logically the get/set property of an accessor descriptor on an object might be in any of the three
+ states above, but in practice there is no way to distinguish between the first two states. As such
+ we stor the get/set values in property storage in a JSObject* field, with 0 indicating absent or
+ undefined. When unboxing to a PropertyDescriptor, map this back to a JS undefined value.
+
+ * runtime/GetterSetter.h:
+ (JSC::GetterSetter::setGetter):
+ (JSC::GetterSetter::setSetter):
+ - Allow the getter/setter to be cleared.
+ * runtime/JSArray.cpp:
+ (JSC::JSArray::putDescriptor):
+ - Changed to call getterObject/setterObject.
+ (JSC::JSArray::defineOwnNumericProperty):
+ - Added ASSERT.
+ * runtime/JSObject.cpp:
+ (JSC::putDescriptor):
+ (JSC::JSObject::defineOwnProperty):
+ - Changed to call getterObject/setterObject.
+ * runtime/ObjectConstructor.cpp:
+ (JSC::objectConstructorGetOwnPropertyDescriptor):
+ - getter/setter values read from properties on object are never missing, they will now be set as undefined by 'setDescriptor'.
+ (JSC::toPropertyDescriptor):
+ - Do not translate undefined->empty, this loses an important distinction between a get/set property being absent, or being explicitly set to undefined.
+ * runtime/PropertyDescriptor.cpp:
+ (JSC::PropertyDescriptor::getterObject):
+ (JSC::PropertyDescriptor::setterObject):
+ - Accessors to convert the get/set property to an object pointer, converting undefined to 0.
+ (JSC::PropertyDescriptor::setDescriptor):
+ (JSC::PropertyDescriptor::setAccessorDescriptor):
+ - Translate a getter/setter internally represented at 0 to undefined, indicating that it is present.
+ * runtime/PropertyDescriptor.h:
+ - Declare getterObject/setterObject.
+
+2012-01-12 Zeno Albisser <zeno@webkit.org>
+
+ [Qt][WK2][Mac] Conflict of MacTypes.h defining a Fixed type after r104560.
+ https://bugs.webkit.org/show_bug.cgi?id=76175
+
+ Defining ENABLE_CSS_FILTERS leads to ambiguous references
+ due to MacTypes.h being included.
+ Defining CF_OPEN_SOURCE works around this problem.
+
+ Reviewed by Simon Hausmann.
+
+ * wtf/Platform.h:
+
+2012-01-12 Simon Hausmann <simon.hausmann@nokia.com>
+
+ Make the new WTF module build on Qt
+ https://bugs.webkit.org/show_bug.cgi?id=76163
+
+ Reviewed by Tor Arne Vestbø.
+
+ * JavaScriptCore.pro: Removed wtf from the subdirs to build.
+
+2012-01-11 Filip Pizlo <fpizlo@apple.com>
+
+ CodeBlock::m_executeCounter should be renamed to CodeBlock::m_jitExecuteCounter
+ https://bugs.webkit.org/show_bug.cgi?id=76144
+ <rdar://problem/10681711>
+
+ Rubber stamped by Gavin Barraclough.
+
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::addressOfJITExecuteCounter):
+ (JSC::CodeBlock::offsetOfJITExecuteCounter):
+ (JSC::CodeBlock::jitExecuteCounter):
+ (JSC::CodeBlock::optimizeNextInvocation):
+ (JSC::CodeBlock::dontOptimizeAnytimeSoon):
+ (JSC::CodeBlock::optimizeAfterWarmUp):
+ (JSC::CodeBlock::optimizeAfterLongWarmUp):
+ (JSC::CodeBlock::optimizeSoon):
+ * dfg/DFGOSRExitCompiler32_64.cpp:
+ (JSC::DFG::OSRExitCompiler::compileExit):
+ * dfg/DFGOSRExitCompiler64.cpp:
+ (JSC::DFG::OSRExitCompiler::compileExit):
+ * jit/JIT.cpp:
+ (JSC::JIT::emitOptimizationCheck):
+
+2012-01-11 Gavin Barraclough <barraclough@apple.com>
+
+ Merge 'Getter'/'Setter' attributes into 'Accessor'
+ https://bugs.webkit.org/show_bug.cgi?id=76141
+
+ Reviewed by Filip Pizlo.
+
+ These are currently ambiguous (and used inconsistently). It would logically appear
+ that either being bit set implies that the corresponding type of accessor is present
+ but (a) we don't correctly enforce this, and (b) this means the attributes would not
+ be able to distinguish between a data descriptor and an accessor descriptor with
+ neither a getter nor setter defined (which is a descriptor permissible under the spec).
+ This ambiguity would lead to unsafe property caching behavior (though this does not
+ represent an actual current bug, since we are currently unable to create descriptors
+ that have neither a getter nor setter, it just prevents us from doing so).
+
+ * runtime/Arguments.cpp:
+ (JSC::Arguments::createStrictModeCallerIfNecessary):
+ (JSC::Arguments::createStrictModeCalleeIfNecessary):
+ * runtime/JSArray.cpp:
+ (JSC::SparseArrayValueMap::put):
+ (JSC::JSArray::putDescriptor):
+ * runtime/JSBoundFunction.cpp:
+ (JSC::JSBoundFunction::finishCreation):
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::getOwnPropertySlot):
+ (JSC::JSFunction::getOwnPropertyDescriptor):
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::defineGetter):
+ (JSC::JSObject::initializeGetterSetterProperty):
+ (JSC::JSObject::defineSetter):
+ (JSC::putDescriptor):
+ (JSC::JSObject::defineOwnProperty):
+ * runtime/JSObject.h:
+ * runtime/ObjectConstructor.cpp:
+ (JSC::objectConstructorDefineProperty):
+ * runtime/PropertyDescriptor.cpp:
+ (JSC::PropertyDescriptor::setDescriptor):
+ (JSC::PropertyDescriptor::setAccessorDescriptor):
+ (JSC::PropertyDescriptor::setSetter):
+ (JSC::PropertyDescriptor::setGetter):
+ (JSC::PropertyDescriptor::attributesOverridingCurrent):
+
+2012-01-11 Gavin Barraclough <barraclough@apple.com>
+
+ Object.defineProperty([], 'length', {}) should not make length read-only
+ https://bugs.webkit.org/show_bug.cgi?id=76097
+
+ Reviewed by Oliver Hunt.
+
+ * runtime/JSArray.cpp:
+ (JSC::JSArray::defineOwnProperty):
+ - We should be checking writablePresent().
+
+2012-01-11 Filip Pizlo <fpizlo@apple.com>
+
+ Code duplication for invoking the JIT and DFG should be reduced
+ https://bugs.webkit.org/show_bug.cgi?id=76117
+ <rdar://problem/10680189>
+
+ Rubber stamped by Geoff Garen.
+
+ * GNUmakefile.list.am:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * jit/JITDriver.h: Added.
+ (JSC::jitCompileIfAppropriate):
+ (JSC::jitCompileFunctionIfAppropriate):
+ * runtime/Executable.cpp:
+ (JSC::EvalExecutable::compileInternal):
+ (JSC::ProgramExecutable::compileInternal):
+ (JSC::FunctionExecutable::compileForCallInternal):
+ (JSC::FunctionExecutable::compileForConstructInternal):
+
+2012-01-11 Geoffrey Garen <ggaren@apple.com>
+
+ Bytecode dumping is broken for call opcodes (due to two new operands)
+ https://bugs.webkit.org/show_bug.cgi?id=75886
+
+ Reviewed by Oliver Hunt.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::printCallOp): Made a helper function, so I wouldn't have
+ to fix this more than once. The helper function skips the extra two operands
+ at the end of the opcode, used for optimization.
+
+ (JSC::CodeBlock::dump): Used the helper function.
+
+ * bytecode/CodeBlock.h: Declared the helper function.
+
+2012-01-09 Geoffrey Garen <ggaren@apple.com>
+
+ REGRESSION: d3 Bullet Charts demo doesn't work (call with argument assignment is broken)
+ https://bugs.webkit.org/show_bug.cgi?id=75911
+
+ * bytecompiler/BytecodeGenerator.h:
+ (JSC::BytecodeGenerator::emitNodeForLeftHandSide): Cleanup: No need to
+ explicitly cast to our return type in C++.
+
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::FunctionCallResolveNode::emitBytecode):
+ (JSC::ApplyFunctionCallDotNode::emitBytecode): Make sure to copy our function
+ into a temporary register before evaluating our arguments, since argument
+ evaluation might include function calls or assignments that overwrite our callee by name.
+
+2012-01-11 Michael Saboff <msaboff@apple.com>
+
+ v8-regexp spends 35% of its time allocating and copying internal regexp results data
+ https://bugs.webkit.org/show_bug.cgi?id=76079
+
+ Reviewed by Geoffrey Garen.
+
+ Added a new RegExpResults struct that has the input string, the number of
+ subexpressions and the output vector. Changed RegExpConstructor to
+ include a RegExpConstructorPrivate instead of having a reference to one.
+ Changed RegExpMatchesArray to include a RegExpResults instead of a
+ reference to a RegExpConstructorPrivate. Created an overloaded assignment
+ operator to assign a RegExpConstructorPrivate to a RegExpResults.
+ Collectively this change is worth 24% performance improvement to v8-regexp.
+
+ * runtime/RegExpConstructor.cpp:
+ (JSC::RegExpResult::operator=):
+ (JSC::RegExpConstructor::RegExpConstructor):
+ (JSC::RegExpMatchesArray::RegExpMatchesArray):
+ (JSC::RegExpMatchesArray::finishCreation):
+ (JSC::RegExpMatchesArray::~RegExpMatchesArray):
+ (JSC::RegExpMatchesArray::fillArrayInstance):
+ (JSC::RegExpConstructor::arrayOfMatches):
+ (JSC::RegExpConstructor::getBackref):
+ (JSC::RegExpConstructor::getLastParen):
+ (JSC::RegExpConstructor::getLeftContext):
+ (JSC::RegExpConstructor::getRightContext):
+ (JSC::RegExpConstructor::setInput):
+ (JSC::RegExpConstructor::input):
+ (JSC::RegExpConstructor::setMultiline):
+ (JSC::RegExpConstructor::multiline):
+ * runtime/RegExpConstructor.h:
+ (JSC::RegExpResult::RegExpResult):
+ (JSC::RegExpConstructor::performMatch):
+ * runtime/RegExpMatchesArray.h:
+ (JSC::RegExpMatchesArray::create):
+ (JSC::RegExpMatchesArray::getOwnPropertySlot):
+ (JSC::RegExpMatchesArray::getOwnPropertySlotByIndex):
+ (JSC::RegExpMatchesArray::getOwnPropertyDescriptor):
+ (JSC::RegExpMatchesArray::put):
+ (JSC::RegExpMatchesArray::putByIndex):
+ (JSC::RegExpMatchesArray::deleteProperty):
+ (JSC::RegExpMatchesArray::deletePropertyByIndex):
+ (JSC::RegExpMatchesArray::getOwnPropertyNames):
+
+2012-01-11 Eugene Girard <girard@google.com>
+
+ Typo in error message: Unexpected token 'defualt'
+ https://bugs.webkit.org/show_bug.cgi?id=75105
+
+ Reviewed by Simon Fraser.
+
+ * parser/Parser.h:
+ (JSC::Parser::getTokenName):
+
+2012-01-11 Anders Carlsson <andersca@apple.com>
+
+ Assertion failure in JSC::allocateCell trying to allocate a JSString
+ https://bugs.webkit.org/show_bug.cgi?id=76101
+
+ Reviewed by Adam Roben.
+
+ Remove the ExecutableBase::s_info and JSString::s_info static member variables from the .def file and
+ export them explicitly using the JS_EXPORTDATA macro.
+
+ member variables explicitly using
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
+ * runtime/Executable.h:
+ * runtime/JSString.h:
+
2012-01-10 Mark Rowe <mrowe@apple.com>
<rdar://problem/10673792> jsc should install directly in to versioned Resources subfolder
diff --git a/Source/JavaScriptCore/Configurations/Base.xcconfig b/Source/JavaScriptCore/Configurations/Base.xcconfig
index ba5c75e29..e304bd1fb 100644
--- a/Source/JavaScriptCore/Configurations/Base.xcconfig
+++ b/Source/JavaScriptCore/Configurations/Base.xcconfig
@@ -82,12 +82,19 @@ REAL_PLATFORM_NAME_macosx = macosx;
TARGET_MAC_OS_X_VERSION_MAJOR = $(MAC_OS_X_VERSION_MAJOR);
+NORMAL_JAVASCRIPTCORE_FRAMEWORKS_DIR = $(NORMAL_JAVASCRIPTCORE_FRAMEWORKS_DIR_$(REAL_PLATFORM_NAME));
+NORMAL_JAVASCRIPTCORE_FRAMEWORKS_DIR_iphoneos = $(SYSTEM_LIBRARY_DIR)/PrivateFrameworks;
+NORMAL_JAVASCRIPTCORE_FRAMEWORKS_DIR_iphonesimulator = $(NORMAL_JAVASCRIPTCORE_FRAMEWORKS_DIR_iphoneos);
+NORMAL_JAVASCRIPTCORE_FRAMEWORKS_DIR_macosx = $(SYSTEM_LIBRARY_DIR)/Frameworks;
JAVASCRIPTCORE_FRAMEWORKS_DIR = $(JAVASCRIPTCORE_FRAMEWORKS_DIR_$(REAL_PLATFORM_NAME));
-JAVASCRIPTCORE_FRAMEWORKS_DIR_iphoneos = $(SYSTEM_LIBRARY_DIR)/PrivateFrameworks;
+JAVASCRIPTCORE_FRAMEWORKS_DIR_iphoneos = $(NORMAL_JAVASCRIPTCORE_FRAMEWORKS_DIR_iphoneos);
JAVASCRIPTCORE_FRAMEWORKS_DIR_iphonesimulator = $(JAVASCRIPTCORE_FRAMEWORKS_DIR_iphoneos);
-JAVASCRIPTCORE_FRAMEWORKS_DIR_macosx = $(SYSTEM_LIBRARY_DIR)/Frameworks;
+JAVASCRIPTCORE_FRAMEWORKS_DIR_macosx = $(JAVASCRIPTCORE_FRAMEWORKS_DIR_macosx_USE_STAGING_INSTALL_PATH_$(USE_STAGING_INSTALL_PATH));
+JAVASCRIPTCORE_FRAMEWORKS_DIR_macosx_USE_STAGING_INSTALL_PATH_ = $(JAVASCRIPTCORE_FRAMEWORKS_DIR_macosx_USE_STAGING_INSTALL_PATH_NO);
+JAVASCRIPTCORE_FRAMEWORKS_DIR_macosx_USE_STAGING_INSTALL_PATH_NO = $(NORMAL_JAVASCRIPTCORE_FRAMEWORKS_DIR);
+JAVASCRIPTCORE_FRAMEWORKS_DIR_macosx_USE_STAGING_INSTALL_PATH_YES = $(SYSTEM_LIBRARY_DIR)/StagedFrameworks/Safari;
// DEBUG_DEFINES, GCC_OPTIMIZATION_LEVEL, STRIP_INSTALLED_PRODUCT and DEAD_CODE_STRIPPING vary between the debug and normal variants.
// We set up the values for each variant here, and have the Debug configuration in the Xcode project use the _debug variant.
diff --git a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig
index ac37615e8..3846b27bf 100644
--- a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig
+++ b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig
@@ -106,11 +106,13 @@ ENABLE_PROGRESS_TAG = ENABLE_PROGRESS_TAG;
ENABLE_QUOTA = ;
ENABLE_REGISTER_PROTOCOL_HANDLER = ;
ENABLE_REQUEST_ANIMATION_FRAME = ENABLE_REQUEST_ANIMATION_FRAME;
+ENABLE_SHADOW_DOM = ;
ENABLE_SHARED_WORKERS = ENABLE_SHARED_WORKERS;
ENABLE_SQL_DATABASE = ENABLE_SQL_DATABASE;
ENABLE_STYLE_SCOPED = ;
ENABLE_SVG = ENABLE_SVG;
ENABLE_SVG_FONTS = ENABLE_SVG_FONTS;
+ENABLE_TEXT_NOTIFICATIONS_ONLY = ENABLE_TEXT_NOTIFICATIONS_ONLY;
ENABLE_TOUCH_ICON_LOADING = ;
ENABLE_VIDEO = ENABLE_VIDEO;
ENABLE_VIDEO_TRACK = ;
@@ -121,4 +123,4 @@ ENABLE_WEB_TIMING = ;
ENABLE_WORKERS = ENABLE_WORKERS;
ENABLE_XSLT = ENABLE_XSLT;
-FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ANIMATION_API) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_CSS_FILTERS) $(ENABLE_CSS_GRID_LAYOUT) $(ENABLE_CSS_SHADERS) $(ENABLE_DATALIST) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_FILE_SYSTEM) $(ENABLE_FILTERS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_COLOR) $(ENABLE_INPUT_SPEECH) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_LINK_PREFETCH) $(ENABLE_MATHML) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_TAG) $(ENABLE_MUTATION_OBSERVERS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_TAG) $(ENABLE_QUOTA) $(ENABLE_REGISTER_PROTOCOL_HANDLER) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_SHARED_WORKERS) $(ENABLE_SQL_DATABASE) $(ENABLE_STYLE_SCOPED) $(ENABLE_SVG) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WORKERS) $(ENABLE_XSLT);
+FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ANIMATION_API) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_CSS_FILTERS) $(ENABLE_CSS_GRID_LAYOUT) $(ENABLE_CSS_SHADERS) $(ENABLE_DATALIST) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_FILE_SYSTEM) $(ENABLE_FILTERS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_COLOR) $(ENABLE_INPUT_SPEECH) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_LINK_PREFETCH) $(ENABLE_MATHML) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_TAG) $(ENABLE_MUTATION_OBSERVERS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_TAG) $(ENABLE_QUOTA) $(ENABLE_REGISTER_PROTOCOL_HANDLER) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_SHADOW_DOM) $(ENABLE_SHARED_WORKERS) $(ENABLE_SQL_DATABASE) $(ENABLE_STYLE_SCOPED) $(ENABLE_SVG) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_TEXT_NOTIFICATIONS_ONLY) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WORKERS) $(ENABLE_XSLT);
diff --git a/Source/JavaScriptCore/Configurations/JavaScriptCore.xcconfig b/Source/JavaScriptCore/Configurations/JavaScriptCore.xcconfig
index e6b5b4d2a..827749871 100644
--- a/Source/JavaScriptCore/Configurations/JavaScriptCore.xcconfig
+++ b/Source/JavaScriptCore/Configurations/JavaScriptCore.xcconfig
@@ -46,8 +46,5 @@ GCC_PREFIX_HEADER = JavaScriptCorePrefix.h;
HEADER_SEARCH_PATHS = "${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore" $(HEADER_SEARCH_PATHS);
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = $(JAVASCRIPTCORE_FRAMEWORKS_DIR);
+DYLIB_INSTALL_NAME_BASE = $(NORMAL_JAVASCRIPTCORE_FRAMEWORKS_DIR);
PRODUCT_NAME = JavaScriptCore;
-
-OTHER_CFLAGS = $(OTHER_CFLAGS_$(CONFIGURATION)_$(CURRENT_VARIANT));
-OTHER_CFLAGS_Release_normal = -fomit-frame-pointer -funwind-tables;
-OTHER_CFLAGS_Production_normal = $(OTHER_CFLAGS_Release_normal);
diff --git a/Source/JavaScriptCore/Configurations/Version.xcconfig b/Source/JavaScriptCore/Configurations/Version.xcconfig
index 33019e72f..0510654ff 100644
--- a/Source/JavaScriptCore/Configurations/Version.xcconfig
+++ b/Source/JavaScriptCore/Configurations/Version.xcconfig
@@ -22,7 +22,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
MAJOR_VERSION = 535;
-MINOR_VERSION = 16;
+MINOR_VERSION = 19;
TINY_VERSION = 0;
FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION);
diff --git a/Source/JavaScriptCore/GNUmakefile.am b/Source/JavaScriptCore/GNUmakefile.am
index 8498702dc..654cd108e 100644
--- a/Source/JavaScriptCore/GNUmakefile.am
+++ b/Source/JavaScriptCore/GNUmakefile.am
@@ -60,6 +60,7 @@ javascriptcore_cppflags += \
-I$(srcdir)/Source/JavaScriptCore/parser \
-I$(srcdir)/Source/JavaScriptCore/profiler \
-I$(srcdir)/Source/JavaScriptCore/runtime \
+ -I$(srcdir)/Source/JavaScriptCore/tools \
-I$(srcdir)/Source/JavaScriptCore/wtf \
-I$(srcdir)/Source/JavaScriptCore/wtf \
-I$(srcdir)/Source/JavaScriptCore/wtf/gobject \
diff --git a/Source/JavaScriptCore/GNUmakefile.list.am b/Source/JavaScriptCore/GNUmakefile.list.am
index 4fb218199..de5338dd4 100644
--- a/Source/JavaScriptCore/GNUmakefile.list.am
+++ b/Source/JavaScriptCore/GNUmakefile.list.am
@@ -83,6 +83,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/assembler/X86Assembler.h \
Source/JavaScriptCore/bytecode/CallLinkInfo.cpp \
Source/JavaScriptCore/bytecode/CallLinkInfo.h \
+ Source/JavaScriptCore/bytecode/CallLinkStatus.cpp \
+ Source/JavaScriptCore/bytecode/CallLinkStatus.h \
Source/JavaScriptCore/bytecode/CallReturnOffsetToBytecodeOffset.h \
Source/JavaScriptCore/bytecode/CodeType.h \
Source/JavaScriptCore/bytecode/CodeBlock.cpp \
@@ -93,21 +95,28 @@ javascriptcore_sources += \
Source/JavaScriptCore/bytecode/DFGExitProfile.h \
Source/JavaScriptCore/bytecode/EvalCodeCache.h \
Source/JavaScriptCore/bytecode/ExpressionRangeInfo.h \
+ Source/JavaScriptCore/bytecode/GetByIdStatus.cpp \
+ Source/JavaScriptCore/bytecode/GetByIdStatus.h \
Source/JavaScriptCore/bytecode/GlobalResolveInfo.h \
- Source/JavaScriptCore/bytecode/HandelerInfo.h \
+ Source/JavaScriptCore/bytecode/HandlerInfo.h \
Source/JavaScriptCore/bytecode/Instruction.h \
Source/JavaScriptCore/bytecode/JumpTable.cpp \
Source/JavaScriptCore/bytecode/JumpTable.h \
Source/JavaScriptCore/bytecode/LineInfo.h \
Source/JavaScriptCore/bytecode/MethodCallLinkInfo.cpp \
Source/JavaScriptCore/bytecode/MethodCallLinkInfo.h \
+ Source/JavaScriptCore/bytecode/MethodCallLinkStatus.cpp \
+ Source/JavaScriptCore/bytecode/MethodCallLinkStatus.h \
Source/JavaScriptCore/bytecode/Opcode.cpp \
Source/JavaScriptCore/bytecode/Opcode.h \
Source/JavaScriptCore/bytecode/PredictedType.cpp \
Source/JavaScriptCore/bytecode/PredictedType.h \
Source/JavaScriptCore/bytecode/PredictionTracker.h \
+ Source/JavaScriptCore/bytecode/PutByIdStatus.cpp \
+ Source/JavaScriptCore/bytecode/PutByIdStatus.h \
Source/JavaScriptCore/bytecode/SamplingTool.cpp \
Source/JavaScriptCore/bytecode/SamplingTool.h \
+ Source/JavaScriptCore/bytecode/StructureSet.h \
Source/JavaScriptCore/bytecode/StructureStubInfo.cpp \
Source/JavaScriptCore/bytecode/StructureStubInfo.h \
Source/JavaScriptCore/bytecode/ValueProfile.cpp \
@@ -129,6 +138,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/dfg/DFGByteCodeCache.h \
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp \
Source/JavaScriptCore/dfg/DFGByteCodeParser.h \
+ Source/JavaScriptCore/dfg/DFGCCallHelpers.h \
Source/JavaScriptCore/dfg/DFGCapabilities.cpp \
Source/JavaScriptCore/dfg/DFGCapabilities.h \
Source/JavaScriptCore/dfg/DFGCommon.h \
@@ -165,12 +175,13 @@ javascriptcore_sources += \
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp \
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp \
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h \
- Source/JavaScriptCore/dfg/DFGStructureSet.h \
Source/JavaScriptCore/dfg/DFGThunks.cpp \
Source/JavaScriptCore/dfg/DFGThunks.h \
Source/JavaScriptCore/dfg/DFGVariableAccessData.h \
- Source/JavaScriptCore/heap/AllocationSpace.cpp \
- Source/JavaScriptCore/heap/AllocationSpace.h \
+ Source/JavaScriptCore/heap/BumpBlock.h \
+ Source/JavaScriptCore/heap/BumpSpace.cpp \
+ Source/JavaScriptCore/heap/BumpSpace.h \
+ Source/JavaScriptCore/heap/BumpSpaceInlineMethods.h \
Source/JavaScriptCore/heap/CardSet.h \
Source/JavaScriptCore/heap/ConservativeRoots.cpp \
Source/JavaScriptCore/heap/ConservativeRoots.h \
@@ -179,6 +190,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/heap/Handle.h \
Source/JavaScriptCore/heap/HandleHeap.cpp \
Source/JavaScriptCore/heap/HandleHeap.h \
+ Source/JavaScriptCore/heap/HeapBlock.h \
Source/JavaScriptCore/heap/SlotVisitor.h \
Source/JavaScriptCore/heap/HandleStack.cpp \
Source/JavaScriptCore/heap/HandleStack.h \
@@ -250,6 +262,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/icu/unicode/utf_old.h \
Source/JavaScriptCore/icu/unicode/utypes.h \
Source/JavaScriptCore/icu/unicode/uversion.h \
+ Source/JavaScriptCore/interpreter/AbstractPC.cpp \
+ Source/JavaScriptCore/interpreter/AbstractPC.h \
Source/JavaScriptCore/interpreter/CachedCall.h \
Source/JavaScriptCore/interpreter/CallFrameClosure.h \
Source/JavaScriptCore/interpreter/CallFrame.cpp \
@@ -268,6 +282,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/jit/JITCall32_64.cpp \
Source/JavaScriptCore/jit/JITCall.cpp \
Source/JavaScriptCore/jit/JITCode.h \
+ Source/JavaScriptCore/jit/JITDriver.h \
Source/JavaScriptCore/jit/JIT.cpp \
Source/JavaScriptCore/jit/JIT.h \
Source/JavaScriptCore/jit/JITExceptions.cpp \
@@ -510,6 +525,12 @@ javascriptcore_sources += \
Source/JavaScriptCore/runtime/WeakGCMap.h \
Source/JavaScriptCore/runtime/WeakRandom.h \
Source/JavaScriptCore/runtime/WriteBarrier.h \
+ Source/JavaScriptCore/tools/CodeProfile.cpp \
+ Source/JavaScriptCore/tools/CodeProfile.h \
+ Source/JavaScriptCore/tools/CodeProfiling.cpp \
+ Source/JavaScriptCore/tools/CodeProfiling.h \
+ Source/JavaScriptCore/tools/ProfileTreeNode.h \
+ Source/JavaScriptCore/tools/TieredMMapArray.h \
Source/JavaScriptCore/wtf/Alignment.h \
Source/JavaScriptCore/wtf/AlwaysInline.h \
Source/JavaScriptCore/wtf/ArrayBuffer.cpp \
@@ -531,6 +552,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/wtf/ByteArray.cpp \
Source/JavaScriptCore/wtf/ByteArray.h \
Source/JavaScriptCore/wtf/CheckedArithmetic.h \
+ Source/JavaScriptCore/wtf/CheckedBoolean.h \
Source/JavaScriptCore/wtf/Compiler.h \
Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.cpp \
Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.h \
@@ -616,6 +638,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/wtf/NonCopyingSort.h \
Source/JavaScriptCore/wtf/NotFound.h \
Source/JavaScriptCore/wtf/NullPtr.h \
+ Source/JavaScriptCore/wtf/NumberOfCores.cpp \
+ Source/JavaScriptCore/wtf/NumberOfCores.h \
Source/JavaScriptCore/wtf/OSAllocator.h \
Source/JavaScriptCore/wtf/OSRandomSource.cpp \
Source/JavaScriptCore/wtf/OSRandomSource.h \
@@ -704,6 +728,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/wtf/Uint16Array.h \
Source/JavaScriptCore/wtf/Uint32Array.h \
Source/JavaScriptCore/wtf/Uint8Array.h \
+ Source/JavaScriptCore/wtf/Uint8ClampedArray.h \
Source/JavaScriptCore/wtf/unicode/CharacterNames.h \
Source/JavaScriptCore/wtf/unicode/Collator.h \
Source/JavaScriptCore/wtf/unicode/CollatorDefault.cpp \
diff --git a/Source/JavaScriptCore/JavaScriptCore.exp b/Source/JavaScriptCore/JavaScriptCore.exp
index c79c146e9..51032d742 100644
--- a/Source/JavaScriptCore/JavaScriptCore.exp
+++ b/Source/JavaScriptCore/JavaScriptCore.exp
@@ -91,6 +91,7 @@ _JSWeakObjectMapGet
_JSWeakObjectMapRemove
_JSWeakObjectMapSet
_WTFGetBacktrace
+_WTFInvokeCrashHook
_WTFLog
_WTFLogVerbose
_WTFReportArgumentAssertionFailure
@@ -99,6 +100,7 @@ _WTFReportAssertionFailureWithMessage
_WTFReportBacktrace
_WTFReportError
_WTFReportFatalError
+_WTFSetCrashHook
__ZN14OpaqueJSString6createERKN3JSC7UStringE
__ZN3JSC10HandleHeap12writeBarrierEPNS_7JSValueERKS1_
__ZN3JSC10HandleHeap4growEv
@@ -110,6 +112,8 @@ __ZN3JSC10Identifier3addEPNS_9ExecStateEPKc
__ZN3JSC10Identifier4fromEPNS_9ExecStateEi
__ZN3JSC10Identifier4fromEPNS_9ExecStateEj
__ZN3JSC10Identifier8toUInt32ERKNS_7UStringERb
+__ZN3JSC10JSFunction11displayNameEPNS_9ExecStateE
+__ZN3JSC10JSFunction21calculatedDisplayNameEPNS_9ExecStateE
__ZN3JSC10JSFunction4nameEPNS_9ExecStateE
__ZN3JSC10JSFunction6s_infoE
__ZN3JSC10JSFunctionC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
@@ -125,6 +129,7 @@ __ZN3JSC11JSByteArray3putEPNS_6JSCellEPNS_9ExecStateERKNS_10IdentifierENS_7JSVal
__ZN3JSC11JSByteArray6s_infoE
__ZN3JSC11JSByteArray7destroyEPNS_6JSCellE
__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEPNS_9StructureEPN3WTF9ByteArrayE
+__ZN3JSC11MarkedSpace16allocateSlowCaseERNS0_9SizeClassE
__ZN3JSC11ParserArena5resetEv
__ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeEPNS_7JSValueE
__ZN3JSC11createErrorEPNS_9ExecStateERKNS_7UStringE
@@ -168,7 +173,7 @@ __ZN3JSC14JSGlobalObject12defineSetterEPNS_8JSObjectEPNS_9ExecStateERKNS_10Ident
__ZN3JSC14JSGlobalObject13clearRareDataEPNS_6JSCellE
__ZN3JSC14JSGlobalObject13visitChildrenEPNS_6JSCellERNS_11SlotVisitorE
__ZN3JSC14JSGlobalObject16addStaticGlobalsEPNS0_18GlobalPropertyInfoEi
-__ZN3JSC14JSGlobalObject17putWithAttributesEPNS_8JSObjectEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
+__ZN3JSC14JSGlobalObject16putDirectVirtualEPNS_8JSObjectEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
__ZN3JSC14JSGlobalObject18getOwnPropertySlotEPNS_6JSCellEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
__ZN3JSC14JSGlobalObject24getOwnPropertyDescriptorEPNS_8JSObjectEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
__ZN3JSC14JSGlobalObject25s_globalObjectMethodTableE
@@ -188,7 +193,6 @@ __ZN3JSC14TimeoutChecker5resetEv
__ZN3JSC14VTableSpectrum5countEPNS_6JSCellE
__ZN3JSC14throwTypeErrorEPNS_9ExecStateE
__ZN3JSC14throwTypeErrorEPNS_9ExecStateERKNS_7UStringE
-__ZN3JSC15AllocationSpace16allocateSlowCaseERNS_11MarkedSpace9SizeClassE
__ZN3JSC15WeakHandleOwner26isReachableFromOpaqueRootsENS_6HandleINS_7UnknownEEEPvRNS_11SlotVisitorE
__ZN3JSC15WeakHandleOwner8finalizeENS_6HandleINS_7UnknownEEEPv
__ZN3JSC15WeakHandleOwnerD2Ev
@@ -237,6 +241,7 @@ __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectER
__ZN3JSC24DynamicGlobalObjectScopeC1ERNS_12JSGlobalDataEPNS_14JSGlobalObjectE
__ZN3JSC24TerminatedExecutionError6s_infoE
__ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
+__ZN3JSC24getCalculatedDisplayNameEPNS_9ExecStateEPNS_8JSObjectE
__ZN3JSC25evaluateInGlobalCallFrameERKNS_7UStringERNS_7JSValueEPNS_14JSGlobalObjectE
__ZN3JSC29callHostFunctionAsConstructorEPNS_9ExecStateE
__ZN3JSC30isTerminatedExecutionExceptionENS_7JSValueE
@@ -276,7 +281,7 @@ __ZN3JSC6JSLock4lockENS_14JSLockBehaviorE
__ZN3JSC6JSLock6unlockENS_14JSLockBehaviorE
__ZN3JSC6JSLock9lockCountEv
__ZN3JSC6JSLockC1EPNS_9ExecStateE
-__ZN3JSC6RegExp5matchERNS_12JSGlobalDataERKNS_7UStringEiPN3WTF6VectorIiLm32EEE
+__ZN3JSC6RegExp5matchERNS_12JSGlobalDataERKNS_7UStringEjPN3WTF6VectorIiLm32EEE
__ZN3JSC6RegExp6createERNS_12JSGlobalDataERKNS_7UStringENS_11RegExpFlagsE
__ZN3JSC7JSArray13visitChildrenEPNS_6JSCellERNS_11SlotVisitorE
__ZN3JSC7JSArray14finishCreationERNS_12JSGlobalDataEj
@@ -285,10 +290,8 @@ __ZN3JSC7JSArray17defineOwnPropertyEPNS_8JSObjectEPNS_9ExecStateERKNS_10Identifi
__ZN3JSC7JSArray25getOwnPropertySlotByIndexEPNS_6JSCellEPNS_9ExecStateEjRNS_12PropertySlotE
__ZN3JSC7JSArray30tryFinishCreationUninitializedERNS_12JSGlobalDataEj
__ZN3JSC7JSArray6s_infoE
-__ZN3JSC7JSArray7destroyEPNS_6JSCellE
__ZN3JSC7JSArrayC1ERNS_12JSGlobalDataEPNS_9StructureE
__ZN3JSC7JSArrayC2ERNS_12JSGlobalDataEPNS_9StructureE
-__ZN3JSC7JSArrayD2Ev
__ZN3JSC7JSValue13isValidCalleeEv
__ZN3JSC7Options17numberOfGCMarkersE
__ZN3JSC7Options24opaqueRootMergeThresholdE
@@ -320,10 +323,9 @@ __ZN3JSC8JSObject12toThisObjectEPNS_6JSCellEPNS_9ExecStateE
__ZN3JSC8JSObject13visitChildrenEPNS_6JSCellERNS_11SlotVisitorE
__ZN3JSC8JSObject14deletePropertyEPNS_6JSCellEPNS_9ExecStateERKNS_10IdentifierE
__ZN3JSC8JSObject16getPropertyNamesEPS0_PNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3JSC8JSObject16putDirectVirtualEPS0_PNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
__ZN3JSC8JSObject17defineOwnPropertyEPS0_PNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorEb
__ZN3JSC8JSObject17preventExtensionsERNS_12JSGlobalDataE
-__ZN3JSC8JSObject17putWithAttributesEPNS_12JSGlobalDataERKNS_10IdentifierENS_7JSValueEj
-__ZN3JSC8JSObject17putWithAttributesEPS0_PNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
__ZN3JSC8JSObject19getOwnPropertyNamesEPS0_PNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
__ZN3JSC8JSObject21deletePropertyByIndexEPNS_6JSCellEPNS_9ExecStateEj
__ZN3JSC8JSObject21getPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
@@ -402,6 +404,7 @@ __ZN3WTF12AtomicString3addEPKh
__ZN3WTF12AtomicString3addEPKt
__ZN3WTF12AtomicString3addEPKtj
__ZN3WTF12AtomicString3addEPKtjj
+__ZN3WTF12AtomicString3addEPNS_10StringImplEjj
__ZN3WTF12AtomicString4findEPKtjj
__ZN3WTF12AtomicString4initEv
__ZN3WTF12createThreadEPFPvS0_ES0_
@@ -410,11 +413,10 @@ __ZN3WTF12detachThreadEj
__ZN3WTF12isMainThreadEv
__ZN3WTF12randomNumberEv
__ZN3WTF13MetaAllocator17addFreshFreeSpaceEPvm
-__ZN3WTF13MetaAllocator17freeFreeSpaceNodeEPNS_12RedBlackTreeImPvE4NodeE
+__ZN3WTF13MetaAllocator17freeFreeSpaceNodeEPNS0_13FreeSpaceNodeE
__ZN3WTF13MetaAllocator18debugFreeSpaceSizeEv
-__ZN3WTF13MetaAllocator8allocateEm
+__ZN3WTF13MetaAllocator8allocateEmPv
__ZN3WTF13MetaAllocatorC2Em
-__ZN3WTF13StringBuilder11reifyStringEv
__ZN3WTF13StringBuilder11shrinkToFitEv
__ZN3WTF13StringBuilder15reserveCapacityEj
__ZN3WTF13StringBuilder6appendEPKhj
@@ -450,6 +452,7 @@ __ZN3WTF17equalIgnoringCaseEPNS_10StringImplEPKh
__ZN3WTF17equalIgnoringCaseEPNS_10StringImplES1_
__ZN3WTF18calculateDSTOffsetEdd
__ZN3WTF18calculateUTCOffsetEv
+__ZN3WTF18charactersToDoubleEPKhmPbS2_
__ZN3WTF18charactersToDoubleEPKtmPbS2_
__ZN3WTF18dateToDaysFrom1970Eiii
__ZN3WTF18monthFromDayInYearEib
@@ -547,7 +550,6 @@ __ZN3WTF9xmlnsAtomE
__ZN3WTFeqERKNS_7CStringES2_
__ZNK3JSC10JSFunction10sourceCodeEv
__ZNK3JSC10JSFunction23isHostFunctionNonInlineEv
-__ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_10JSFunctionE
__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE
__ZNK3JSC12PropertySlot14functionGetterEPNS_9ExecStateE
__ZNK3JSC17DebuggerCallFrame10thisObjectEv
@@ -566,13 +568,13 @@ __ZNK3JSC19SourceProviderCache8byteSizeEv
__ZNK3JSC6JSCell11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
__ZNK3JSC6JSCell8toNumberEPNS_9ExecStateE
__ZNK3JSC6JSCell8toObjectEPNS_9ExecStateEPNS_14JSGlobalObjectE
-__ZNK3JSC6JSCell8toStringEPNS_9ExecStateE
__ZNK3JSC6JSCell9getStringEPNS_9ExecStateE
__ZNK3JSC6JSCell9getStringEPNS_9ExecStateERNS_7UStringE
__ZNK3JSC7ArgList8getSliceEiRS0_
__ZNK3JSC7JSArray12subclassDataEv
__ZNK3JSC7JSValue16toNumberSlowCaseEPNS_9ExecStateE
__ZNK3JSC7JSValue16toObjectSlowCaseEPNS_9ExecStateEPNS_14JSGlobalObjectE
+__ZNK3JSC7JSValue16toStringSlowCaseEPNS_9ExecStateE
__ZNK3JSC7JSValue19synthesizePrototypeEPNS_9ExecStateE
__ZNK3JSC7JSValue20toThisObjectSlowCaseEPNS_9ExecStateE
__ZNK3JSC7JSValue9toIntegerEPNS_9ExecStateE
@@ -596,6 +598,8 @@ __ZNK3WTF13DecimalNumber15toStringDecimalEPtj
__ZNK3WTF13DecimalNumber19toStringExponentialEPtj
__ZNK3WTF13DecimalNumber28bufferLengthForStringDecimalEv
__ZNK3WTF13DecimalNumber32bufferLengthForStringExponentialEv
+__ZNK3WTF13StringBuilder11reifyStringEv
+__ZNK3WTF13StringBuilder9canShrinkEv
__ZNK3WTF6String11toIntStrictEPbi
__ZNK3WTF6String12isolatedCopyEv
__ZNK3WTF6String12toUIntStrictEPbi
diff --git a/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp b/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp
index bec3ae17d..34b4e08e5 100644
--- a/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp
+++ b/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp
@@ -1,10 +1,10 @@
#
-# Copyright (C) 2009 Google Inc. All rights reserved.
-#
+# Copyright (C) 2009, 2012 Google 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:
-#
+#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
@@ -14,7 +14,7 @@
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
-#
+#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -30,8 +30,7 @@
{
'includes': [
- # FIXME: Sense whether upstream or downstream build, and
- # include the right features.gypi
+ '../../WebKit/chromium/WinPrecompile.gypi',
'../../WebKit/chromium/features.gypi',
'../JavaScriptCore.gypi',
],
@@ -66,7 +65,7 @@
'defines': [
# Import features_defines from features.gypi
'<@(feature_defines)',
-
+
# Turns on #if PLATFORM(CHROMIUM)
'BUILDING_CHROMIUM__=1',
# Controls wtf/FastMalloc
@@ -123,18 +122,18 @@
['exclude', '../'],
# ... Then include what we want.
['include', '../wtf/'],
- # FIXME: This is clearly not sustainable.
- ['exclude', '../wtf/efl'],
- ['exclude', '../wtf/gobject'],
- ['exclude', '../wtf/gtk'],
- ['exclude', '../wtf/mac'],
- ['exclude', '../wtf/qt'],
- ['exclude', '../wtf/url'],
- ['exclude', '../wtf/wince'],
- ['exclude', '../wtf/wx'],
- ['exclude', '../wtf/unicode/wince'],
- ['exclude', '../wtf/unicode/glib'],
- ['exclude', '../wtf/unicode/qt4'],
+ # FIXME: This is clearly not sustainable.
+ ['exclude', '../wtf/efl'],
+ ['exclude', '../wtf/gobject'],
+ ['exclude', '../wtf/gtk'],
+ ['exclude', '../wtf/mac'],
+ ['exclude', '../wtf/qt'],
+ ['exclude', '../wtf/url'],
+ ['exclude', '../wtf/wince'],
+ ['exclude', '../wtf/wx'],
+ ['exclude', '../wtf/unicode/wince'],
+ ['exclude', '../wtf/unicode/glib'],
+ ['exclude', '../wtf/unicode/qt4'],
# GLib/GTK, even though its name doesn't really indicate.
['exclude', '/(gtk|glib|gobject)/.*\\.(cpp|h)$'],
['exclude', '(Default|Gtk|Mac|None|Qt|Win|Wx|Efl|Symbian)\\.(cpp|mm)$'],
@@ -172,7 +171,8 @@
['exclude', 'ThreadingPthreads\\.cpp$'],
['include', 'Thread(ing|Specific)Win\\.cpp$'],
['exclude', 'OSAllocatorPosix\\.cpp$'],
- ['include', 'OSAllocatorWin\\.cpp$']
+ ['include', 'OSAllocatorWin\\.cpp$'],
+ ['include', 'win/OwnPtrWin\\.cpp$'],
],
'include_dirs!': [
'<(SHARED_INTERMEDIATE_DIR)/webkit',
@@ -198,11 +198,6 @@
'dependencies': [
'wtf',
],
- 'conditions': [
- ['OS=="win"', {
- 'dependencies': ['<(chromium_src_dir)/build/win/system.gyp:cygwin'],
- }],
- ],
'variables': { 'optimize': 'max' },
'actions': [
{
diff --git a/Source/JavaScriptCore/JavaScriptCore.gypi b/Source/JavaScriptCore/JavaScriptCore.gypi
index c9367911b..b59be38d9 100644
--- a/Source/JavaScriptCore/JavaScriptCore.gypi
+++ b/Source/JavaScriptCore/JavaScriptCore.gypi
@@ -27,10 +27,13 @@
'API/OpaqueJSString.h',
'assembler/MacroAssemblerCodeRef.h',
'bytecode/Opcode.h',
- 'heap/AllocationSpace.h',
+ 'heap/BumpBlock.h',
+ 'heap/BumpSpace.h',
+ 'heap/BumpSpaceInlineMethods.h',
'heap/ConservativeRoots.h',
'heap/Handle.h',
'heap/HandleHeap.h',
+ 'heap/HeapBlock.h',
'heap/SlotVisitor.h',
'heap/HandleStack.h',
'heap/HandleTypes.h',
@@ -144,6 +147,7 @@
'wtf/BumpPointerAllocator.h',
'wtf/ByteArray.h',
'wtf/CheckedArithmetic.h',
+ 'wtf/CheckedBoolean.h',
'wtf/Compiler.h',
'wtf/Complex.h',
'wtf/CryptographicallyRandomNumber.h',
@@ -328,7 +332,6 @@
'bytecompiler/LabelScope.h',
'bytecompiler/NodesCodegen.cpp',
'bytecompiler/RegisterID.h',
- 'heap/AllocationSpace.cpp',
'heap/ConservativeRoots.cpp',
'heap/HandleHeap.cpp',
'heap/HandleStack.cpp',
@@ -571,6 +574,8 @@
'wtf/MainThread.cpp',
'wtf/MallocZoneSupport.h',
'wtf/NullPtr.cpp',
+ 'wtf/NumberOfCores.cpp',
+ 'wtf/NumberOfCores.h',
'wtf/OSAllocatorPosix.cpp',
'wtf/OSAllocatorWin.cpp',
'wtf/OSRandomSource.cpp',
diff --git a/Source/JavaScriptCore/JavaScriptCore.order b/Source/JavaScriptCore/JavaScriptCore.order
index 3ceda653e..d8513d099 100644
--- a/Source/JavaScriptCore/JavaScriptCore.order
+++ b/Source/JavaScriptCore/JavaScriptCore.order
@@ -323,7 +323,8 @@ __ZN3WTF13StringBuilder6appendEPKtj
__ZN3WTF13StringBuilder19appendUninitializedEj
__ZN3WTF13StringBuilder14allocateBufferEPKtj
__ZN3WTF13StringBuilder11shrinkToFitEv
-__ZN3WTF13StringBuilder11reifyStringEv
+__ZNK3WTF13StringBuilder11reifyStringEv
+__ZNK3WTF13StringBuilder9canShrinkEv
__ZN3JSC7JSArray4pushEPNS_9ExecStateENS_7JSValueE
__ZN3JSC7JSArray20increaseVectorLengthEj
__ZN3WTF14tryFastReallocEPvm
diff --git a/Source/JavaScriptCore/JavaScriptCore.pri b/Source/JavaScriptCore/JavaScriptCore.pri
index 65e0eb31a..4e2426f8f 100644
--- a/Source/JavaScriptCore/JavaScriptCore.pri
+++ b/Source/JavaScriptCore/JavaScriptCore.pri
@@ -23,6 +23,7 @@ INCLUDEPATH += \
$$SOURCE_DIR/parser \
$$SOURCE_DIR/profiler \
$$SOURCE_DIR/runtime \
+ $$SOURCE_DIR/tools \
$$SOURCE_DIR/yarr \
$$SOURCE_DIR/API \
$$SOURCE_DIR/ForwardingHeaders \
diff --git a/Source/JavaScriptCore/JavaScriptCore.pro b/Source/JavaScriptCore/JavaScriptCore.pro
index cd3ab235f..393728f99 100644
--- a/Source/JavaScriptCore/JavaScriptCore.pro
+++ b/Source/JavaScriptCore/JavaScriptCore.pro
@@ -7,19 +7,13 @@
TEMPLATE = subdirs
CONFIG += ordered
-WTF.file = wtf/wtf.pro
-WTF.makefile = Makefile.WTF
-SUBDIRS += WTF
+derived_sources.file = DerivedSources.pri
+target.file = Target.pri
-!v8 {
- derived_sources.file = DerivedSources.pri
- target.file = Target.pri
+SUBDIRS += derived_sources target
- SUBDIRS += derived_sources target
+addStrictSubdirOrderBetween(derived_sources, target)
- addStrictSubdirOrderBetween(derived_sources, target)
-
- jsc.file = jsc.pro
- jsc.makefile = Makefile.jsc
- SUBDIRS += jsc
-}
+jsc.file = jsc.pro
+jsc.makefile = Makefile.jsc
+SUBDIRS += jsc
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
index 577329e94..93c9e7569 100644
--- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
+++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
@@ -64,7 +64,7 @@ EXPORTS
?addSlowCase@Identifier@JSC@@CA?AV?$PassRefPtr@VStringImpl@WTF@@@WTF@@PAVJSGlobalData@2@PAVStringImpl@4@@Z
?addStaticGlobals@JSGlobalObject@JSC@@IAEXPAUGlobalPropertyInfo@12@H@Z
?allocatePropertyStorage@JSObject@JSC@@QAEXAAVJSGlobalData@2@II@Z
- ?allocateSlowCase@AllocationSpace@JSC@@AAEPAXAAUSizeClass@MarkedSpace@2@@Z
+ ?allocateSlowCase@MarkedSpace@JSC@@AAEPAXAAUSizeClass@12@@Z
?append@StringBuilder@WTF@@QAEXPBEI@Z
?append@StringBuilder@WTF@@QAEXPB_WI@Z
?ascii@UString@JSC@@QBE?AVCString@WTF@@XZ
@@ -158,6 +158,7 @@ EXPORTS
?detach@Debugger@JSC@@UAEXPAVJSGlobalObject@2@@Z
?detachThread@WTF@@YAXI@Z
?didTimeOut@TimeoutChecker@JSC@@QAE_NPAVExecState@2@@Z
+ ?displayName@JSFunction@JSC@@QAE?BVUString@2@PAVExecState@2@@Z
?dtoa@WTF@@YAXQADNAA_NAAHAAI@Z
?dumpSampleData@JSGlobalData@JSC@@QAEXPAVExecState@2@@Z
?empty@StringImpl@WTF@@SAPAV12@XZ
@@ -243,7 +244,7 @@ EXPORTS
?lock@Mutex@WTF@@QAEXXZ
?lockAtomicallyInitializedStaticMutex@WTF@@YAXXZ
?lockCount@JSLock@JSC@@SAHXZ
- ?match@RegExp@JSC@@QAEHAAVJSGlobalData@2@ABVUString@2@HPAV?$Vector@H$0CA@@WTF@@@Z
+ ?match@RegExp@JSC@@QAEHAAVJSGlobalData@2@ABVUString@2@IPAV?$Vector@H$0CA@@WTF@@@Z
?materializePropertyMap@Structure@JSC@@AAEXAAVJSGlobalData@2@@Z
?monotonicallyIncreasingTime@WTF@@YANXZ
?monthFromDayInYear@WTF@@YAHH_N@Z
@@ -274,13 +275,12 @@ EXPORTS
?put@JSObject@JSC@@SAXPAVJSCell@2@PAVExecState@2@ABVIdentifier@2@VJSValue@2@AAVPutPropertySlot@2@@Z
?putByIndex@JSByteArray@JSC@@SAXPAVJSCell@2@PAVExecState@2@IVJSValue@2@@Z
?putByIndex@JSObject@JSC@@SAXPAVJSCell@2@PAVExecState@2@IVJSValue@2@@Z
- ?putDirectInternal@JSObject@JSC@@AAE_NAAVJSGlobalData@2@ABVIdentifier@2@VJSValue@2@I_NAAVPutPropertySlot@2@PAVJSCell@2@@Z
- ?putWithAttributes@JSGlobalObject@JSC@@SAXPAVJSObject@2@PAVExecState@2@ABVIdentifier@2@VJSValue@2@I@Z
- ?putWithAttributes@JSObject@JSC@@SAXPAV12@PAVExecState@2@ABVIdentifier@2@VJSValue@2@I@Z
+ ?putDirectVirtual@JSGlobalObject@JSC@@SAXPAVJSObject@2@PAVExecState@2@ABVIdentifier@2@VJSValue@2@I@Z
+ ?putDirectVirtual@JSObject@JSC@@SAXPAV12@PAVExecState@2@ABVIdentifier@2@VJSValue@2@I@Z
?randomNumber@WTF@@YANXZ
?recompileAllJSFunctions@Debugger@JSC@@QAEXPAVJSGlobalData@2@@Z
?regExpFlags@JSC@@YA?AW4RegExpFlags@1@ABVUString@1@@Z
- ?reifyString@StringBuilder@WTF@@AAEXXZ
+ ?reifyString@StringBuilder@WTF@@ABEXXZ
?releaseDecommitted@OSAllocator@WTF@@SAXPAXI@Z
?releaseExecutableMemory@JSGlobalData@JSC@@QAEXXZ
?reportExtraMemoryCostSlowCase@Heap@JSC@@AAEXI@Z
@@ -292,11 +292,9 @@ EXPORTS
?resize@StringBuilder@WTF@@QAEXI@Z
?resolveRope@JSString@JSC@@ABEXPAVExecState@2@@Z
?restoreAll@Profile@JSC@@QAEXXZ
- ?retrieveCaller@Interpreter@JSC@@QBE?AVJSValue@2@PAVExecState@2@PAVJSFunction@2@@Z
+ ?retrieveCallerFromVMCode@Interpreter@JSC@@QBE?AVJSValue@2@PAVExecState@2@PAVJSFunction@2@@Z
?retrieveLastCaller@Interpreter@JSC@@QBEXPAVExecState@2@AAH1AAVUString@2@AAVJSValue@2@@Z
?s_globalObjectMethodTable@JSGlobalObject@JSC@@1UGlobalObjectMethodTable@2@B
- ?s_info@ExecutableBase@JSC@@2UClassInfo@2@B
- ?s_info@JSString@JSC@@2UClassInfo@2@B
?setConfigurable@PropertyDescriptor@JSC@@QAEX_N@Z
?setDescriptor@PropertyDescriptor@JSC@@QAEXVJSValue@2@I@Z
?setDumpsGeneratedCode@BytecodeGenerator@JSC@@SAX_N@Z
@@ -342,10 +340,10 @@ EXPORTS
?toNumberSlowCase@JSValue@JSC@@ABENPAVExecState@2@@Z
?toObject@JSCell@JSC@@QBEPAVJSObject@2@PAVExecState@2@PAVJSGlobalObject@2@@Z
?toObjectSlowCase@JSValue@JSC@@ABEPAVJSObject@2@PAVExecState@2@PAVJSGlobalObject@2@@Z
- ?toString@JSCell@JSC@@QBE?AVUString@2@PAVExecState@2@@Z
- ?toString@JSObject@JSC@@QBE?AVUString@2@PAVExecState@2@@Z
+ ?toString@JSObject@JSC@@QBEPAVJSString@2@PAVExecState@2@@Z
?toStringDecimal@DecimalNumber@WTF@@QBEIPA_WI@Z
?toStringExponential@DecimalNumber@WTF@@QBEIPA_WI@Z
+ ?toStringSlowCase@JSValue@JSC@@ABEPAVJSString@2@PAVExecState@2@@Z
?toThisObject@JSObject@JSC@@SAPAV12@PAVJSCell@2@PAVExecState@2@@Z
?toThisObjectSlowCase@JSValue@JSC@@ABEPAVJSObject@2@PAVExecState@2@@Z
?toUInt32@Identifier@JSC@@SAIABVUString@2@AA_N@Z
@@ -370,6 +368,7 @@ EXPORTS
?writeBarrier@HandleHeap@JSC@@QAEXPAVJSValue@2@ABV32@@Z
?yield@WTF@@YAXXZ
WTFGetBacktrace
+ WTFInvokeCrashHook
WTFLog
WTFLogVerbose
WTFReportArgumentAssertionFailure
@@ -377,3 +376,4 @@ EXPORTS
WTFReportAssertionFailureWithMessage
WTFReportBacktrace
WTFReportError
+ WTFSetCrashHook
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
index 8fd3c8ab0..fea820ddc 100644
--- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
+++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
@@ -1447,9 +1447,69 @@
</File>
</Filter>
<Filter
+ Name="tools"
+ >
+ <File
+ RelativePath="..\..\tools\CodeProfile.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\tools\CodeProfile.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\tools\CodeProfiling.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\tools\CodeProfiling.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\tools\ProfileTreeNode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\tools\TieredMMapArray.h"
+ >
+ </File>
+ </Filter>
+ <Filter
Name="bytecode"
>
<File
+ RelativePath="..\..\bytecode\GetByIdStatus.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\PutByIdStatus.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\CallLinkStatus.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\MethodCallLinkStatus.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\GetByIdStatus.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\PutByIdStatus.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\CallLinkStatus.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\MethodCallLinkStatus.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\bytecode\HandlerInfo.h"
>
</File>
@@ -1786,6 +1846,14 @@
Name="interpreter"
>
<File
+ RelativePath="..\..\interpreter\AbstractPC.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\interpreter\AbstractPC.h"
+ >
+ </File>
+ <File
RelativePath="..\..\interpreter\CachedCall.h"
>
</File>
@@ -1966,11 +2034,19 @@
Name="heap"
>
<File
- RelativePath="..\..\heap\AllocationSpace.cpp"
+ RelativePath="..\..\heap\BumpBlock.h"
>
</File>
<File
- RelativePath="..\..\heap\AllocationSpace.h"
+ RelativePath="..\..\heap\BumpSpace.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\heap\BumpSpace.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\heap\BumpSpaceInlineMethods.h"
>
</File>
<File
@@ -2026,6 +2102,10 @@
>
</File>
<File
+ RelativePath="..\..\heap\HeapBlock.h"
+ >
+ </File>
+ <File
RelativePath="..\..\heap\Strong.h"
>
</File>
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops
index e94459681..33b53442a 100644
--- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops
+++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops
@@ -6,7 +6,7 @@
>
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="&quot;$(ConfigurationBuildDir)\obj\JavaScriptCore\DerivedSources\&quot;;../../;../../API/;../../parser/;../../bytecompiler/;../../dfg/;../../jit/;../../runtime/;../../bytecode/;../../interpreter/;../../wtf/;../../profiler;../../assembler/;../../debugger/;../../heap/;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\private&quot;;&quot;$(ConfigurationBuildDir)\include&quot;;&quot;$(ConfigurationBuildDir)\include\JavaScriptCore&quot;;&quot;$(ConfigurationBuildDir)\include\private&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;"
+ AdditionalIncludeDirectories="&quot;$(ConfigurationBuildDir)\obj\JavaScriptCore\DerivedSources\&quot;;../../;../../API/;../../parser/;../../bytecompiler/;../../dfg/;../../jit/;../../runtime/;../../tools/;../../bytecode/;../../interpreter/;../../wtf/;../../profiler;../../assembler/;../../debugger/;../../heap/;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\private&quot;;&quot;$(ConfigurationBuildDir)\include&quot;;&quot;$(ConfigurationBuildDir)\include\JavaScriptCore&quot;;&quot;$(ConfigurationBuildDir)\include\private&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;"
PreprocessorDefinitions="__STD_C"
ForcedIncludeFiles="ICUVersion.h"
/>
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj
index 6e89b0167..c914b22c1 100644
--- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj
+++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj
@@ -693,6 +693,10 @@
>
</File>
<File
+ RelativePath="..\..\wtf\CheckedBoolean.h"
+ >
+ </File>
+ <File
RelativePath="..\..\wtf\Compiler.h"
>
</File>
@@ -949,6 +953,14 @@
>
</File>
<File
+ RelativePath="..\..\wtf\NumberOfCores.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\NumberOfCores.h"
+ >
+ </File>
+ <File
RelativePath="..\..\wtf\OSAllocatorWin.cpp"
>
</File>
diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index 8685f097f..9d8b3dd58 100644
--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -60,6 +60,7 @@
0F0B83B914BCF95F00885B4F /* CallReturnOffsetToBytecodeOffset.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F16D726142C39C000CF784A /* BitVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F16D724142C39A200CF784A /* BitVector.cpp */; };
+ 0F21C26814BE5F6800ADC64B /* JITDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C26614BE5F5E00ADC64B /* JITDriver.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F242DA713F3B1E8007ADD4C /* WeakReferenceHarvester.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F2C556F14738F3100121E4F /* DFGCodeBlocks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F2C557014738F3500121E4F /* DFGCodeBlocks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */; };
@@ -70,6 +71,8 @@
0F431738146BAC69007E3890 /* ListableHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F431736146BAC65007E3890 /* ListableHandler.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F46808214BA572D00BFE272 /* JITExceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F46808014BA572700BFE272 /* JITExceptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F46808314BA573100BFE272 /* JITExceptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F46807F14BA572700BFE272 /* JITExceptions.cpp */; };
+ 0F55F0F414D1063900AC7649 /* AbstractPC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F55F0F114D1063600AC7649 /* AbstractPC.cpp */; };
+ 0F55F0F514D1063C00AC7649 /* AbstractPC.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F55F0F214D1063600AC7649 /* AbstractPC.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F5F08CF146C7633000472A9 /* UnconditionalFinalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F620174143FCD330068B77C /* DFGVariableAccessData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F620175143FCD370068B77C /* DFGOperands.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620171143FCD2F0068B77C /* DFGOperands.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -79,6 +82,19 @@
0F620179143FCD480068B77C /* DFGAbstractState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */; };
0F636DA0142D27D700B2E66A /* PackedIntVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F636D9F142D27D200B2E66A /* PackedIntVector.h */; };
0F7700921402FF3C0078EB39 /* SamplingCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7700911402FF280078EB39 /* SamplingCounter.cpp */; };
+ 0F7B294A14C3CD29007C3DB1 /* DFGCCallHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7B294814C3CD23007C3DB1 /* DFGCCallHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F7B294C14C3CD43007C3DB1 /* DFGByteCodeCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5F08CC146BE602000472A9 /* DFGByteCodeCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC0977E1469EBC400CF2442 /* DFGCommon.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F93329D14CA7DC30085F3C6 /* CallLinkStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */; };
+ 0F93329E14CA7DC50085F3C6 /* CallLinkStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329414CA7DC10085F3C6 /* CallLinkStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F93329F14CA7DCA0085F3C6 /* GetByIdStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93329514CA7DC10085F3C6 /* GetByIdStatus.cpp */; };
+ 0F9332A014CA7DCD0085F3C6 /* GetByIdStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329614CA7DC10085F3C6 /* GetByIdStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F9332A114CA7DD10085F3C6 /* MethodCallLinkStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93329714CA7DC10085F3C6 /* MethodCallLinkStatus.cpp */; };
+ 0F9332A214CA7DD30085F3C6 /* MethodCallLinkStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329814CA7DC10085F3C6 /* MethodCallLinkStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F9332A314CA7DD70085F3C6 /* PutByIdStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */; };
+ 0F9332A414CA7DD90085F3C6 /* PutByIdStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F9332A514CA7DDD0085F3C6 /* StructureSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329B14CA7DC10085F3C6 /* StructureSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F963B2713F753BB0002D9B2 /* RedBlackTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B2613F753990002D9B2 /* RedBlackTree.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F963B2C13F853EC0002D9B2 /* MetaAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F963B2B13F853C70002D9B2 /* MetaAllocator.cpp */; settings = {COMPILER_FLAGS = "-fno-strict-aliasing"; }; };
0F963B2D13F854020002D9B2 /* MetaAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B2A13F853BD0002D9B2 /* MetaAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -120,7 +136,6 @@
0FD82F4B142806A100179C94 /* BitVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82F491428069200179C94 /* BitVector.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FE228ED1436AB2700196C48 /* Options.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE228EB1436AB2300196C48 /* Options.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FE228EE1436AB2C00196C48 /* Options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE228EA1436AB2300196C48 /* Options.cpp */; };
- 0FFF4BB4143955E900655BC0 /* DFGStructureSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFF4BB2143955E600655BC0 /* DFGStructureSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
1400067712A6F7830064D123 /* OSAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 1400067612A6F7830064D123 /* OSAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
1400069312A6F9E10064D123 /* OSAllocatorPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */; };
140566C4107EC255005DBC8D /* JSAPIValueWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC0894D50FAFBA2D00001865 /* JSAPIValueWrapper.cpp */; };
@@ -367,6 +382,8 @@
86AE64AA135E5E1C00963012 /* SH4Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86AE64A7135E5E1C00963012 /* SH4Assembler.h */; };
86AE6C4D136A11E400963012 /* DFGFPRInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 86AE6C4B136A11E400963012 /* DFGFPRInfo.h */; };
86AE6C4E136A11E400963012 /* DFGGPRInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 86AE6C4C136A11E400963012 /* DFGGPRInfo.h */; };
+ 86B5826714D2796C00A9C306 /* CodeProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86B5822E14D2373B00A9C306 /* CodeProfile.cpp */; };
+ 86B5826914D2797000A9C306 /* CodeProfiling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8603CEF214C7546400AE59E3 /* CodeProfiling.cpp */; };
86B99AE3117E578100DF5A90 /* StringBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86B99AE1117E578100DF5A90 /* StringBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
86BB09C0138E381B0056702F /* DFGRepatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86BB09BE138E381B0056702F /* DFGRepatch.cpp */; };
86BB09C1138E381B0056702F /* DFGRepatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 86BB09BF138E381B0056702F /* DFGRepatch.h */; };
@@ -414,6 +431,7 @@
90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = 90213E3C123A40C200D422F3 /* MemoryStatistics.h */; settings = {ATTRIBUTES = (Private, ); }; };
905B02AE0E28640F006DF882 /* RefCountedLeakCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 905B02AD0E28640F006DF882 /* RefCountedLeakCounter.cpp */; };
90D3469C0E285280009492EE /* RefCountedLeakCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 90D3469B0E285280009492EE /* RefCountedLeakCounter.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 91A3905614C0F47200F67901 /* Uint8ClampedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 91A3905514C0F47200F67901 /* Uint8ClampedArray.h */; settings = {ATTRIBUTES = (Private, ); }; };
93052C340FB792190048FDC3 /* ParserArena.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93052C320FB792190048FDC3 /* ParserArena.cpp */; };
93052C350FB792190048FDC3 /* ParserArena.h in Headers */ = {isa = PBXBuildFile; fileRef = 93052C330FB792190048FDC3 /* ParserArena.h */; settings = {ATTRIBUTES = (Private, ); }; };
932F5BD30822A1C700736975 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6560A4CF04B3B3E7008AE952 /* CoreFoundation.framework */; };
@@ -460,8 +478,6 @@
A1712B3F11C7B228007A5315 /* RegExpCache.h in Headers */ = {isa = PBXBuildFile; fileRef = A1712B3E11C7B228007A5315 /* RegExpCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
A1712B4111C7B235007A5315 /* RegExpKey.h in Headers */ = {isa = PBXBuildFile; fileRef = A1712B4011C7B235007A5315 /* RegExpKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
A1D764521354448B00C5C7C0 /* Alignment.h in Headers */ = {isa = PBXBuildFile; fileRef = A1D764511354448B00C5C7C0 /* Alignment.h */; settings = {ATTRIBUTES = (Private, ); }; };
- A70456B01427FB910037DA68 /* AllocationSpace.h in Headers */ = {isa = PBXBuildFile; fileRef = A70456AF1427FB150037DA68 /* AllocationSpace.h */; settings = {ATTRIBUTES = (Private, ); }; };
- A70456B11427FB950037DA68 /* AllocationSpace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A70456AE1427FB030037DA68 /* AllocationSpace.cpp */; };
A71236E51195F33C00BD2174 /* JITOpcodes32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A71236E41195F33C00BD2174 /* JITOpcodes32_64.cpp */; };
A72700900DAC6BBC00E548D7 /* JSNotAnObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A72700780DAC605600E548D7 /* JSNotAnObject.cpp */; };
A72701B90DADE94900E548D7 /* ExceptionHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = A72701B30DADE94900E548D7 /* ExceptionHelpers.h */; };
@@ -704,6 +720,12 @@
C22C531313FAF6EF00B7DC0D /* strtod.cc in Sources */ = {isa = PBXBuildFile; fileRef = C22C52B913FAF6EF00B7DC0D /* strtod.cc */; };
C22C531413FAF6EF00B7DC0D /* strtod.h in Headers */ = {isa = PBXBuildFile; fileRef = C22C52BA13FAF6EF00B7DC0D /* strtod.h */; settings = {ATTRIBUTES = (Private, ); }; };
C22C531513FAF6EF00B7DC0D /* utils.h in Headers */ = {isa = PBXBuildFile; fileRef = C22C52BB13FAF6EF00B7DC0D /* utils.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ C240305514B404E60079EB64 /* BumpSpace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C240305314B404C90079EB64 /* BumpSpace.cpp */; };
+ C2C8D02D14A3C6E000578E65 /* BumpSpaceInlineMethods.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C8D02B14A3C6B200578E65 /* BumpSpaceInlineMethods.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ C2C8D03014A3CEFC00578E65 /* BumpBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C8D02E14A3CEFC00578E65 /* BumpBlock.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ C2C8D03114A3CEFC00578E65 /* HeapBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C8D02F14A3CEFC00578E65 /* HeapBlock.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ C2D9CA1314BCC04600304B46 /* CheckedBoolean.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D9CA1214BCC04600304B46 /* CheckedBoolean.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ C2EAA3FA149A835E00FCE112 /* BumpSpace.h in Headers */ = {isa = PBXBuildFile; fileRef = C2EAA3F8149A830800FCE112 /* BumpSpace.h */; settings = {ATTRIBUTES = (Private, ); }; };
C2EE59A013FC973F009CEAFE /* DecimalNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = C2EE599E13FC972A009CEAFE /* DecimalNumber.h */; settings = {ATTRIBUTES = (Private, ); }; };
C2EE59A113FC9768009CEAFE /* DecimalNumber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2EE599D13FC972A009CEAFE /* DecimalNumber.cpp */; };
D7A46A4F1338FFEA00ED695C /* DynamicAnnotations.h in Headers */ = {isa = PBXBuildFile; fileRef = D75AF59612F8CB9500FC0ADF /* DynamicAnnotations.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -725,6 +747,8 @@
E49DC16D12EF295300184A1F /* SourceProviderCacheItem.h in Headers */ = {isa = PBXBuildFile; fileRef = E49DC14912EF261A00184A1F /* SourceProviderCacheItem.h */; settings = {ATTRIBUTES = (Private, ); }; };
E4D8CEFB12FC439600BC9F5A /* BloomFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D8CE9B12FC42E100BC9F5A /* BloomFilter.h */; settings = {ATTRIBUTES = (Private, ); }; };
F3BD31ED126735770065467F /* TextPosition.h in Headers */ = {isa = PBXBuildFile; fileRef = F3BD31D0126730180065467F /* TextPosition.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ F69E86C314C6E551002C2C62 /* NumberOfCores.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F69E86C114C6E551002C2C62 /* NumberOfCores.cpp */; };
+ F69E86C414C6E551002C2C62 /* NumberOfCores.h in Headers */ = {isa = PBXBuildFile; fileRef = F69E86C214C6E551002C2C62 /* NumberOfCores.h */; };
FDA15C1E12B0305C003A583A /* Complex.h in Headers */ = {isa = PBXBuildFile; fileRef = FDA15C1612B03028003A583A /* Complex.h */; settings = {ATTRIBUTES = (Private, ); }; };
FE1B447A0ECCD73B004F4DD1 /* StdLibExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1B44790ECCD73B004F4DD1 /* StdLibExtras.h */; settings = {ATTRIBUTES = (Private, ); }; };
/* End PBXBuildFile section */
@@ -827,6 +851,7 @@
0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallReturnOffsetToBytecodeOffset.h; sourceTree = "<group>"; };
0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonSlowPaths.h; sourceTree = "<group>"; };
0F16D724142C39A200CF784A /* BitVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BitVector.cpp; sourceTree = "<group>"; };
+ 0F21C26614BE5F5E00ADC64B /* JITDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITDriver.h; sourceTree = "<group>"; };
0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakReferenceHarvester.h; sourceTree = "<group>"; };
0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DFGCodeBlocks.cpp; sourceTree = "<group>"; };
0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFGCodeBlocks.h; sourceTree = "<group>"; };
@@ -837,6 +862,8 @@
0F431736146BAC65007E3890 /* ListableHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ListableHandler.h; sourceTree = "<group>"; };
0F46807F14BA572700BFE272 /* JITExceptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITExceptions.cpp; sourceTree = "<group>"; };
0F46808014BA572700BFE272 /* JITExceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITExceptions.h; sourceTree = "<group>"; };
+ 0F55F0F114D1063600AC7649 /* AbstractPC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AbstractPC.cpp; sourceTree = "<group>"; };
+ 0F55F0F214D1063600AC7649 /* AbstractPC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbstractPC.h; sourceTree = "<group>"; };
0F5F08CC146BE602000472A9 /* DFGByteCodeCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGByteCodeCache.h; path = dfg/DFGByteCodeCache.h; sourceTree = "<group>"; };
0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnconditionalFinalizer.h; sourceTree = "<group>"; };
0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAbstractState.cpp; path = dfg/DFGAbstractState.cpp; sourceTree = "<group>"; };
@@ -848,6 +875,16 @@
0F636D9F142D27D200B2E66A /* PackedIntVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PackedIntVector.h; sourceTree = "<group>"; };
0F77008E1402FDD60078EB39 /* SamplingCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SamplingCounter.h; sourceTree = "<group>"; };
0F7700911402FF280078EB39 /* SamplingCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SamplingCounter.cpp; sourceTree = "<group>"; };
+ 0F7B294814C3CD23007C3DB1 /* DFGCCallHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCCallHelpers.h; path = dfg/DFGCCallHelpers.h; sourceTree = "<group>"; };
+ 0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallLinkStatus.cpp; sourceTree = "<group>"; };
+ 0F93329414CA7DC10085F3C6 /* CallLinkStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallLinkStatus.h; sourceTree = "<group>"; };
+ 0F93329514CA7DC10085F3C6 /* GetByIdStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetByIdStatus.cpp; sourceTree = "<group>"; };
+ 0F93329614CA7DC10085F3C6 /* GetByIdStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetByIdStatus.h; sourceTree = "<group>"; };
+ 0F93329714CA7DC10085F3C6 /* MethodCallLinkStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MethodCallLinkStatus.cpp; sourceTree = "<group>"; };
+ 0F93329814CA7DC10085F3C6 /* MethodCallLinkStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MethodCallLinkStatus.h; sourceTree = "<group>"; };
+ 0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PutByIdStatus.cpp; sourceTree = "<group>"; };
+ 0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutByIdStatus.h; sourceTree = "<group>"; };
+ 0F93329B14CA7DC10085F3C6 /* StructureSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureSet.h; sourceTree = "<group>"; };
0F963B2613F753990002D9B2 /* RedBlackTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RedBlackTree.h; sourceTree = "<group>"; };
0F963B2A13F853BD0002D9B2 /* MetaAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MetaAllocator.h; sourceTree = "<group>"; };
0F963B2B13F853C70002D9B2 /* MetaAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MetaAllocator.cpp; sourceTree = "<group>"; };
@@ -891,7 +928,6 @@
0FD82F491428069200179C94 /* BitVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BitVector.h; sourceTree = "<group>"; };
0FE228EA1436AB2300196C48 /* Options.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Options.cpp; sourceTree = "<group>"; };
0FE228EB1436AB2300196C48 /* Options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Options.h; sourceTree = "<group>"; };
- 0FFF4BB2143955E600655BC0 /* DFGStructureSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStructureSet.h; path = dfg/DFGStructureSet.h; sourceTree = "<group>"; };
1400067612A6F7830064D123 /* OSAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSAllocator.h; sourceTree = "<group>"; };
1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSAllocatorPosix.cpp; sourceTree = "<group>"; };
140D17D60E8AD4A9000CD17D /* JSBasePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBasePrivate.h; sourceTree = "<group>"; };
@@ -1008,7 +1044,7 @@
1A082778142168D70090CCAC /* BinarySemaphore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BinarySemaphore.h; sourceTree = "<group>"; };
1AA9E5501498093500001A8A /* Functional.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Functional.h; sourceTree = "<group>"; };
1C9051420BA9E8A70081E9D0 /* Version.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Version.xcconfig; sourceTree = "<group>"; };
- 1C9051430BA9E8A70081E9D0 /* JavaScriptCore.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = JavaScriptCore.xcconfig; path = ../Configurations/JavaScriptCore.xcconfig; sourceTree = "<group>"; };
+ 1C9051430BA9E8A70081E9D0 /* JavaScriptCore.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = JavaScriptCore.xcconfig; sourceTree = "<group>"; };
1C9051440BA9E8A70081E9D0 /* DebugRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugRelease.xcconfig; sourceTree = "<group>"; };
1C9051450BA9E8A70081E9D0 /* Base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = "<group>"; };
1CAA8B4A0D32C39A0041BCFF /* JavaScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaScript.h; sourceTree = "<group>"; };
@@ -1104,6 +1140,8 @@
860161E00F3A83C100F84710 /* MacroAssemblerX86.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerX86.h; sourceTree = "<group>"; };
860161E10F3A83C100F84710 /* MacroAssemblerX86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerX86_64.h; sourceTree = "<group>"; };
860161E20F3A83C100F84710 /* MacroAssemblerX86Common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerX86Common.h; sourceTree = "<group>"; };
+ 8603CEF214C7546400AE59E3 /* CodeProfiling.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeProfiling.cpp; sourceTree = "<group>"; };
+ 8603CEF314C7546400AE59E3 /* CodeProfiling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeProfiling.h; sourceTree = "<group>"; };
8604F4F2143A6C4400B295F5 /* ChangeLog */ = {isa = PBXFileReference; lastKnownFileType = text; path = ChangeLog; sourceTree = "<group>"; };
8604F503143CE1C100B295F5 /* JSGlobalThis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalThis.h; sourceTree = "<group>"; };
8626BECE11928E3900782FAB /* StringStatics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringStatics.cpp; path = text/StringStatics.cpp; sourceTree = "<group>"; };
@@ -1151,6 +1189,10 @@
86AE64A7135E5E1C00963012 /* SH4Assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SH4Assembler.h; sourceTree = "<group>"; };
86AE6C4B136A11E400963012 /* DFGFPRInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGFPRInfo.h; path = dfg/DFGFPRInfo.h; sourceTree = "<group>"; };
86AE6C4C136A11E400963012 /* DFGGPRInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGGPRInfo.h; path = dfg/DFGGPRInfo.h; sourceTree = "<group>"; };
+ 86B5822C14D22F5F00A9C306 /* ProfileTreeNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProfileTreeNode.h; sourceTree = "<group>"; };
+ 86B5822E14D2373B00A9C306 /* CodeProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeProfile.cpp; sourceTree = "<group>"; };
+ 86B5822F14D2373B00A9C306 /* CodeProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeProfile.h; sourceTree = "<group>"; };
+ 86B5826A14D35D5100A9C306 /* TieredMMapArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TieredMMapArray.h; sourceTree = "<group>"; };
86B99AE1117E578100DF5A90 /* StringBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringBuffer.h; path = text/StringBuffer.h; sourceTree = "<group>"; };
86BB09BE138E381B0056702F /* DFGRepatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGRepatch.cpp; path = dfg/DFGRepatch.cpp; sourceTree = "<group>"; };
86BB09BF138E381B0056702F /* DFGRepatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGRepatch.h; path = dfg/DFGRepatch.h; sourceTree = "<group>"; };
@@ -1199,6 +1241,7 @@
90213E3C123A40C200D422F3 /* MemoryStatistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryStatistics.h; sourceTree = "<group>"; };
905B02AD0E28640F006DF882 /* RefCountedLeakCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RefCountedLeakCounter.cpp; sourceTree = "<group>"; };
90D3469B0E285280009492EE /* RefCountedLeakCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RefCountedLeakCounter.h; sourceTree = "<group>"; };
+ 91A3905514C0F47200F67901 /* Uint8ClampedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Uint8ClampedArray.h; sourceTree = "<group>"; };
9303F567099118FA00AD71B8 /* OwnPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OwnPtr.h; sourceTree = "<group>"; };
9303F5690991190000AD71B8 /* Noncopyable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Noncopyable.h; sourceTree = "<group>"; };
9303F5A409911A5800AD71B8 /* OwnArrayPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OwnArrayPtr.h; sourceTree = "<group>"; };
@@ -1272,8 +1315,6 @@
A1712B3E11C7B228007A5315 /* RegExpCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpCache.h; sourceTree = "<group>"; };
A1712B4011C7B235007A5315 /* RegExpKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpKey.h; sourceTree = "<group>"; };
A1D764511354448B00C5C7C0 /* Alignment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Alignment.h; sourceTree = "<group>"; };
- A70456AE1427FB030037DA68 /* AllocationSpace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AllocationSpace.cpp; sourceTree = "<group>"; };
- A70456AF1427FB150037DA68 /* AllocationSpace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllocationSpace.h; sourceTree = "<group>"; };
A71236E41195F33C00BD2174 /* JITOpcodes32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITOpcodes32_64.cpp; sourceTree = "<group>"; };
A718F61A11754A21002465A7 /* RegExpJitTables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpJitTables.h; sourceTree = "<group>"; };
A718F8211178EB4B002465A7 /* create_regex_tables */ = {isa = PBXFileReference; explicitFileType = text.script.python; fileEncoding = 4; path = create_regex_tables; sourceTree = "<group>"; };
@@ -1464,6 +1505,12 @@
C22C52B913FAF6EF00B7DC0D /* strtod.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = strtod.cc; sourceTree = "<group>"; };
C22C52BA13FAF6EF00B7DC0D /* strtod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = strtod.h; sourceTree = "<group>"; };
C22C52BB13FAF6EF00B7DC0D /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = "<group>"; };
+ C240305314B404C90079EB64 /* BumpSpace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BumpSpace.cpp; sourceTree = "<group>"; };
+ C2C8D02B14A3C6B200578E65 /* BumpSpaceInlineMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BumpSpaceInlineMethods.h; sourceTree = "<group>"; };
+ C2C8D02E14A3CEFC00578E65 /* BumpBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BumpBlock.h; sourceTree = "<group>"; };
+ C2C8D02F14A3CEFC00578E65 /* HeapBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapBlock.h; sourceTree = "<group>"; };
+ C2D9CA1214BCC04600304B46 /* CheckedBoolean.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CheckedBoolean.h; sourceTree = "<group>"; };
+ C2EAA3F8149A830800FCE112 /* BumpSpace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BumpSpace.h; sourceTree = "<group>"; };
C2EE599D13FC972A009CEAFE /* DecimalNumber.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DecimalNumber.cpp; sourceTree = "<group>"; };
C2EE599E13FC972A009CEAFE /* DecimalNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DecimalNumber.h; sourceTree = "<group>"; };
D21202280AD4310C00ED79B6 /* DateConversion.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DateConversion.cpp; sourceTree = "<group>"; };
@@ -1533,6 +1580,8 @@
F692A8850255597D01FF60F7 /* UString.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UString.cpp; sourceTree = "<group>"; tabWidth = 8; };
F692A8860255597D01FF60F7 /* UString.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = UString.h; sourceTree = "<group>"; tabWidth = 8; };
F692A8870255597D01FF60F7 /* JSValue.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSValue.cpp; sourceTree = "<group>"; tabWidth = 8; };
+ F69E86C114C6E551002C2C62 /* NumberOfCores.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NumberOfCores.cpp; path = wtf/NumberOfCores.cpp; sourceTree = "<group>"; };
+ F69E86C214C6E551002C2C62 /* NumberOfCores.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NumberOfCores.h; path = wtf/NumberOfCores.h; sourceTree = "<group>"; };
FDA15C1612B03028003A583A /* Complex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Complex.h; sourceTree = "<group>"; };
FE1B44790ECCD73B004F4DD1 /* StdLibExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StdLibExtras.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -1613,6 +1662,8 @@
0867D691FE84028FC02AAC07 /* JavaScriptCore */ = {
isa = PBXGroup;
children = (
+ F69E86C114C6E551002C2C62 /* NumberOfCores.cpp */,
+ F69E86C214C6E551002C2C62 /* NumberOfCores.h */,
8604F4F2143A6C4400B295F5 /* ChangeLog */,
A718F8211178EB4B002465A7 /* create_regex_tables */,
937B63CC09E766D200A671DD /* DerivedSources.make */,
@@ -1637,6 +1688,7 @@
95AB831A0DA42C6900BC83F3 /* profiler */,
7EF6E0BB0EB7A1EC0079AFAF /* runtime */,
141211000A48772600480255 /* tests */,
+ 8603CEF014C753EF00AE59E3 /* tools */,
65162EF108E6A21C007556CD /* wtf */,
86EAC48C0F93E8B9008EC948 /* yarr */,
1C90513E0BA9E8830081E9D0 /* Configurations */,
@@ -1678,6 +1730,8 @@
1429D77A0ED20D7300B89619 /* interpreter */ = {
isa = PBXGroup;
children = (
+ 0F55F0F114D1063600AC7649 /* AbstractPC.cpp */,
+ 0F55F0F214D1063600AC7649 /* AbstractPC.h */,
A7F8690E0F9584A100558697 /* CachedCall.h */,
1429D8DB0ED2205B00B89619 /* CallFrame.cpp */,
1429D8DC0ED2205B00B89619 /* CallFrame.h */,
@@ -1707,6 +1761,7 @@
86CC85A20EE79B7400288682 /* JITCall.cpp */,
146FE51111A710430087AE66 /* JITCall32_64.cpp */,
86CCEFDD0F413F8900FD7F9E /* JITCode.h */,
+ 0F21C26614BE5F5E00ADC64B /* JITDriver.h */,
86CC85A00EE79A4700288682 /* JITInlineMethods.h */,
BCDD51E90FB8DF74004A8BDC /* JITOpcodes.cpp */,
A71236E41195F33C00BD2174 /* JITOpcodes32_64.cpp */,
@@ -1727,8 +1782,10 @@
142E312A134FF0A600AFADB5 /* heap */ = {
isa = PBXGroup;
children = (
- A70456AE1427FB030037DA68 /* AllocationSpace.cpp */,
- A70456AF1427FB150037DA68 /* AllocationSpace.h */,
+ C2C8D02E14A3CEFC00578E65 /* BumpBlock.h */,
+ C240305314B404C90079EB64 /* BumpSpace.cpp */,
+ C2EAA3F8149A830800FCE112 /* BumpSpace.h */,
+ C2C8D02B14A3C6B200578E65 /* BumpSpaceInlineMethods.h */,
A7521E121429169A003C8D0C /* CardSet.h */,
146B14DB12EB5B12001BEC1B /* ConservativeRoots.cpp */,
149DAAF212EB559D0083B12B /* ConservativeRoots.h */,
@@ -1742,6 +1799,7 @@
146FA5A81378F6B0003627A3 /* HandleTypes.h */,
14BA7A9513AADFF8005B7C2C /* Heap.cpp */,
14BA7A9613AADFF8005B7C2C /* Heap.h */,
+ C2C8D02F14A3CEFC00578E65 /* HeapBlock.h */,
14F97446138C853E00DA1C67 /* HeapRootVisitor.h */,
0F431736146BAC65007E3890 /* ListableHandler.h */,
142E3130134FF0A600AFADB5 /* Local.h */,
@@ -1777,7 +1835,6 @@
865F408710E7D56300947361 /* APIShims.h */,
1CAA8B4A0D32C39A0041BCFF /* JavaScript.h */,
1CAA8B4B0D32C39A0041BCFF /* JavaScriptCore.h */,
- 1C9051430BA9E8A70081E9D0 /* JavaScriptCore.xcconfig */,
BC0894D50FAFBA2D00001865 /* JSAPIValueWrapper.cpp */,
BC0894D60FAFBA2D00001865 /* JSAPIValueWrapper.h */,
1421359A0A677F4F00A8195E /* JSBase.cpp */,
@@ -1867,6 +1924,7 @@
1C9051440BA9E8A70081E9D0 /* DebugRelease.xcconfig */,
449097EE0F8F81B50076A327 /* FeatureDefines.xcconfig */,
5DAFD6CB146B686300FBEFB4 /* JSC.xcconfig */,
+ 1C9051430BA9E8A70081E9D0 /* JavaScriptCore.xcconfig */,
BC021BF2136900C300FC5467 /* TestAPI.xcconfig */,
5DAFD6CC146B68B900FBEFB4 /* TestRegExp.xcconfig */,
1C9051420BA9E8A70081E9D0 /* Version.xcconfig */,
@@ -2057,6 +2115,7 @@
A73BE165148420520091204B /* Uint16Array.h */,
A73BE167148420520091204B /* Uint32Array.h */,
A73BE163148420520091204B /* Uint8Array.h */,
+ 91A3905514C0F47200F67901 /* Uint8ClampedArray.h */,
E195678D09E7CF1200B89D13 /* unicode */,
0FD52AAC1430359D0026DC9F /* UnionFind.h */,
935AF46B09E9D9DB00ACD1D8 /* UnusedParam.h */,
@@ -2066,6 +2125,7 @@
96DD73780F9DA3100027FBCC /* VMTags.h */,
86D08D5111793613006E5ED0 /* WTFThreadData.cpp */,
86D08D5211793613006E5ED0 /* WTFThreadData.h */,
+ C2D9CA1214BCC04600304B46 /* CheckedBoolean.h */,
);
path = wtf;
sourceTree = "<group>";
@@ -2314,6 +2374,19 @@
path = runtime;
sourceTree = "<group>";
};
+ 8603CEF014C753EF00AE59E3 /* tools */ = {
+ isa = PBXGroup;
+ children = (
+ 86B5822E14D2373B00A9C306 /* CodeProfile.cpp */,
+ 86B5822F14D2373B00A9C306 /* CodeProfile.h */,
+ 8603CEF214C7546400AE59E3 /* CodeProfiling.cpp */,
+ 8603CEF314C7546400AE59E3 /* CodeProfiling.h */,
+ 86B5822C14D22F5F00A9C306 /* ProfileTreeNode.h */,
+ 86B5826A14D35D5100A9C306 /* TieredMMapArray.h */,
+ );
+ path = tools;
+ sourceTree = "<group>";
+ };
8656573E115BE35200291F40 /* text */ = {
isa = PBXGroup;
children = (
@@ -2369,6 +2442,7 @@
0F5F08CC146BE602000472A9 /* DFGByteCodeCache.h */,
86EC9DB41328DF82002B2AD7 /* DFGByteCodeParser.cpp */,
86EC9DB51328DF82002B2AD7 /* DFGByteCodeParser.h */,
+ 0F7B294814C3CD23007C3DB1 /* DFGCCallHelpers.h */,
0FD82E1E14172C2F00179C94 /* DFGCapabilities.cpp */,
0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */,
0FC0977E1469EBC400CF2442 /* DFGCommon.h */,
@@ -2405,7 +2479,6 @@
86EC9DC31328DF82002B2AD7 /* DFGSpeculativeJIT.h */,
86880F1B14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp */,
86880F4C14353B2100B08D42 /* DFGSpeculativeJIT64.cpp */,
- 0FFF4BB2143955E600655BC0 /* DFGStructureSet.h */,
0FC0979F146B28C700CF2442 /* DFGThunks.cpp */,
0FC097A0146B28C700CF2442 /* DFGThunks.h */,
0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */,
@@ -2474,6 +2547,15 @@
969A078F0ED1D3AE00F1F681 /* bytecode */ = {
isa = PBXGroup;
children = (
+ 0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */,
+ 0F93329414CA7DC10085F3C6 /* CallLinkStatus.h */,
+ 0F93329514CA7DC10085F3C6 /* GetByIdStatus.cpp */,
+ 0F93329614CA7DC10085F3C6 /* GetByIdStatus.h */,
+ 0F93329714CA7DC10085F3C6 /* MethodCallLinkStatus.cpp */,
+ 0F93329814CA7DC10085F3C6 /* MethodCallLinkStatus.h */,
+ 0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */,
+ 0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */,
+ 0F93329B14CA7DC10085F3C6 /* StructureSet.h */,
0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */,
0F0B83B614BCF8DF00885B4F /* GlobalResolveInfo.h */,
0F0B83B214BCF85E00885B4F /* MethodCallLinkInfo.cpp */,
@@ -2586,7 +2668,6 @@
files = (
860161E30F3A83C100F84710 /* AbstractMacroAssembler.h in Headers */,
A1D764521354448B00C5C7C0 /* Alignment.h in Headers */,
- A70456B01427FB910037DA68 /* AllocationSpace.h in Headers */,
BC18C3E40E16F5CD00B34460 /* AlwaysInline.h in Headers */,
BC18C3E50E16F5CD00B34460 /* APICast.h in Headers */,
865F408810E7D56300947361 /* APIShims.h in Headers */,
@@ -2595,6 +2676,7 @@
86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */,
86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */,
A73BE169148420520091204B /* ArrayBuffer.h in Headers */,
+ C2D9CA1314BCC04600304B46 /* CheckedBoolean.h in Headers */,
A73BE16B148420520091204B /* ArrayBufferView.h in Headers */,
BC18C3E60E16F5CD00B34460 /* ArrayConstructor.h in Headers */,
BC18C3E70E16F5CD00B34460 /* ArrayPrototype.h in Headers */,
@@ -2621,7 +2703,10 @@
E4D8CEFB12FC439600BC9F5A /* BloomFilter.h in Headers */,
BC18C3EC0E16F5CD00B34460 /* BooleanObject.h in Headers */,
0FD82E85141F3FE300179C94 /* BoundsCheckedPointer.h in Headers */,
+ C2C8D03014A3CEFC00578E65 /* BumpBlock.h in Headers */,
86676D5211FED9BC004B6863 /* BumpPointerAllocator.h in Headers */,
+ C2EAA3FA149A835E00FCE112 /* BumpSpace.h in Headers */,
+ C2C8D02D14A3C6E000578E65 /* BumpSpaceInlineMethods.h in Headers */,
A7A1F7AD0F252B3C00E184E2 /* ByteArray.h in Headers */,
969A07230ED1CE3300F1F681 /* BytecodeGenerator.h in Headers */,
C22C52F613FAF6EF00B7DC0D /* cached-powers.h in Headers */,
@@ -2688,7 +2773,6 @@
86BB09C1138E381B0056702F /* DFGRepatch.h in Headers */,
86ECA3FA132DF25A002B2AD7 /* DFGScoreBoard.h in Headers */,
86EC9DD31328DF82002B2AD7 /* DFGSpeculativeJIT.h in Headers */,
- 0FFF4BB4143955E900655BC0 /* DFGStructureSet.h in Headers */,
0FC097A2146B28CC00CF2442 /* DFGThunks.h in Headers */,
0F620174143FCD330068B77C /* DFGVariableAccessData.h in Headers */,
BC18C3FD0E16F5CD00B34460 /* DisallowCType.h in Headers */,
@@ -2733,6 +2817,7 @@
BC18C40D0E16F5CD00B34460 /* HashTable.h in Headers */,
BC18C40E0E16F5CD00B34460 /* HashTraits.h in Headers */,
14BA7A9813AADFF8005B7C2C /* Heap.h in Headers */,
+ C2C8D03114A3CEFC00578E65 /* HeapBlock.h in Headers */,
14F97447138C853E00DA1C67 /* HeapRootVisitor.h in Headers */,
7186A6EC13100BA5004479E1 /* HexNumber.h in Headers */,
BC18C40F0E16F5CD00B34460 /* Identifier.h in Headers */,
@@ -3021,6 +3106,19 @@
0F0B83B514BCF86200885B4F /* MethodCallLinkInfo.h in Headers */,
0F0B83B714BCF8E100885B4F /* GlobalResolveInfo.h in Headers */,
0F0B83B914BCF95F00885B4F /* CallReturnOffsetToBytecodeOffset.h in Headers */,
+ 0F21C26814BE5F6800ADC64B /* JITDriver.h in Headers */,
+ 0F7B294A14C3CD29007C3DB1 /* DFGCCallHelpers.h in Headers */,
+ 0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */,
+ 0F7B294C14C3CD43007C3DB1 /* DFGByteCodeCache.h in Headers */,
+ 0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */,
+ 91A3905614C0F47200F67901 /* Uint8ClampedArray.h in Headers */,
+ F69E86C414C6E551002C2C62 /* NumberOfCores.h in Headers */,
+ 0F93329E14CA7DC50085F3C6 /* CallLinkStatus.h in Headers */,
+ 0F9332A014CA7DCD0085F3C6 /* GetByIdStatus.h in Headers */,
+ 0F9332A214CA7DD30085F3C6 /* MethodCallLinkStatus.h in Headers */,
+ 0F9332A414CA7DD90085F3C6 /* PutByIdStatus.h in Headers */,
+ 0F9332A514CA7DDD0085F3C6 /* StructureSet.h in Headers */,
+ 0F55F0F514D1063C00AC7649 /* AbstractPC.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3330,7 +3428,6 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- A70456B11427FB950037DA68 /* AllocationSpace.cpp in Sources */,
147F39BD107EC37600427A48 /* ArgList.cpp in Sources */,
147F39BE107EC37600427A48 /* Arguments.cpp in Sources */,
86D3B2C310156BDE002865E7 /* ARMAssembler.cpp in Sources */,
@@ -3348,6 +3445,7 @@
14280863107EC11A0013E7B2 /* BooleanConstructor.cpp in Sources */,
14280864107EC11A0013E7B2 /* BooleanObject.cpp in Sources */,
14280865107EC11A0013E7B2 /* BooleanPrototype.cpp in Sources */,
+ C240305514B404E60079EB64 /* BumpSpace.cpp in Sources */,
A7A1F7AC0F252B3C00E184E2 /* ByteArray.cpp in Sources */,
148F21AA107EC53A0042EC2C /* BytecodeGenerator.cpp in Sources */,
C22C52F513FAF6EF00B7DC0D /* cached-powers.cc in Sources */,
@@ -3558,6 +3656,14 @@
0F46808314BA573100BFE272 /* JITExceptions.cpp in Sources */,
0F0B83B014BCF71600885B4F /* CallLinkInfo.cpp in Sources */,
0F0B83B414BCF86000885B4F /* MethodCallLinkInfo.cpp in Sources */,
+ F69E86C314C6E551002C2C62 /* NumberOfCores.cpp in Sources */,
+ 0F93329D14CA7DC30085F3C6 /* CallLinkStatus.cpp in Sources */,
+ 0F93329F14CA7DCA0085F3C6 /* GetByIdStatus.cpp in Sources */,
+ 0F9332A114CA7DD10085F3C6 /* MethodCallLinkStatus.cpp in Sources */,
+ 0F9332A314CA7DD70085F3C6 /* PutByIdStatus.cpp in Sources */,
+ 0F55F0F414D1063900AC7649 /* AbstractPC.cpp in Sources */,
+ 86B5826714D2796C00A9C306 /* CodeProfile.cpp in Sources */,
+ 86B5826914D2797000A9C306 /* CodeProfiling.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/Source/JavaScriptCore/Target.pri b/Source/JavaScriptCore/Target.pri
index 6ea82d102..c61fb37f1 100644
--- a/Source/JavaScriptCore/Target.pri
+++ b/Source/JavaScriptCore/Target.pri
@@ -50,18 +50,22 @@ SOURCES += \
assembler/MacroAssemblerARM.cpp \
assembler/MacroAssemblerSH4.cpp \
bytecode/CallLinkInfo.cpp \
+ bytecode/CallLinkStatus.cpp \
bytecode/CodeBlock.cpp \
bytecode/DFGExitProfile.cpp \
+ bytecode/GetByIdStatus.cpp \
bytecode/JumpTable.cpp \
bytecode/MethodCallLinkInfo.cpp \
+ bytecode/MethodCallLinkStatus.cpp \
bytecode/Opcode.cpp \
bytecode/PredictedType.cpp \
+ bytecode/PutByIdStatus.cpp \
bytecode/SamplingTool.cpp \
bytecode/StructureStubInfo.cpp \
bytecode/ValueProfile.cpp \
bytecompiler/BytecodeGenerator.cpp \
bytecompiler/NodesCodegen.cpp \
- heap/AllocationSpace.cpp \
+ heap/BumpSpace.cpp \
heap/ConservativeRoots.cpp \
heap/DFGCodeBlocks.cpp \
heap/HandleHeap.cpp \
@@ -96,6 +100,7 @@ SOURCES += \
dfg/DFGSpeculativeJIT32_64.cpp \
dfg/DFGSpeculativeJIT64.cpp \
dfg/DFGThunks.cpp \
+ interpreter/AbstractPC.cpp \
interpreter/CallFrame.cpp \
interpreter/Interpreter.cpp \
interpreter/RegisterFile.cpp \
@@ -204,6 +209,8 @@ SOURCES += \
runtime/Structure.cpp \
runtime/TimeoutChecker.cpp \
runtime/UString.cpp \
+ tools/CodeProfile.cpp \
+ tools/CodeProfiling.cpp \
yarr/YarrJIT.cpp \
*sh4* {
diff --git a/Source/JavaScriptCore/assembler/ARMAssembler.cpp b/Source/JavaScriptCore/assembler/ARMAssembler.cpp
index 9e6c5e5fc..4ded0e88e 100644
--- a/Source/JavaScriptCore/assembler/ARMAssembler.cpp
+++ b/Source/JavaScriptCore/assembler/ARMAssembler.cpp
@@ -344,14 +344,14 @@ void ARMAssembler::doubleTransfer(bool isLoad, FPRegisterID srcDst, RegisterID b
fdtr_u(isLoad, srcDst, ARMRegisters::S0, 0);
}
-PassRefPtr<ExecutableMemoryHandle> ARMAssembler::executableCopy(JSGlobalData& globalData)
+PassRefPtr<ExecutableMemoryHandle> ARMAssembler::executableCopy(JSGlobalData& globalData, void* ownerUID)
{
// 64-bit alignment is required for next constant pool and JIT code as well
m_buffer.flushWithoutBarrier(true);
if (!m_buffer.isAligned(8))
bkpt(0);
- RefPtr<ExecutableMemoryHandle> result = m_buffer.executableCopy(globalData);
+ RefPtr<ExecutableMemoryHandle> result = m_buffer.executableCopy(globalData, ownerUID);
char* data = reinterpret_cast<char*>(result->start());
for (Jumps::Iterator iter = m_jumps.begin(); iter != m_jumps.end(); ++iter) {
diff --git a/Source/JavaScriptCore/assembler/ARMAssembler.h b/Source/JavaScriptCore/assembler/ARMAssembler.h
index 5792d2c0f..a659eefee 100644
--- a/Source/JavaScriptCore/assembler/ARMAssembler.h
+++ b/Source/JavaScriptCore/assembler/ARMAssembler.h
@@ -679,7 +679,7 @@ namespace JSC {
return loadBranchTarget(ARMRegisters::pc, cc, useConstantPool);
}
- PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData&);
+ PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData&, void* ownerUID);
#ifndef NDEBUG
unsigned debugOffset() { return m_buffer.debugOffset(); }
diff --git a/Source/JavaScriptCore/assembler/ARMv7Assembler.h b/Source/JavaScriptCore/assembler/ARMv7Assembler.h
index 530ae0d0b..0b83776df 100644
--- a/Source/JavaScriptCore/assembler/ARMv7Assembler.h
+++ b/Source/JavaScriptCore/assembler/ARMv7Assembler.h
@@ -414,11 +414,6 @@ private:
class ARMv7Assembler {
public:
- ~ARMv7Assembler()
- {
- ASSERT(m_jumpsToLink.isEmpty());
- }
-
typedef ARMRegisters::RegisterID RegisterID;
typedef ARMRegisters::FPSingleRegisterID FPSingleRegisterID;
typedef ARMRegisters::FPDoubleRegisterID FPDoubleRegisterID;
diff --git a/Source/JavaScriptCore/assembler/AssemblerBuffer.h b/Source/JavaScriptCore/assembler/AssemblerBuffer.h
index 498dd09ac..c6e0a1003 100644
--- a/Source/JavaScriptCore/assembler/AssemblerBuffer.h
+++ b/Source/JavaScriptCore/assembler/AssemblerBuffer.h
@@ -129,12 +129,12 @@ namespace JSC {
return AssemblerLabel(m_index);
}
- PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData)
+ PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID)
{
if (!m_index)
return 0;
- RefPtr<ExecutableMemoryHandle> result = globalData.executableAllocator.allocate(globalData, m_index);
+ RefPtr<ExecutableMemoryHandle> result = globalData.executableAllocator.allocate(globalData, m_index, ownerUID);
if (!result)
return 0;
diff --git a/Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h b/Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h
index 0287d4829..68afa766b 100644
--- a/Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h
+++ b/Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h
@@ -195,10 +195,10 @@ public:
putIntegralUnchecked(value.low);
}
- PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData)
+ PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID)
{
flushConstantPool(false);
- return AssemblerBuffer::executableCopy(globalData);
+ return AssemblerBuffer::executableCopy(globalData, ownerUID);
}
void putShortWithConstantInt(uint16_t insn, uint32_t constant, bool isReusable = false)
diff --git a/Source/JavaScriptCore/assembler/LinkBuffer.h b/Source/JavaScriptCore/assembler/LinkBuffer.h
index 1be8af217..e8047e100 100644
--- a/Source/JavaScriptCore/assembler/LinkBuffer.h
+++ b/Source/JavaScriptCore/assembler/LinkBuffer.h
@@ -31,6 +31,9 @@
#define DUMP_LINK_STATISTICS 0
#define DUMP_CODE 0
+#define GLOBAL_THUNK_ID reinterpret_cast<void*>(static_cast<intptr_t>(-1))
+#define REGEXP_CODE_ID reinterpret_cast<void*>(static_cast<intptr_t>(-2))
+
#include <MacroAssembler.h>
#include <wtf/Noncopyable.h>
@@ -69,7 +72,7 @@ class LinkBuffer {
#endif
public:
- LinkBuffer(JSGlobalData& globalData, MacroAssembler* masm)
+ LinkBuffer(JSGlobalData& globalData, MacroAssembler* masm, void* ownerUID)
: m_size(0)
, m_code(0)
, m_assembler(masm)
@@ -78,7 +81,7 @@ public:
, m_completed(false)
#endif
{
- linkCode();
+ linkCode(ownerUID);
}
~LinkBuffer()
@@ -173,10 +176,7 @@ public:
return applyOffset(label.m_label).m_offset;
}
- // Upon completion of all patching either 'finalizeCode()' or 'finalizeCodeAddendum()' should be called
- // once to complete generation of the code. 'finalizeCode()' is suited to situations
- // where the executable pool must also be retained, the lighter-weight 'finalizeCodeAddendum()' is
- // suited to adding to an existing allocation.
+ // Upon completion of all patching 'finalizeCode()' should be called once to complete generation of the code.
CodeRef finalizeCode()
{
performFinalization();
@@ -210,18 +210,17 @@ private:
return src;
}
- // Keep this private! - the underlying code should only be obtained externally via
- // finalizeCode() or finalizeCodeAddendum().
+ // Keep this private! - the underlying code should only be obtained externally via finalizeCode().
void* code()
{
return m_code;
}
- void linkCode()
+ void linkCode(void* ownerUID)
{
ASSERT(!m_code);
#if !ENABLE(BRANCH_COMPACTION)
- m_executableMemory = m_assembler->m_assembler.executableCopy(*m_globalData);
+ m_executableMemory = m_assembler->m_assembler.executableCopy(*m_globalData, ownerUID);
if (!m_executableMemory)
return;
m_code = m_executableMemory->start();
@@ -229,7 +228,7 @@ private:
ASSERT(m_code);
#else
size_t initialSize = m_assembler->m_assembler.codeSize();
- m_executableMemory = m_globalData->executableAllocator.allocate(*m_globalData, initialSize);
+ m_executableMemory = m_globalData->executableAllocator.allocate(*m_globalData, initialSize, ownerUID);
if (!m_executableMemory)
return;
m_code = (uint8_t*)m_executableMemory->start();
diff --git a/Source/JavaScriptCore/assembler/MIPSAssembler.h b/Source/JavaScriptCore/assembler/MIPSAssembler.h
index da91a14f1..4471c1303 100644
--- a/Source/JavaScriptCore/assembler/MIPSAssembler.h
+++ b/Source/JavaScriptCore/assembler/MIPSAssembler.h
@@ -645,9 +645,9 @@ public:
return m_buffer.codeSize();
}
- PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData)
+ PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID)
{
- RefPtr<ExecutableMemoryHandle> result = m_buffer.executableCopy(globalData);
+ RefPtr<ExecutableMemoryHandle> result = m_buffer.executableCopy(globalData, ownerUID);
if (!result)
return 0;
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h b/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h
index 82e8c4151..c59d1514a 100644
--- a/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h
@@ -52,7 +52,7 @@
#define ASSERT_VALID_CODE_OFFSET(offset) // Anything goes!
#endif
-#if CPU(X86) && OS(WIN)
+#if CPU(X86) && OS(WINDOWS)
#define CALLING_CONVENTION_IS_STDCALL 1
#ifndef CDECL
#if COMPILER(MSVC)
@@ -126,7 +126,9 @@ public:
ASSERT_VALID_CODE_POINTER(m_value);
}
-#if CALLING_CONVENTION_IS_STDCALL
+// MSVC doesn't seem to treat functions with different calling conventions as
+// different types; these methods already defined for fastcall, below.
+#if CALLING_CONVENTION_IS_STDCALL && !OS(WINDOWS)
template<typename returnType>
FunctionPtr(returnType (CDECL *value)())
diff --git a/Source/JavaScriptCore/assembler/SH4Assembler.h b/Source/JavaScriptCore/assembler/SH4Assembler.h
index 90e232a63..0709588a5 100644
--- a/Source/JavaScriptCore/assembler/SH4Assembler.h
+++ b/Source/JavaScriptCore/assembler/SH4Assembler.h
@@ -1513,9 +1513,9 @@ public:
return reinterpret_cast<void*>(readPCrelativeAddress((*instructionPtr & 0xff), instructionPtr));
}
- PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData)
+ PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID)
{
- return m_buffer.executableCopy(globalData);
+ return m_buffer.executableCopy(globalData, ownerUID);
}
void prefix(uint16_t pre)
diff --git a/Source/JavaScriptCore/assembler/X86Assembler.h b/Source/JavaScriptCore/assembler/X86Assembler.h
index cd1921819..3b9e122cd 100644
--- a/Source/JavaScriptCore/assembler/X86Assembler.h
+++ b/Source/JavaScriptCore/assembler/X86Assembler.h
@@ -1782,9 +1782,9 @@ public:
return b.m_offset - a.m_offset;
}
- PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData)
+ PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID)
{
- return m_formatter.executableCopy(globalData);
+ return m_formatter.executableCopy(globalData, ownerUID);
}
#ifndef NDEBUG
@@ -2132,9 +2132,9 @@ private:
bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
void* data() const { return m_buffer.data(); }
- PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData)
+ PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID)
{
- return m_buffer.executableCopy(globalData);
+ return m_buffer.executableCopy(globalData, ownerUID);
}
#ifndef NDEBUG
diff --git a/Source/JavaScriptCore/bytecode/CallLinkInfo.h b/Source/JavaScriptCore/bytecode/CallLinkInfo.h
index 8ec48e4e1..44d50a971 100644
--- a/Source/JavaScriptCore/bytecode/CallLinkInfo.h
+++ b/Source/JavaScriptCore/bytecode/CallLinkInfo.h
@@ -72,7 +72,7 @@ struct CallLinkInfo : public BasicRawSentinelNode<CallLinkInfo> {
WriteBarrier<JSFunction> lastSeenCallee;
bool hasSeenShouldRepatch : 1;
bool isDFG : 1;
- CallType callType : 2;
+ CallType callType : 6;
unsigned bytecodeIndex;
bool isLinked() { return callee; }
diff --git a/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp b/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp
new file mode 100644
index 000000000..f3fd5bb27
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 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 "CallLinkStatus.h"
+
+#include "CodeBlock.h"
+
+namespace JSC {
+
+CallLinkStatus CallLinkStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex)
+{
+ UNUSED_PARAM(profiledBlock);
+ UNUSED_PARAM(bytecodeIndex);
+#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
+ return CallLinkStatus(
+ profiledBlock->getCallLinkInfo(bytecodeIndex).lastSeenCallee.get(),
+ profiledBlock->couldTakeSlowCase(bytecodeIndex));
+#else
+ return CallLinkStatus(0, false);
+#endif
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/bytecode/CallLinkStatus.h b/Source/JavaScriptCore/bytecode/CallLinkStatus.h
new file mode 100644
index 000000000..e1c741016
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/CallLinkStatus.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 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 CallLinkStatus_h
+#define CallLinkStatus_h
+
+namespace JSC {
+
+class JSFunction;
+class CodeBlock;
+
+class CallLinkStatus {
+public:
+ CallLinkStatus()
+ : m_callTarget(0)
+ , m_couldTakeSlowPath(false)
+ {
+ }
+
+ CallLinkStatus(JSFunction* callTarget, bool couldTakeSlowPath)
+ : m_callTarget(callTarget)
+ , m_couldTakeSlowPath(couldTakeSlowPath)
+ {
+ }
+
+ static CallLinkStatus computeFor(CodeBlock*, unsigned bytecodeIndex);
+
+ bool isSet() const { return !!m_callTarget; }
+
+ bool operator!() const { return !m_callTarget; }
+
+ bool couldTakeSlowPath() const { return m_couldTakeSlowPath; }
+
+ JSFunction* callTarget() const { return m_callTarget; }
+
+private:
+ JSFunction* m_callTarget;
+ bool m_couldTakeSlowPath;
+};
+
+} // namespace JSC
+
+#endif // CallLinkStatus_h
+
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index 47745268c..4a953266e 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -78,7 +78,7 @@ static UString valueToSourceString(ExecState* exec, JSValue val)
return "0";
if (val.isString())
- return makeUString("\"", escapeQuotes(val.toString(exec)), "\"");
+ return makeUString("\"", escapeQuotes(val.toString(exec)->value(exec)), "\"");
return val.description();
}
@@ -180,7 +180,16 @@ void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector<Instruction
int r1 = (++it)->u.operand;
int id0 = (++it)->u.operand;
printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
- it += 4;
+ it += 5;
+}
+
+void CodeBlock::printCallOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
+{
+ int func = (++it)->u.operand;
+ int argCount = (++it)->u.operand;
+ int registerOffset = (++it)->u.operand;
+ printf("[%4d] %s\t %s, %d, %d\n", location, op, registerName(exec, func).data(), argCount, registerOffset);
+ it += 2;
}
void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
@@ -522,7 +531,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
}
case op_convert_this: {
int r0 = (++it)->u.operand;
- printf("[%4d] convert_this %s\n", location, registerName(exec, r0).data());
+ printf("[%4d] convert_this\t %s\n", location, registerName(exec, r0).data());
break;
}
case op_new_object: {
@@ -734,6 +743,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
int r0 = (++it)->u.operand;
int id0 = (++it)->u.operand;
printf("[%4d] resolve\t\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data());
+ it++;
break;
}
case op_resolve_skip: {
@@ -741,13 +751,14 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
int id0 = (++it)->u.operand;
int skipLevels = (++it)->u.operand;
printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), skipLevels);
+ it++;
break;
}
case op_resolve_global: {
int r0 = (++it)->u.operand;
int id0 = (++it)->u.operand;
printf("[%4d] resolve_global\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data());
- it += 2;
+ it += 3;
break;
}
case op_resolve_global_dynamic: {
@@ -757,6 +768,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
++it;
int depth = (++it)->u.operand;
printf("[%4d] resolve_global_dynamic\t %s, %s, %s, %d\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).utf8().data(), idName(id0, m_identifiers[id0]).data(), depth);
+ ++it;
break;
}
case op_get_scoped_var: {
@@ -764,6 +776,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
int index = (++it)->u.operand;
int skipLevels = (++it)->u.operand;
printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(exec, r0).data(), index, skipLevels);
+ it++;
break;
}
case op_put_scoped_var: {
@@ -777,6 +790,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
int r0 = (++it)->u.operand;
int index = (++it)->u.operand;
printf("[%4d] get_global_var\t %s, %d\n", location, registerName(exec, r0).data(), index);
+ it++;
break;
}
case op_put_global_var: {
@@ -790,6 +804,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
int id0 = (++it)->u.operand;
int isStrict = (++it)->u.operand;
printf("[%4d] resolve_base%s\t %s, %s\n", location, isStrict ? "_strict" : "", registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data());
+ it++;
break;
}
case op_ensure_property_exists: {
@@ -803,6 +818,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
int r1 = (++it)->u.operand;
int id0 = (++it)->u.operand;
printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
+ it++;
break;
}
case op_resolve_with_this: {
@@ -810,6 +826,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
int r1 = (++it)->u.operand;
int id0 = (++it)->u.operand;
printf("[%4d] resolve_with_this %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
+ it++;
break;
}
case op_get_by_id: {
@@ -885,18 +902,12 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
printPutByIdOp(exec, location, it, "put_by_id_generic");
break;
}
- case op_put_getter: {
+ case op_put_getter_setter: {
int r0 = (++it)->u.operand;
int id0 = (++it)->u.operand;
int r1 = (++it)->u.operand;
- printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data());
- break;
- }
- case op_put_setter: {
- int r0 = (++it)->u.operand;
- int id0 = (++it)->u.operand;
- int r1 = (++it)->u.operand;
- printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data());
+ int r2 = (++it)->u.operand;
+ printf("[%4d] put_getter_setter\t %s, %s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
break;
}
case op_method_check: {
@@ -915,6 +926,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
int r1 = (++it)->u.operand;
int r2 = (++it)->u.operand;
printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
+ it++;
break;
}
case op_get_argument_by_val: {
@@ -922,6 +934,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
int r1 = (++it)->u.operand;
int r2 = (++it)->u.operand;
printf("[%4d] get_argument_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
+ ++it;
break;
}
case op_get_by_pname: {
@@ -1119,17 +1132,11 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
break;
}
case op_call: {
- int func = (++it)->u.operand;
- int argCount = (++it)->u.operand;
- int registerOffset = (++it)->u.operand;
- printf("[%4d] call\t\t %s, %d, %d\n", location, registerName(exec, func).data(), argCount, registerOffset);
+ printCallOp(exec, location, it, "call");
break;
}
case op_call_eval: {
- int func = (++it)->u.operand;
- int argCount = (++it)->u.operand;
- int registerOffset = (++it)->u.operand;
- printf("[%4d] call_eval\t %s, %d, %d\n", location, registerName(exec, func).data(), argCount, registerOffset);
+ printCallOp(exec, location, it, "call_eval");
break;
}
case op_call_varargs: {
@@ -1148,7 +1155,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
}
case op_tear_off_arguments: {
int r0 = (++it)->u.operand;
- printf("[%4d] tear_off_arguments\t %s\n", location, registerName(exec, r0).data());
+ printf("[%4d] tear_off_arguments %s\n", location, registerName(exec, r0).data());
break;
}
case op_ret: {
@@ -1159,6 +1166,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
case op_call_put_result: {
int r0 = (++it)->u.operand;
printf("[%4d] op_call_put_result\t\t %s\n", location, registerName(exec, r0).data());
+ it++;
break;
}
case op_ret_object_or_this: {
@@ -1168,10 +1176,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
break;
}
case op_construct: {
- int func = (++it)->u.operand;
- int argCount = (++it)->u.operand;
- int registerOffset = (++it)->u.operand;
- printf("[%4d] construct\t %s, %d, %d\n", location, registerName(exec, func).data(), argCount, registerOffset);
+ printCallOp(exec, location, it, "construct");
break;
}
case op_strcat: {
@@ -1446,6 +1451,9 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other, SymbolTable* symTab)
, m_speculativeFailCounter(0)
, m_optimizationDelayCounter(0)
, m_reoptimizationRetryCounter(0)
+#if ENABLE(JIT)
+ , m_canCompileWithDFGState(CompileWithDFGUnset)
+#endif
{
setNumParameters(other.numParameters());
optimizeAfterWarmUp();
@@ -2054,6 +2062,16 @@ void CodeBlock::createActivation(CallFrame* callFrame)
callFrame->uncheckedR(activationRegister()) = JSValue(activation);
callFrame->setScopeChain(callFrame->scopeChain()->push(activation));
}
+
+unsigned CodeBlock::addOrFindConstant(JSValue v)
+{
+ unsigned numberOfConstants = numberOfConstantRegisters();
+ for (unsigned i = 0; i < numberOfConstants; ++i) {
+ if (getConstant(FirstConstantRegisterIndex + i) == v)
+ return i;
+ }
+ return addConstant(v);
+}
#if ENABLE(JIT)
void CodeBlock::unlinkCalls()
@@ -2154,17 +2172,17 @@ JSObject* FunctionCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* s
return error;
}
-bool ProgramCodeBlock::canCompileWithDFG()
+bool ProgramCodeBlock::canCompileWithDFGInternal()
{
return DFG::canCompileProgram(this);
}
-bool EvalCodeBlock::canCompileWithDFG()
+bool EvalCodeBlock::canCompileWithDFGInternal()
{
return DFG::canCompileEval(this);
}
-bool FunctionCodeBlock::canCompileWithDFG()
+bool FunctionCodeBlock::canCompileWithDFGInternal()
{
if (m_isConstructor)
return DFG::canCompileFunctionForConstruct(this);
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h
index c440c72e1..23d6a6b6d 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.h
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h
@@ -94,7 +94,7 @@ namespace JSC {
Heap* m_heap;
public:
- virtual ~CodeBlock();
+ JS_EXPORT_PRIVATE virtual ~CodeBlock();
int numParameters() const { return m_numParameters; }
void setNumParameters(int newValue);
@@ -388,7 +388,22 @@ namespace JSC {
virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*) = 0;
virtual void jettison() = 0;
virtual CodeBlock* replacement() = 0;
- virtual bool canCompileWithDFG() = 0;
+
+ enum CompileWithDFGState {
+ CompileWithDFGFalse,
+ CompileWithDFGTrue,
+ CompileWithDFGUnset
+ };
+
+ virtual bool canCompileWithDFGInternal() = 0;
+ bool canCompileWithDFG()
+ {
+ bool result = canCompileWithDFGInternal();
+ m_canCompileWithDFGState = result ? CompileWithDFGTrue : CompileWithDFGFalse;
+ return result;
+ }
+ CompileWithDFGState canCompileWithDFGState() { return m_canCompileWithDFGState; }
+
bool hasOptimizedReplacement()
{
ASSERT(getJITType() == JITCode::BaselineJIT);
@@ -521,6 +536,11 @@ namespace JSC {
{
ValueProfile* result = WTF::genericBinarySearch<ValueProfile, int, getValueProfileBytecodeOffset>(m_valueProfiles, m_valueProfiles.size(), bytecodeOffset);
ASSERT(result->m_bytecodeOffset != -1);
+ ASSERT(!hasInstructions()
+ || instructions()[bytecodeOffset + opcodeLength(
+ m_globalData->interpreter->getOpcodeID(
+ instructions()[
+ bytecodeOffset].u.opcode)) - 1].u.profile == result);
return result;
}
@@ -664,10 +684,22 @@ namespace JSC {
return m_rareData && !!m_rareData->m_codeOrigins.size();
}
- CodeOrigin codeOriginForReturn(ReturnAddressPtr returnAddress)
+ bool codeOriginForReturn(ReturnAddressPtr returnAddress, CodeOrigin& codeOrigin)
{
- ASSERT(hasCodeOrigins());
- return binarySearch<CodeOriginAtCallReturnOffset, unsigned, getCallReturnOffsetForCodeOrigin>(codeOrigins().begin(), codeOrigins().size(), getJITCode().offsetOf(returnAddress.value()))->codeOrigin;
+ if (!hasCodeOrigins())
+ return false;
+ unsigned offset = getJITCode().offsetOf(returnAddress.value());
+ CodeOriginAtCallReturnOffset* entry = binarySearch<CodeOriginAtCallReturnOffset, unsigned, getCallReturnOffsetForCodeOrigin>(codeOrigins().begin(), codeOrigins().size(), offset, WTF::KeyMustNotBePresentInArray);
+ if (entry->callReturnOffset != offset)
+ return false;
+ codeOrigin = entry->codeOrigin;
+ return true;
+ }
+
+ CodeOrigin codeOrigin(unsigned index)
+ {
+ ASSERT(m_rareData);
+ return m_rareData->m_codeOrigins[index].codeOrigin;
}
bool addFrequentExitSite(const DFG::FrequentExitSite& site)
@@ -686,11 +718,14 @@ namespace JSC {
Identifier& identifier(int index) { return m_identifiers[index]; }
size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); }
- void addConstant(JSValue v)
+ unsigned addConstant(JSValue v)
{
+ unsigned result = m_constantRegisters.size();
m_constantRegisters.append(WriteBarrier<Unknown>());
m_constantRegisters.last().set(m_globalObject->globalData(), m_ownerExecutable.get(), v);
+ return result;
}
+ unsigned addOrFindConstant(JSValue);
WriteBarrier<Unknown>& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); }
@@ -780,7 +815,7 @@ namespace JSC {
// Functions for controlling when tiered compilation kicks in. This
// controls both when the optimizing compiler is invoked and when OSR
// entry happens. Two triggers exist: the loop trigger and the return
- // trigger. In either case, when an addition to m_executeCounter
+ // trigger. In either case, when an addition to m_jitExecuteCounter
// causes it to become non-negative, the optimizing compiler is
// invoked. This includes a fast check to see if this CodeBlock has
// already been optimized (i.e. replacement() returns a CodeBlock
@@ -821,14 +856,14 @@ namespace JSC {
return Options::executionCounterValueForOptimizeAfterLongWarmUp << reoptimizationRetryCounter();
}
- int32_t* addressOfExecuteCounter()
+ int32_t* addressOfJITExecuteCounter()
{
- return &m_executeCounter;
+ return &m_jitExecuteCounter;
}
- static ptrdiff_t offsetOfExecuteCounter() { return OBJECT_OFFSETOF(CodeBlock, m_executeCounter); }
+ static ptrdiff_t offsetOfJITExecuteCounter() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter); }
- int32_t executeCounter() const { return m_executeCounter; }
+ int32_t jitExecuteCounter() const { return m_jitExecuteCounter; }
unsigned optimizationDelayCounter() const { return m_optimizationDelayCounter; }
@@ -837,7 +872,7 @@ namespace JSC {
// expensive than executing baseline code.
void optimizeNextInvocation()
{
- m_executeCounter = Options::executionCounterValueForOptimizeNextInvocation;
+ m_jitExecuteCounter = Options::executionCounterValueForOptimizeNextInvocation;
}
// Call this to prevent optimization from happening again. Note that
@@ -847,7 +882,7 @@ namespace JSC {
// the future as well.
void dontOptimizeAnytimeSoon()
{
- m_executeCounter = Options::executionCounterValueForDontOptimizeAnytimeSoon;
+ m_jitExecuteCounter = Options::executionCounterValueForDontOptimizeAnytimeSoon;
}
// Call this to reinitialize the counter to its starting state,
@@ -858,14 +893,14 @@ namespace JSC {
// counter that this corresponds to is also available directly.
void optimizeAfterWarmUp()
{
- m_executeCounter = counterValueForOptimizeAfterWarmUp();
+ m_jitExecuteCounter = counterValueForOptimizeAfterWarmUp();
}
// Call this to force an optimization trigger to fire only after
// a lot of warm-up.
void optimizeAfterLongWarmUp()
{
- m_executeCounter = counterValueForOptimizeAfterLongWarmUp();
+ m_jitExecuteCounter = counterValueForOptimizeAfterLongWarmUp();
}
// Call this to cause an optimization trigger to fire soon, but
@@ -888,7 +923,7 @@ namespace JSC {
// in the baseline code.
void optimizeSoon()
{
- m_executeCounter = Options::executionCounterValueForOptimizeSoon << reoptimizationRetryCounter();
+ m_jitExecuteCounter = Options::executionCounterValueForOptimizeSoon << reoptimizationRetryCounter();
}
// The speculative JIT tracks its success rate, so that we can
@@ -989,6 +1024,7 @@ namespace JSC {
void printBinaryOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
void printConditionalJump(ExecState*, const Vector<Instruction>::const_iterator&, Vector<Instruction>::const_iterator&, int location, const char* op) const;
void printGetByIdOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
+ void printCallOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
void printPutByIdOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
#endif
void visitStructures(SlotVisitor&, Instruction* vPC) const;
@@ -1129,7 +1165,7 @@ namespace JSC {
OwnPtr<CodeBlock> m_alternative;
- int32_t m_executeCounter;
+ int32_t m_jitExecuteCounter;
uint32_t m_speculativeSuccessCounter;
uint32_t m_speculativeFailCounter;
uint8_t m_optimizationDelayCounter;
@@ -1169,6 +1205,9 @@ namespace JSC {
friend void WTF::deleteOwnedPtr<RareData>(RareData*);
#endif
OwnPtr<RareData> m_rareData;
+#if ENABLE(JIT)
+ CompileWithDFGState m_canCompileWithDFGState;
+#endif
};
// Program code is not marked by any function, so we make the global object
@@ -1208,7 +1247,7 @@ namespace JSC {
virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
virtual void jettison();
virtual CodeBlock* replacement();
- virtual bool canCompileWithDFG();
+ virtual bool canCompileWithDFGInternal();
#endif
};
@@ -1242,7 +1281,7 @@ namespace JSC {
virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
virtual void jettison();
virtual CodeBlock* replacement();
- virtual bool canCompileWithDFG();
+ virtual bool canCompileWithDFGInternal();
#endif
private:
@@ -1279,7 +1318,7 @@ namespace JSC {
virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
virtual void jettison();
virtual CodeBlock* replacement();
- virtual bool canCompileWithDFG();
+ virtual bool canCompileWithDFGInternal();
#endif
};
diff --git a/Source/JavaScriptCore/bytecode/CodeOrigin.h b/Source/JavaScriptCore/bytecode/CodeOrigin.h
index 7b6ce7d48..25a116c55 100644
--- a/Source/JavaScriptCore/bytecode/CodeOrigin.h
+++ b/Source/JavaScriptCore/bytecode/CodeOrigin.h
@@ -38,29 +38,37 @@ class ExecutableBase;
class JSFunction;
struct CodeOrigin {
- uint32_t bytecodeIndex;
+ // Bytecode offset that you'd use to re-execute this instruction.
+ unsigned bytecodeIndex : 29;
+ // Bytecode offset corresponding to the opcode that gives the result (needed to handle
+ // op_call/op_call_put_result and op_method_check/op_get_by_id).
+ unsigned valueProfileOffset : 3;
+
InlineCallFrame* inlineCallFrame;
CodeOrigin()
: bytecodeIndex(std::numeric_limits<uint32_t>::max())
+ , valueProfileOffset(0)
, inlineCallFrame(0)
{
}
- explicit CodeOrigin(uint32_t bytecodeIndex)
- : bytecodeIndex(bytecodeIndex)
- , inlineCallFrame(0)
- {
- }
-
- explicit CodeOrigin(uint32_t bytecodeIndex, InlineCallFrame* inlineCallFrame)
+ explicit CodeOrigin(unsigned bytecodeIndex, InlineCallFrame* inlineCallFrame = 0, unsigned valueProfileOffset = 0)
: bytecodeIndex(bytecodeIndex)
+ , valueProfileOffset(valueProfileOffset)
, inlineCallFrame(inlineCallFrame)
{
+ ASSERT(bytecodeIndex < (1u << 29));
+ ASSERT(valueProfileOffset < (1u << 3));
}
bool isSet() const { return bytecodeIndex != std::numeric_limits<uint32_t>::max(); }
+ unsigned bytecodeIndexForValueProfile() const
+ {
+ return bytecodeIndex + valueProfileOffset;
+ }
+
// The inline depth is the depth of the inline stack, so 1 = not inlined,
// 2 = inlined one deep, etc.
unsigned inlineDepth() const;
diff --git a/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp b/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
new file mode 100644
index 000000000..5eff1d4a0
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2012 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 "GetByIdStatus.h"
+
+#include "CodeBlock.h"
+
+namespace JSC {
+
+GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
+{
+ UNUSED_PARAM(profiledBlock);
+ UNUSED_PARAM(bytecodeIndex);
+ UNUSED_PARAM(ident);
+#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
+ // First check if it makes either calls, in which case we want to be super careful, or
+ // if it's not set at all, in which case we punt.
+ StructureStubInfo& stubInfo = profiledBlock->getStubInfo(bytecodeIndex);
+ if (!stubInfo.seen)
+ return GetByIdStatus(NoInformation, StructureSet(), notFound);
+
+ PolymorphicAccessStructureList* list;
+ int listSize;
+ switch (stubInfo.accessType) {
+ case access_get_by_id_self_list:
+ list = stubInfo.u.getByIdSelfList.structureList;
+ listSize = stubInfo.u.getByIdSelfList.listSize;
+ break;
+ case access_get_by_id_proto_list:
+ list = stubInfo.u.getByIdProtoList.structureList;
+ listSize = stubInfo.u.getByIdProtoList.listSize;
+ break;
+ default:
+ list = 0;
+ listSize = 0;
+ break;
+ }
+ for (int i = 0; i < listSize; ++i) {
+ if (!list->list[i].isDirect)
+ return GetByIdStatus(MakesCalls, StructureSet(), notFound);
+ }
+
+ // Next check if it takes slow case, in which case we want to be kind of careful.
+ if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex))
+ return GetByIdStatus(TakesSlowPath, StructureSet(), notFound);
+
+ // Finally figure out if we can derive an access strategy.
+ GetByIdStatus result;
+ switch (stubInfo.accessType) {
+ case access_unset:
+ return GetByIdStatus(NoInformation, StructureSet(), notFound);
+
+ case access_get_by_id_self: {
+ Structure* structure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
+ result.m_offset = structure->get(*profiledBlock->globalData(), ident);
+
+ if (result.m_offset != notFound)
+ result.m_structureSet.add(structure);
+
+ if (result.m_offset != notFound)
+ ASSERT(result.m_structureSet.size());
+ break;
+ }
+
+ case access_get_by_id_self_list: {
+ PolymorphicAccessStructureList* list = stubInfo.u.getByIdProtoList.structureList;
+ unsigned size = stubInfo.u.getByIdProtoList.listSize;
+ for (unsigned i = 0; i < size; ++i) {
+ ASSERT(list->list[i].isDirect);
+
+ Structure* structure = list->list[i].base.get();
+ if (result.m_structureSet.contains(structure))
+ continue;
+
+ size_t myOffset = structure->get(*profiledBlock->globalData(), ident);
+
+ if (myOffset == notFound) {
+ result.m_offset = notFound;
+ break;
+ }
+
+ if (!i)
+ result.m_offset = myOffset;
+ else if (result.m_offset != myOffset) {
+ result.m_offset = notFound;
+ break;
+ }
+
+ result.m_structureSet.add(structure);
+ }
+
+ if (result.m_offset != notFound)
+ ASSERT(result.m_structureSet.size());
+ break;
+ }
+
+ default:
+ ASSERT(result.m_offset == notFound);
+ break;
+ }
+
+ if (result.m_offset == notFound) {
+ result.m_state = TakesSlowPath;
+ result.m_structureSet.clear();
+ } else
+ result.m_state = SimpleDirect;
+
+ return result;
+#else // ENABLE(JIT)
+ return GetByIdStatus(NoInformation, StructureSet(), notFound);
+#endif // ENABLE(JIT)
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/bytecode/GetByIdStatus.h b/Source/JavaScriptCore/bytecode/GetByIdStatus.h
new file mode 100644
index 000000000..00e50e76d
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/GetByIdStatus.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2012 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 GetByIdStatus_h
+#define GetByIdStatus_h
+
+#include "StructureSet.h"
+#include <wtf/NotFound.h>
+
+namespace JSC {
+
+class CodeBlock;
+class Identifier;
+
+class GetByIdStatus {
+public:
+ enum State {
+ NoInformation, // It's uncached so we have no information.
+ SimpleDirect, // It's cached for a direct access to a known object property.
+ TakesSlowPath, // It's known to often take slow path.
+ MakesCalls // It's known to take paths that make calls.
+ };
+
+ GetByIdStatus()
+ : m_state(NoInformation)
+ , m_offset(notFound)
+ {
+ }
+
+ GetByIdStatus(State state, const StructureSet& structureSet, size_t offset)
+ : m_state(state)
+ , m_structureSet(structureSet)
+ , m_offset(offset)
+ {
+ ASSERT((state == SimpleDirect) == (offset != notFound));
+ }
+
+ static GetByIdStatus computeFor(CodeBlock*, unsigned bytecodeIndex, Identifier&);
+
+ State state() const { return m_state; }
+
+ bool isSet() const { return m_state != NoInformation; }
+ bool operator!() const { return !isSet(); }
+ bool isSimpleDirect() const { return m_state == SimpleDirect; }
+ bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls; }
+ bool makesCalls() const { return m_state == MakesCalls; }
+
+ const StructureSet& structureSet() const { return m_structureSet; }
+ size_t offset() const { return m_offset; }
+
+private:
+ State m_state;
+ StructureSet m_structureSet;
+ size_t m_offset;
+};
+
+} // namespace JSC
+
+#endif // PropertyAccessStatus_h
+
diff --git a/Source/JavaScriptCore/bytecode/Instruction.h b/Source/JavaScriptCore/bytecode/Instruction.h
index 7e4413065..92118eeb2 100644
--- a/Source/JavaScriptCore/bytecode/Instruction.h
+++ b/Source/JavaScriptCore/bytecode/Instruction.h
@@ -48,6 +48,7 @@ namespace JSC {
class JSCell;
class Structure;
class StructureChain;
+ struct ValueProfile;
#if ENABLE(JIT)
typedef MacroAssemblerCodeRef PolymorphicAccessStructureListStubRoutineType;
@@ -99,6 +100,10 @@ namespace JSC {
}
} list[POLYMORPHIC_LIST_CACHE_SIZE];
+ PolymorphicAccessStructureList()
+ {
+ }
+
PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, bool isDirect)
{
list[0].set(globalData, owner, stubRoutine, firstBase, isDirect);
@@ -176,6 +181,8 @@ namespace JSC {
}
Instruction(PropertySlot::GetValueFunc getterFunc) { u.getterFunc = getterFunc; }
+
+ Instruction(ValueProfile* profile) { u.profile = profile; }
union {
Opcode opcode;
@@ -184,6 +191,7 @@ namespace JSC {
WriteBarrierBase<StructureChain> structureChain;
WriteBarrierBase<JSCell> jsCell;
PropertySlot::GetValueFunc getterFunc;
+ ValueProfile* profile;
} u;
private:
diff --git a/Source/JavaScriptCore/bytecode/MethodCallLinkStatus.cpp b/Source/JavaScriptCore/bytecode/MethodCallLinkStatus.cpp
new file mode 100644
index 000000000..e7d721c29
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/MethodCallLinkStatus.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 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 "MethodCallLinkStatus.h"
+
+#include "CodeBlock.h"
+
+namespace JSC {
+
+MethodCallLinkStatus MethodCallLinkStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex)
+{
+ UNUSED_PARAM(profiledBlock);
+ UNUSED_PARAM(bytecodeIndex);
+#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
+ MethodCallLinkInfo& methodCall = profiledBlock->getMethodCallLinkInfo(bytecodeIndex);
+
+ if (!methodCall.seen || !methodCall.cachedStructure)
+ return MethodCallLinkStatus();
+
+ if (methodCall.cachedPrototype.get() == profiledBlock->globalObject()->methodCallDummy()) {
+ return MethodCallLinkStatus(
+ methodCall.cachedStructure.get(),
+ 0,
+ methodCall.cachedFunction.get(),
+ 0);
+ }
+
+ return MethodCallLinkStatus(
+ methodCall.cachedStructure.get(),
+ methodCall.cachedPrototypeStructure.get(),
+ methodCall.cachedFunction.get(),
+ methodCall.cachedPrototype.get());
+#else // ENABLE(JIT)
+ return MethodCallLinkStatus();
+#endif // ENABLE(JIT)
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/bytecode/MethodCallLinkStatus.h b/Source/JavaScriptCore/bytecode/MethodCallLinkStatus.h
new file mode 100644
index 000000000..c3d11a1d8
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/MethodCallLinkStatus.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2012 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 MethodCallLinkStatus_h
+#define MethodCallLinkStatus_h
+
+namespace JSC {
+
+class CodeBlock;
+class JSObject;
+class Structure;
+
+class MethodCallLinkStatus {
+public:
+ MethodCallLinkStatus()
+ : m_structure(0)
+ , m_prototypeStructure(0)
+ , m_function(0)
+ , m_prototype(0)
+ {
+ }
+
+ MethodCallLinkStatus(
+ Structure* structure,
+ Structure* prototypeStructure,
+ JSObject* function,
+ JSObject* prototype)
+ : m_structure(structure)
+ , m_prototypeStructure(prototypeStructure)
+ , m_function(function)
+ , m_prototype(prototype)
+ {
+ if (!m_function) {
+ ASSERT(!m_structure);
+ ASSERT(!m_prototypeStructure);
+ ASSERT(!m_prototype);
+ } else
+ ASSERT(m_structure);
+
+ ASSERT(!m_prototype == !m_prototypeStructure);
+ }
+
+ static MethodCallLinkStatus computeFor(CodeBlock*, unsigned bytecodeIndex);
+
+ bool isSet() const { return !!m_function; }
+ bool operator!() const { return !m_function; }
+
+ bool needsPrototypeCheck() const { return !!m_prototype; }
+
+ Structure* structure() { return m_structure; }
+ Structure* prototypeStructure() { return m_prototypeStructure; }
+ JSObject* function() const { return m_function; }
+ JSObject* prototype() const { return m_prototype; }
+
+private:
+ Structure* m_structure;
+ Structure* m_prototypeStructure;
+ JSObject* m_function;
+ JSObject* m_prototype;
+};
+
+} // namespace JSC
+
+#endif // MethodCallLinkStatus_h
+
diff --git a/Source/JavaScriptCore/bytecode/Opcode.h b/Source/JavaScriptCore/bytecode/Opcode.h
index 4801e4c32..57633a338 100644
--- a/Source/JavaScriptCore/bytecode/Opcode.h
+++ b/Source/JavaScriptCore/bytecode/Opcode.h
@@ -95,45 +95,44 @@ namespace JSC {
macro(op_is_function, 3) \
macro(op_in, 4) \
\
- macro(op_resolve, 3) \
- macro(op_resolve_skip, 4) \
- macro(op_resolve_global, 5) \
- macro(op_resolve_global_dynamic, 6) \
- macro(op_get_scoped_var, 4) \
+ macro(op_resolve, 4) /* has value profiling */ \
+ macro(op_resolve_skip, 5) /* has value profiling */ \
+ macro(op_resolve_global, 6) /* has value profiling */ \
+ macro(op_resolve_global_dynamic, 7) /* has value profiling */ \
+ macro(op_get_scoped_var, 5) /* has value profiling */ \
macro(op_put_scoped_var, 4) \
- macro(op_get_global_var, 3) \
+ macro(op_get_global_var, 4) /* has value profiling */ \
macro(op_put_global_var, 3) \
- macro(op_resolve_base, 4) \
+ macro(op_resolve_base, 5) /* has value profiling */ \
macro(op_ensure_property_exists, 3) \
- macro(op_resolve_with_base, 4) \
- macro(op_resolve_with_this, 4) \
- macro(op_get_by_id, 8) \
- macro(op_get_by_id_self, 8) \
- macro(op_get_by_id_proto, 8) \
- macro(op_get_by_id_chain, 8) \
- macro(op_get_by_id_getter_self, 8) \
- macro(op_get_by_id_getter_proto, 8) \
- macro(op_get_by_id_getter_chain, 8) \
- macro(op_get_by_id_custom_self, 8) \
- macro(op_get_by_id_custom_proto, 8) \
- macro(op_get_by_id_custom_chain, 8) \
- macro(op_get_by_id_generic, 8) \
- macro(op_get_array_length, 8) \
- macro(op_get_string_length, 8) \
+ macro(op_resolve_with_base, 5) /* has value profiling */ \
+ macro(op_resolve_with_this, 5) /* has value profiling */ \
+ macro(op_get_by_id, 9) /* has value profiling */ \
+ macro(op_get_by_id_self, 9) /* has value profiling */ \
+ macro(op_get_by_id_proto, 9) /* has value profiling */ \
+ macro(op_get_by_id_chain, 9) /* has value profiling */ \
+ macro(op_get_by_id_getter_self, 9) /* has value profiling */ \
+ macro(op_get_by_id_getter_proto, 9) /* has value profiling */ \
+ macro(op_get_by_id_getter_chain, 9) /* has value profiling */ \
+ macro(op_get_by_id_custom_self, 9) /* has value profiling */ \
+ macro(op_get_by_id_custom_proto, 9) /* has value profiling */ \
+ macro(op_get_by_id_custom_chain, 9) /* has value profiling */ \
+ macro(op_get_by_id_generic, 9) /* has value profiling */ \
+ macro(op_get_array_length, 9) /* has value profiling */ \
+ macro(op_get_string_length, 9) /* has value profiling */ \
macro(op_get_arguments_length, 4) \
macro(op_put_by_id, 9) \
macro(op_put_by_id_transition, 9) \
macro(op_put_by_id_replace, 9) \
macro(op_put_by_id_generic, 9) \
macro(op_del_by_id, 4) \
- macro(op_get_by_val, 4) \
- macro(op_get_argument_by_val, 4) \
+ macro(op_get_by_val, 5) /* has value profiling */ \
+ macro(op_get_argument_by_val, 5) /* must be the same size as op_get_by_val */ \
macro(op_get_by_pname, 7) \
macro(op_put_by_val, 4) \
macro(op_del_by_val, 4) \
macro(op_put_by_index, 4) \
- macro(op_put_getter, 4) \
- macro(op_put_setter, 4) \
+ macro(op_put_getter_setter, 5) \
\
macro(op_jmp, 2) \
macro(op_jtrue, 3) \
@@ -170,7 +169,7 @@ namespace JSC {
macro(op_tear_off_activation, 3) \
macro(op_tear_off_arguments, 2) \
macro(op_ret, 2) \
- macro(op_call_put_result, 2) \
+ macro(op_call_put_result, 3) /* has value profiling */ \
macro(op_ret_object_or_this, 3) \
macro(op_method_check, 1) \
\
diff --git a/Source/JavaScriptCore/bytecode/PredictedType.cpp b/Source/JavaScriptCore/bytecode/PredictedType.cpp
index 9356390a9..4b07ff446 100644
--- a/Source/JavaScriptCore/bytecode/PredictedType.cpp
+++ b/Source/JavaScriptCore/bytecode/PredictedType.cpp
@@ -92,6 +92,11 @@ const char* predictionToString(PredictedType value)
ptr.strcat("Uint8array");
else
isTop = false;
+
+ if (value & PredictUint8ClampedArray)
+ ptr.strcat("Uint8clampedarray");
+ else
+ isTop = false;
if (value & PredictUint16Array)
ptr.strcat("Uint16array");
@@ -184,6 +189,8 @@ PredictedType predictionFromClassInfo(const ClassInfo* classInfo)
return PredictInt32Array;
case TypedArrayUint8:
return PredictUint8Array;
+ case TypedArrayUint8Clamped:
+ return PredictUint8ClampedArray;
case TypedArrayUint16:
return PredictUint16Array;
case TypedArrayUint32:
diff --git a/Source/JavaScriptCore/bytecode/PredictedType.h b/Source/JavaScriptCore/bytecode/PredictedType.h
index 3ec03924a..47583361d 100644
--- a/Source/JavaScriptCore/bytecode/PredictedType.h
+++ b/Source/JavaScriptCore/bytecode/PredictedType.h
@@ -36,33 +36,34 @@ namespace JSC {
class Structure;
typedef uint32_t PredictedType;
-static const PredictedType PredictNone = 0x00000000; // We don't know anything yet.
-static const PredictedType PredictFinalObject = 0x00000001; // It's definitely a JSFinalObject.
-static const PredictedType PredictArray = 0x00000002; // It's definitely a JSArray.
-static const PredictedType PredictByteArray = 0x00000004; // It's definitely a JSByteArray or one of its subclasses.
-static const PredictedType PredictFunction = 0x00000008; // It's definitely a JSFunction or one of its subclasses.
-static const PredictedType PredictInt8Array = 0x00000010; // It's definitely an Int8Array or one of its subclasses.
-static const PredictedType PredictInt16Array = 0x00000020; // It's definitely an Int16Array or one of its subclasses.
-static const PredictedType PredictInt32Array = 0x00000040; // It's definitely an Int32Array or one of its subclasses.
-static const PredictedType PredictUint8Array = 0x00000080; // It's definitely an Uint8Array or one of its subclasses.
-static const PredictedType PredictUint16Array = 0x00000100; // It's definitely an Uint16Array or one of its subclasses.
-static const PredictedType PredictUint32Array = 0x00000200; // It's definitely an Uint32Array or one of its subclasses.
-static const PredictedType PredictFloat32Array = 0x00000400; // It's definitely an Uint16Array or one of its subclasses.
-static const PredictedType PredictFloat64Array = 0x00000800; // It's definitely an Uint16Array or one of its subclasses.
-static const PredictedType PredictObjectOther = 0x00001000; // It's definitely an object but not JSFinalObject, JSArray, JSByteArray, or JSFunction.
-static const PredictedType PredictObjectMask = 0x00001fff; // Bitmask used for testing for any kind of object prediction.
-static const PredictedType PredictString = 0x00002000; // It's definitely a JSString.
-static const PredictedType PredictCellOther = 0x00004000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString.
-static const PredictedType PredictCell = 0x00007fff; // It's definitely a JSCell.
-static const PredictedType PredictInt32 = 0x00008000; // It's definitely an Int32.
-static const PredictedType PredictDoubleReal = 0x00010000; // It's definitely a non-NaN double.
-static const PredictedType PredictDoubleNaN = 0x00020000; // It's definitely a NaN.
-static const PredictedType PredictDouble = 0x00030000; // It's either a non-NaN or a NaN double.
-static const PredictedType PredictNumber = 0x00038000; // It's either an Int32 or a Double.
-static const PredictedType PredictBoolean = 0x00040000; // It's definitely a Boolean.
-static const PredictedType PredictOther = 0x40000000; // It's definitely none of the above.
-static const PredictedType PredictTop = 0x7fffffff; // It can be any of the above.
-static const PredictedType FixedIndexedStorageMask = PredictByteArray | PredictInt8Array | PredictInt16Array | PredictInt32Array | PredictUint8Array | PredictUint16Array | PredictUint32Array | PredictFloat32Array | PredictFloat64Array;
+static const PredictedType PredictNone = 0x00000000; // We don't know anything yet.
+static const PredictedType PredictFinalObject = 0x00000001; // It's definitely a JSFinalObject.
+static const PredictedType PredictArray = 0x00000002; // It's definitely a JSArray.
+static const PredictedType PredictByteArray = 0x00000004; // It's definitely a JSByteArray or one of its subclasses.
+static const PredictedType PredictFunction = 0x00000008; // It's definitely a JSFunction or one of its subclasses.
+static const PredictedType PredictInt8Array = 0x00000010; // It's definitely an Int8Array or one of its subclasses.
+static const PredictedType PredictInt16Array = 0x00000020; // It's definitely an Int16Array or one of its subclasses.
+static const PredictedType PredictInt32Array = 0x00000040; // It's definitely an Int32Array or one of its subclasses.
+static const PredictedType PredictUint8Array = 0x00000080; // It's definitely an Uint8Array or one of its subclasses.
+static const PredictedType PredictUint8ClampedArray = 0x00000100; // It's definitely an Uint8ClampedArray or one of its subclasses.
+static const PredictedType PredictUint16Array = 0x00000200; // It's definitely an Uint16Array or one of its subclasses.
+static const PredictedType PredictUint32Array = 0x00000400; // It's definitely an Uint32Array or one of its subclasses.
+static const PredictedType PredictFloat32Array = 0x00000800; // It's definitely an Uint16Array or one of its subclasses.
+static const PredictedType PredictFloat64Array = 0x00001000; // It's definitely an Uint16Array or one of its subclasses.
+static const PredictedType PredictObjectOther = 0x00002000; // It's definitely an object but not JSFinalObject, JSArray, JSByteArray, or JSFunction.
+static const PredictedType PredictObjectMask = 0x00003fff; // Bitmask used for testing for any kind of object prediction.
+static const PredictedType PredictString = 0x00004000; // It's definitely a JSString.
+static const PredictedType PredictCellOther = 0x00008000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString.
+static const PredictedType PredictCell = 0x0000ffff; // It's definitely a JSCell.
+static const PredictedType PredictInt32 = 0x00010000; // It's definitely an Int32.
+static const PredictedType PredictDoubleReal = 0x00020000; // It's definitely a non-NaN double.
+static const PredictedType PredictDoubleNaN = 0x00040000; // It's definitely a NaN.
+static const PredictedType PredictDouble = 0x00060000; // It's either a non-NaN or a NaN double.
+static const PredictedType PredictNumber = 0x00070000; // It's either an Int32 or a Double.
+static const PredictedType PredictBoolean = 0x00080000; // It's definitely a Boolean.
+static const PredictedType PredictOther = 0x40000000; // It's definitely none of the above.
+static const PredictedType PredictTop = 0x7fffffff; // It can be any of the above.
+static const PredictedType FixedIndexedStorageMask = PredictByteArray | PredictInt8Array | PredictInt16Array | PredictInt32Array | PredictUint8Array | PredictUint8ClampedArray | PredictUint16Array | PredictUint32Array | PredictFloat32Array | PredictFloat64Array;
typedef bool (*PredictionChecker)(PredictedType);
@@ -131,6 +132,11 @@ inline bool isUint8ArrayPrediction(PredictedType value)
return value == PredictUint8Array;
}
+inline bool isUint8ClampedArrayPrediction(PredictedType value)
+{
+ return value == PredictUint8ClampedArray;
+}
+
inline bool isUint16ArrayPrediction(PredictedType value)
{
return value == PredictUint16Array;
@@ -161,6 +167,7 @@ inline bool isActionableMutableArrayPrediction(PredictedType value)
#endif
|| isInt32ArrayPrediction(value)
|| isUint8ArrayPrediction(value)
+ || isUint8ClampedArrayPrediction(value)
|| isUint16ArrayPrediction(value)
|| isUint32ArrayPrediction(value)
#if CPU(X86) || CPU(X86_64)
diff --git a/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp b/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
new file mode 100644
index 000000000..45a5e614c
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 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 "PutByIdStatus.h"
+
+#include "CodeBlock.h"
+#include "Structure.h"
+#include "StructureChain.h"
+
+namespace JSC {
+
+PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
+{
+ UNUSED_PARAM(profiledBlock);
+ UNUSED_PARAM(bytecodeIndex);
+ UNUSED_PARAM(ident);
+#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
+ if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex))
+ return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound);
+
+ StructureStubInfo& stubInfo = profiledBlock->getStubInfo(bytecodeIndex);
+ if (!stubInfo.seen)
+ return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
+
+ switch (stubInfo.accessType) {
+ case access_unset:
+ return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
+
+ case access_put_by_id_replace: {
+ size_t offset = stubInfo.u.putByIdReplace.baseObjectStructure->get(
+ *profiledBlock->globalData(), ident);
+ if (offset != notFound) {
+ return PutByIdStatus(
+ SimpleReplace,
+ stubInfo.u.putByIdReplace.baseObjectStructure.get(),
+ 0, 0,
+ offset);
+ }
+ return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound);
+ }
+
+ case access_put_by_id_transition_normal:
+ case access_put_by_id_transition_direct: {
+ size_t offset = stubInfo.u.putByIdTransition.structure->get(
+ *profiledBlock->globalData(), ident);
+ if (offset != notFound) {
+ return PutByIdStatus(
+ SimpleTransition,
+ stubInfo.u.putByIdTransition.previousStructure.get(),
+ stubInfo.u.putByIdTransition.structure.get(),
+ stubInfo.u.putByIdTransition.chain.get(),
+ offset);
+ }
+ return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound);
+ }
+
+ default:
+ return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound);
+ }
+#else // ENABLE(JIT)
+ return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
+#endif // ENABLE(JIT)
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/bytecode/PutByIdStatus.h b/Source/JavaScriptCore/bytecode/PutByIdStatus.h
new file mode 100644
index 000000000..b33f4d09c
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/PutByIdStatus.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2012 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 PutByIdStatus_h
+#define PutByIdStatus_h
+
+#include <wtf/NotFound.h>
+
+namespace JSC {
+
+class CodeBlock;
+class Identifier;
+class Structure;
+class StructureChain;
+
+class PutByIdStatus {
+public:
+ enum State {
+ // It's uncached so we have no information.
+ NoInformation,
+ // It's cached as a direct store into an object property for cases where the object
+ // already has the property.
+ SimpleReplace,
+ // It's cached as a transition from one structure that lacks the property to one that
+ // includes the property, and a direct store to this new property.
+ SimpleTransition,
+ // It's known to often take slow path.
+ TakesSlowPath
+ };
+
+ PutByIdStatus()
+ : m_state(NoInformation)
+ , m_oldStructure(0)
+ , m_newStructure(0)
+ , m_structureChain(0)
+ , m_offset(notFound)
+ {
+ }
+
+ PutByIdStatus(
+ State state,
+ Structure* oldStructure,
+ Structure* newStructure,
+ StructureChain* structureChain,
+ size_t offset)
+ : m_state(state)
+ , m_oldStructure(oldStructure)
+ , m_newStructure(newStructure)
+ , m_structureChain(structureChain)
+ , m_offset(offset)
+ {
+ ASSERT((m_state == NoInformation || m_state == TakesSlowPath) == !m_oldStructure);
+ ASSERT((m_state != SimpleTransition) == !m_newStructure);
+ ASSERT((m_state != SimpleTransition) == !m_structureChain);
+ ASSERT((m_state == NoInformation || m_state == TakesSlowPath) == (m_offset == notFound));
+ }
+
+ static PutByIdStatus computeFor(CodeBlock*, unsigned bytecodeIndex, Identifier&);
+
+ State state() const { return m_state; }
+
+ bool isSet() const { return m_state != NoInformation; }
+ bool operator!() const { return m_state == NoInformation; }
+ bool isSimpleReplace() const { return m_state == SimpleReplace; }
+ bool isSimpleTransition() const { return m_state == SimpleTransition; }
+ bool takesSlowPath() const { return m_state == TakesSlowPath; }
+
+ Structure* oldStructure() const { return m_oldStructure; }
+ Structure* newStructure() const { return m_newStructure; }
+ StructureChain* structureChain() const { return m_structureChain; }
+ size_t offset() const { return m_offset; }
+
+private:
+ State m_state;
+ Structure* m_oldStructure;
+ Structure* m_newStructure;
+ StructureChain* m_structureChain;
+ size_t m_offset;
+};
+
+} // namespace JSC
+
+#endif // PutByIdStatus_h
+
diff --git a/Source/JavaScriptCore/bytecode/SamplingTool.h b/Source/JavaScriptCore/bytecode/SamplingTool.h
index b69ef026e..32a44ad69 100644
--- a/Source/JavaScriptCore/bytecode/SamplingTool.h
+++ b/Source/JavaScriptCore/bytecode/SamplingTool.h
@@ -45,8 +45,8 @@ namespace JSC {
class SamplingFlags {
public:
- static void start();
- static void stop();
+ JS_EXPORT_PRIVATE static void start();
+ JS_EXPORT_PRIVATE static void stop();
#if ENABLE(SAMPLING_FLAGS)
static void setFlag(unsigned flag)
@@ -89,7 +89,7 @@ namespace JSC {
#endif
private:
- static uint32_t s_flags;
+ JS_EXPORTDATA static uint32_t s_flags;
#if ENABLE(SAMPLING_FLAGS)
static uint64_t s_flagCounts[33];
#endif
@@ -174,7 +174,7 @@ namespace JSC {
class SamplingRegion {
public:
SamplingRegion(const char*) { }
- void dump();
+ JS_EXPORT_PRIVATE void dump();
};
#endif // ENABLE(SAMPLING_REGIONS)
@@ -220,8 +220,8 @@ namespace JSC {
static unsigned s_hertz;
static ThreadIdentifier s_samplingThread;
- static void start(unsigned hertz=10000);
- static void stop();
+ JS_EXPORT_PRIVATE static void start(unsigned hertz=10000);
+ JS_EXPORT_PRIVATE static void stop();
static void* threadStartFunc(void*);
};
@@ -294,7 +294,7 @@ namespace JSC {
memset(m_opcodeSamplesInCTIFunctions, 0, sizeof(m_opcodeSamplesInCTIFunctions));
}
- void setup();
+ JS_EXPORT_PRIVATE void setup();
void dump(ExecState*);
void notifyOfScope(JSGlobalData&, ScriptExecutable* scope);
diff --git a/Source/JavaScriptCore/dfg/DFGStructureSet.h b/Source/JavaScriptCore/bytecode/StructureSet.h
index 181c32910..344183b45 100644
--- a/Source/JavaScriptCore/dfg/DFGStructureSet.h
+++ b/Source/JavaScriptCore/bytecode/StructureSet.h
@@ -23,12 +23,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef DFGStructureSet_h
-#define DFGStructureSet_h
-
-#include <wtf/Platform.h>
-
-#if ENABLE(DFG_JIT)
+#ifndef StructureSet_h
+#define StructureSet_h
#include "PredictedType.h"
#include <stdio.h>
@@ -39,8 +35,8 @@ namespace JSC {
class Structure;
namespace DFG {
-
class StructureAbstractValue;
+}
class StructureSet {
public:
@@ -140,7 +136,6 @@ public:
return true;
}
-#ifndef NDEBUG
void dump(FILE* out)
{
fprintf(out, "[");
@@ -151,16 +146,13 @@ public:
}
fprintf(out, "]");
}
-#endif
private:
- friend class StructureAbstractValue;
+ friend class DFG::StructureAbstractValue;
Vector<Structure*, 2> m_structures;
};
-} } // namespace JSC::DFG
-
-#endif // ENABLE(DFG_JIT)
+} // namespace JSC
-#endif // DFGStructureSet_h
+#endif // StructureSet_h
diff --git a/Source/JavaScriptCore/bytecode/StructureStubInfo.h b/Source/JavaScriptCore/bytecode/StructureStubInfo.h
index 5c7ee0bb8..d6b6092d0 100644
--- a/Source/JavaScriptCore/bytecode/StructureStubInfo.h
+++ b/Source/JavaScriptCore/bytecode/StructureStubInfo.h
@@ -28,6 +28,7 @@
#if ENABLE(JIT)
+#include "CodeOrigin.h"
#include "Instruction.h"
#include "MacroAssembler.h"
#include "Opcode.h"
@@ -175,6 +176,8 @@ namespace JSC {
int8_t seen;
#if ENABLE(DFG_JIT)
+ CodeOrigin codeOrigin;
+ int8_t registersFlushed;
int8_t baseGPR;
#if USE(JSVALUE32_64)
int8_t valueTagGPR;
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index bfb1618a6..3d363354e 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+ * Copyright (C) 2012 Igalia, S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -117,6 +118,39 @@ namespace JSC {
*/
#ifndef NDEBUG
+void ResolveResult::checkValidity()
+{
+ switch (m_type) {
+ case Register:
+ case ReadOnlyRegister:
+ ASSERT(m_local);
+ return;
+ case Lexical:
+ case ReadOnlyLexical:
+ case DynamicLexical:
+ case DynamicReadOnlyLexical:
+ ASSERT(m_index != missingSymbolMarker());
+ return;
+ case Global:
+ case DynamicGlobal:
+ ASSERT(m_globalObject);
+ return;
+ case IndexedGlobal:
+ case ReadOnlyIndexedGlobal:
+ case DynamicIndexedGlobal:
+ case DynamicReadOnlyIndexedGlobal:
+ ASSERT(m_index != missingSymbolMarker());
+ ASSERT(m_globalObject);
+ return;
+ case Dynamic:
+ return;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+#endif
+
+#ifndef NDEBUG
static bool s_dumpsGeneratedCode = false;
#endif
@@ -217,7 +251,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* s
#ifndef NDEBUG
, m_lastOpcodePosition(0)
#endif
- , m_stack(m_globalData->stack())
+ , m_stack(wtfThreadData().stack())
, m_usesExceptions(false)
, m_expressionTooDeep(false)
{
@@ -288,7 +322,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainN
#ifndef NDEBUG
, m_lastOpcodePosition(0)
#endif
- , m_stack(m_globalData->stack())
+ , m_stack(wtfThreadData().stack())
, m_usesExceptions(false)
, m_expressionTooDeep(false)
{
@@ -449,7 +483,7 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, ScopeChainNode* scopeCh
#ifndef NDEBUG
, m_lastOpcodePosition(0)
#endif
- , m_stack(m_globalData->stack())
+ , m_stack(wtfThreadData().stack())
, m_usesExceptions(false)
, m_expressionTooDeep(false)
{
@@ -503,42 +537,6 @@ void BytecodeGenerator::addParameter(const Identifier& ident, int parameterIndex
m_codeBlock->addParameter();
}
-RegisterID* BytecodeGenerator::registerFor(const Identifier& ident)
-{
- if (ident == propertyNames().thisIdentifier)
- return &m_thisRegister;
-
- if (m_codeType == GlobalCode)
- return 0;
-
- if (!shouldOptimizeLocals())
- return 0;
-
- SymbolTableEntry entry = symbolTable().get(ident.impl());
- if (entry.isNull())
- return 0;
-
- if (ident == propertyNames().arguments)
- createArgumentsIfNecessary();
-
- return createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
-}
-
-RegisterID* BytecodeGenerator::constRegisterFor(const Identifier& ident)
-{
- if (m_codeType == EvalCode)
- return 0;
-
- if (m_codeType == GlobalCode)
- return 0;
-
- SymbolTableEntry entry = symbolTable().get(ident.impl());
- if (entry.isNull())
- return 0;
-
- return createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
-}
-
bool BytecodeGenerator::willResolveToArguments(const Identifier& ident)
{
if (ident != propertyNames().arguments)
@@ -668,6 +666,17 @@ void BytecodeGenerator::emitOpcode(OpcodeID opcodeID)
m_lastOpcodeID = opcodeID;
}
+ValueProfile* BytecodeGenerator::emitProfiledOpcode(OpcodeID opcodeID)
+{
+#if ENABLE(VALUE_PROFILER)
+ ValueProfile* result = m_codeBlock->addValueProfile(instructions().size());
+#else
+ ValueProfile* result = 0;
+#endif
+ emitOpcode(opcodeID);
+ return result;
+}
+
void BytecodeGenerator::emitLoopHint()
{
#if ENABLE(DFG_JIT)
@@ -1159,59 +1168,109 @@ RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValue v)
return constantID;
}
-bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& index, size_t& stackDepth, bool forWriting, bool& requiresDynamicChecks, JSObject*& globalObject)
+ResolveResult BytecodeGenerator::resolve(const Identifier& property)
{
+ if (property == propertyNames().thisIdentifier)
+ return ResolveResult::registerResolve(thisRegister(), ResolveResult::ReadOnlyFlag);
+
+ // Check if the property should be allocated in a register.
+ if (m_codeType != GlobalCode && shouldOptimizeLocals()) {
+ SymbolTableEntry entry = symbolTable().get(property.impl());
+ if (!entry.isNull()) {
+ if (property == propertyNames().arguments)
+ createArgumentsIfNecessary();
+ unsigned flags = entry.isReadOnly() ? ResolveResult::ReadOnlyFlag : 0;
+ RegisterID* local = createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
+ return ResolveResult::registerResolve(local, flags);
+ }
+ }
+
// Cases where we cannot statically optimize the lookup.
if (property == propertyNames().arguments || !canOptimizeNonLocals()) {
- stackDepth = 0;
- index = missingSymbolMarker();
-
if (shouldOptimizeLocals() && m_codeType == GlobalCode) {
ScopeChainIterator iter = m_scopeChain->begin();
- globalObject = iter->get();
+ JSObject* globalObject = iter->get();
ASSERT((++iter) == m_scopeChain->end());
- }
- return false;
+ return ResolveResult::globalResolve(globalObject);
+ } else
+ return ResolveResult::dynamicResolve(0);
}
- size_t depth = 0;
- requiresDynamicChecks = false;
ScopeChainIterator iter = m_scopeChain->begin();
ScopeChainIterator end = m_scopeChain->end();
+ size_t depth = 0;
+ unsigned flags = 0;
for (; iter != end; ++iter, ++depth) {
JSObject* currentScope = iter->get();
- if (!currentScope->isVariableObject())
+ if (!currentScope->isVariableObject()) {
+ flags |= ResolveResult::DynamicFlag;
break;
+ }
JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl());
// Found the property
if (!entry.isNull()) {
- if (entry.isReadOnly() && forWriting) {
- stackDepth = 0;
- index = missingSymbolMarker();
- if (++iter == end)
- globalObject = currentVariableObject;
- return false;
+ if (entry.isReadOnly())
+ flags |= ResolveResult::ReadOnlyFlag;
+ depth += m_codeBlock->needsFullScopeChain();
+ if (++iter == end) {
+ if (flags & ResolveResult::DynamicFlag)
+ return ResolveResult::dynamicIndexedGlobalResolve(entry.getIndex(), depth, currentScope, flags);
+ return ResolveResult::indexedGlobalResolve(entry.getIndex(), currentScope, flags);
}
- stackDepth = depth + m_codeBlock->needsFullScopeChain();
- index = entry.getIndex();
- if (++iter == end)
- globalObject = currentVariableObject;
- return true;
+ return ResolveResult::lexicalResolve(entry.getIndex(), depth, flags);
}
bool scopeRequiresDynamicChecks = false;
if (currentVariableObject->isDynamicScope(scopeRequiresDynamicChecks))
break;
- requiresDynamicChecks |= scopeRequiresDynamicChecks;
+ if (scopeRequiresDynamicChecks)
+ flags |= ResolveResult::DynamicFlag;
}
+
// Can't locate the property but we're able to avoid a few lookups.
- stackDepth = depth + m_codeBlock->needsFullScopeChain();
- index = missingSymbolMarker();
JSObject* scope = iter->get();
- if (++iter == end)
- globalObject = scope;
- return true;
+ depth += m_codeBlock->needsFullScopeChain();
+ if (++iter == end) {
+ if ((flags & ResolveResult::DynamicFlag) && depth)
+ return ResolveResult::dynamicGlobalResolve(depth, scope);
+ return ResolveResult::globalResolve(scope);
+ }
+ return ResolveResult::dynamicResolve(depth);
+}
+
+ResolveResult BytecodeGenerator::resolveConstDecl(const Identifier& property)
+{
+ // Register-allocated const declarations.
+ if (m_codeType != EvalCode && m_codeType != GlobalCode) {
+ SymbolTableEntry entry = symbolTable().get(property.impl());
+ if (!entry.isNull()) {
+ unsigned flags = entry.isReadOnly() ? ResolveResult::ReadOnlyFlag : 0;
+ RegisterID* local = createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
+ return ResolveResult::registerResolve(local, flags);
+ }
+ }
+
+ // Const declarations in eval code or global code.
+ ScopeChainIterator iter = scopeChain()->begin();
+ ScopeChainIterator end = scopeChain()->end();
+ size_t depth = 0;
+ for (; iter != end; ++iter, ++depth) {
+ JSObject* currentScope = iter->get();
+ if (!currentScope->isVariableObject())
+ continue;
+ JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
+ SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl());
+ if (entry.isNull())
+ continue;
+ if (++iter == end)
+ return ResolveResult::indexedGlobalResolve(entry.getIndex(), currentVariableObject, 0);
+ return ResolveResult::lexicalResolve(entry.getIndex(), depth + scopeDepth(), 0);
+ }
+
+ // FIXME: While this code should only be hit in an eval block, it will assign
+ // to the wrong base if property exists in an intervening with scope.
+ return ResolveResult::dynamicResolve(scopeDepth());
}
void BytecodeGenerator::emitCheckHasInstance(RegisterID* base)
@@ -1237,246 +1296,222 @@ bool BytecodeGenerator::shouldAvoidResolveGlobal()
return m_codeBlock->globalResolveInfoCount() > maxGlobalResolves && !m_labelScopes.size();
}
-RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& property)
+RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const ResolveResult& resolveResult, const Identifier& property)
{
- size_t depth = 0;
- int index = 0;
- JSObject* globalObject = 0;
- bool requiresDynamicChecks = false;
- if (!findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject) && !globalObject) {
- // We can't optimise at all :-(
- emitOpcode(op_resolve);
- instructions().append(dst->index());
- instructions().append(addConstant(property));
- return dst;
- }
- if (shouldAvoidResolveGlobal()) {
- globalObject = 0;
- requiresDynamicChecks = true;
- }
-
- if (globalObject) {
- if (index != missingSymbolMarker() && !requiresDynamicChecks) {
- // Directly index the property lookup across multiple scopes.
- return emitGetScopedVar(dst, depth, index, globalObject);
- }
-
+ if (resolveResult.isStatic())
+ return emitGetStaticVar(dst, resolveResult);
+
+ if (resolveResult.isGlobal() && !shouldAvoidResolveGlobal()) {
#if ENABLE(JIT)
m_codeBlock->addGlobalResolveInfo(instructions().size());
#endif
#if ENABLE(INTERPRETER)
m_codeBlock->addGlobalResolveInstruction(instructions().size());
#endif
- emitOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
+ bool dynamic = resolveResult.isDynamic() && resolveResult.depth();
+ ValueProfile* profile = emitProfiledOpcode(dynamic ? op_resolve_global_dynamic : op_resolve_global);
instructions().append(dst->index());
instructions().append(addConstant(property));
instructions().append(0);
instructions().append(0);
- if (requiresDynamicChecks)
- instructions().append(depth);
+ if (dynamic)
+ instructions().append(resolveResult.depth());
+ instructions().append(profile);
return dst;
}
-
- if (requiresDynamicChecks) {
- // If we get here we have eval nested inside a |with| just give up
- emitOpcode(op_resolve);
+
+ if (resolveResult.type() == ResolveResult::Dynamic && resolveResult.depth()) {
+ // In this case we are at least able to drop a few scope chains from the
+ // lookup chain, although we still need to hash from then on.
+ ValueProfile* profile = emitProfiledOpcode(op_resolve_skip);
instructions().append(dst->index());
instructions().append(addConstant(property));
+ instructions().append(resolveResult.depth());
+ instructions().append(profile);
return dst;
}
- if (index != missingSymbolMarker()) {
- // Directly index the property lookup across multiple scopes.
- return emitGetScopedVar(dst, depth, index, globalObject);
- }
-
- // In this case we are at least able to drop a few scope chains from the
- // lookup chain, although we still need to hash from then on.
- emitOpcode(op_resolve_skip);
+ ValueProfile* profile = emitProfiledOpcode(op_resolve);
instructions().append(dst->index());
instructions().append(addConstant(property));
- instructions().append(depth);
+ instructions().append(profile);
return dst;
}
-RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValue globalObject)
+RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const ResolveResult& resolveResult, const Identifier& property)
{
- if (globalObject) {
- if (m_lastOpcodeID == op_put_global_var) {
- int dstIndex;
- int srcIndex;
- retrieveLastUnaryOp(dstIndex, srcIndex);
-
- if (dstIndex == index && srcIndex == dst->index())
- return dst;
- }
+ if (resolveResult.isGlobal() && !resolveResult.isDynamic())
+ // Global object is the base
+ return emitLoad(dst, JSValue(resolveResult.globalObject()));
- emitOpcode(op_get_global_var);
- instructions().append(dst->index());
- instructions().append(index);
- return dst;
- }
-
- emitOpcode(op_get_scoped_var);
+ // We can't optimise at all :-(
+ ValueProfile* profile = emitProfiledOpcode(op_resolve_base);
instructions().append(dst->index());
- instructions().append(index);
- instructions().append(depth);
+ instructions().append(addConstant(property));
+ instructions().append(false);
+ instructions().append(profile);
return dst;
}
-RegisterID* BytecodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value, JSValue globalObject)
+RegisterID* BytecodeGenerator::emitResolveBaseForPut(RegisterID* dst, const ResolveResult& resolveResult, const Identifier& property)
{
- if (globalObject) {
- emitOpcode(op_put_global_var);
- instructions().append(index);
- instructions().append(value->index());
- return value;
- }
- emitOpcode(op_put_scoped_var);
- instructions().append(index);
- instructions().append(depth);
- instructions().append(value->index());
- return value;
-}
+ if (!m_codeBlock->isStrictMode())
+ return emitResolveBase(dst, resolveResult, property);
-RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier& property)
-{
- size_t depth = 0;
- int index = 0;
- JSObject* globalObject = 0;
- bool requiresDynamicChecks = false;
- findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject);
- if (!globalObject || requiresDynamicChecks) {
- // We can't optimise at all :-(
- emitOpcode(op_resolve_base);
+ if (resolveResult.isGlobal() && !resolveResult.isDynamic()) {
+ // Global object is the base
+ RefPtr<RegisterID> result = emitLoad(dst, JSValue(resolveResult.globalObject()));
+ emitOpcode(op_ensure_property_exists);
instructions().append(dst->index());
instructions().append(addConstant(property));
- instructions().append(false);
- return dst;
+ return result.get();
}
- // Global object is the base
- return emitLoad(dst, JSValue(globalObject));
-}
-
-RegisterID* BytecodeGenerator::emitResolveBaseForPut(RegisterID* dst, const Identifier& property)
-{
- if (!m_codeBlock->isStrictMode())
- return emitResolveBase(dst, property);
- size_t depth = 0;
- int index = 0;
- JSObject* globalObject = 0;
- bool requiresDynamicChecks = false;
- findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject);
- if (!globalObject || requiresDynamicChecks) {
- // We can't optimise at all :-(
- emitOpcode(op_resolve_base);
- instructions().append(dst->index());
- instructions().append(addConstant(property));
- instructions().append(true);
- return dst;
- }
-
- // Global object is the base
- RefPtr<RegisterID> result = emitLoad(dst, JSValue(globalObject));
- emitOpcode(op_ensure_property_exists);
+ // We can't optimise at all :-(
+ ValueProfile* profile = emitProfiledOpcode(op_resolve_base);
instructions().append(dst->index());
instructions().append(addConstant(property));
- return result.get();
+ instructions().append(true);
+ instructions().append(profile);
+ return dst;
}
-RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property)
+RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const ResolveResult& resolveResult, const Identifier& property)
{
- size_t depth = 0;
- int index = 0;
- JSObject* globalObject = 0;
- bool requiresDynamicChecks = false;
- if (!findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject) || !globalObject || requiresDynamicChecks) {
- // We can't optimise at all :-(
- emitOpcode(op_resolve_with_base);
- instructions().append(baseDst->index());
- instructions().append(propDst->index());
- instructions().append(addConstant(property));
- return baseDst;
- }
+ if (resolveResult.isGlobal() && !resolveResult.isDynamic()) {
+ // Global object is the base
+ emitLoad(baseDst, JSValue(resolveResult.globalObject()));
- bool forceGlobalResolve = false;
+ if (resolveResult.isStatic()) {
+ // Directly index the property lookup across multiple scopes.
+ emitGetStaticVar(propDst, resolveResult);
+ return baseDst;
+ }
- // Global object is the base
- emitLoad(baseDst, JSValue(globalObject));
+ if (shouldAvoidResolveGlobal()) {
+ ValueProfile* profile = emitProfiledOpcode(op_resolve);
+ instructions().append(propDst->index());
+ instructions().append(addConstant(property));
+ instructions().append(profile);
+ return baseDst;
+ }
- if (index != missingSymbolMarker() && !forceGlobalResolve) {
- // Directly index the property lookup across multiple scopes.
- emitGetScopedVar(propDst, depth, index, globalObject);
- return baseDst;
- }
- if (shouldAvoidResolveGlobal()) {
- emitOpcode(op_resolve);
- instructions().append(propDst->index());
- instructions().append(addConstant(property));
- return baseDst;
- }
#if ENABLE(JIT)
- m_codeBlock->addGlobalResolveInfo(instructions().size());
+ m_codeBlock->addGlobalResolveInfo(instructions().size());
#endif
#if ENABLE(INTERPRETER)
- m_codeBlock->addGlobalResolveInstruction(instructions().size());
+ m_codeBlock->addGlobalResolveInstruction(instructions().size());
#endif
- emitOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
+ ValueProfile* profile = emitProfiledOpcode(op_resolve_global);
+ instructions().append(propDst->index());
+ instructions().append(addConstant(property));
+ instructions().append(0);
+ instructions().append(0);
+ instructions().append(profile);
+ return baseDst;
+ }
+
+
+
+
+ ValueProfile* profile = emitProfiledOpcode(op_resolve_with_base);
+ instructions().append(baseDst->index());
instructions().append(propDst->index());
instructions().append(addConstant(property));
- instructions().append(0);
- instructions().append(0);
- if (requiresDynamicChecks)
- instructions().append(depth);
+ instructions().append(profile);
return baseDst;
}
-RegisterID* BytecodeGenerator::emitResolveWithThis(RegisterID* baseDst, RegisterID* propDst, const Identifier& property)
+RegisterID* BytecodeGenerator::emitResolveWithThis(RegisterID* baseDst, RegisterID* propDst, const ResolveResult& resolveResult, const Identifier& property)
{
- size_t depth = 0;
- int index = 0;
- JSObject* globalObject = 0;
- bool requiresDynamicChecks = false;
- if (!findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject) || !globalObject || requiresDynamicChecks) {
+ if (resolveResult.isStatic()) {
+ emitLoad(baseDst, jsUndefined());
+ emitGetStaticVar(propDst, resolveResult);
+ return baseDst;
+ }
+
+ if (resolveResult.type() == ResolveResult::Dynamic) {
// We can't optimise at all :-(
- emitOpcode(op_resolve_with_this);
+ ValueProfile* profile = emitProfiledOpcode(op_resolve_with_this);
instructions().append(baseDst->index());
instructions().append(propDst->index());
instructions().append(addConstant(property));
+ instructions().append(profile);
return baseDst;
}
- bool forceGlobalResolve = false;
-
- // Global object is the base
emitLoad(baseDst, jsUndefined());
+ return emitResolve(propDst, resolveResult, property);
+}
- if (index != missingSymbolMarker() && !forceGlobalResolve) {
- // Directly index the property lookup across multiple scopes.
- emitGetScopedVar(propDst, depth, index, globalObject);
- return baseDst;
+RegisterID* BytecodeGenerator::emitGetStaticVar(RegisterID* dst, const ResolveResult& resolveResult)
+{
+ ValueProfile* profile = 0;
+
+ switch (resolveResult.type()) {
+ case ResolveResult::Register:
+ case ResolveResult::ReadOnlyRegister:
+ if (dst == ignoredResult())
+ return 0;
+ return moveToDestinationIfNeeded(dst, resolveResult.local());
+
+ case ResolveResult::Lexical:
+ case ResolveResult::ReadOnlyLexical:
+ profile = emitProfiledOpcode(op_get_scoped_var);
+ instructions().append(dst->index());
+ instructions().append(resolveResult.index());
+ instructions().append(resolveResult.depth());
+ instructions().append(profile);
+ return dst;
+
+ case ResolveResult::IndexedGlobal:
+ case ResolveResult::ReadOnlyIndexedGlobal:
+ if (m_lastOpcodeID == op_put_global_var) {
+ int dstIndex;
+ int srcIndex;
+ retrieveLastUnaryOp(dstIndex, srcIndex);
+ if (dstIndex == resolveResult.index() && srcIndex == dst->index())
+ return dst;
+ }
+
+ profile = emitProfiledOpcode(op_get_global_var);
+ instructions().append(dst->index());
+ instructions().append(resolveResult.index());
+ instructions().append(profile);
+ return dst;
+
+ default:
+ ASSERT_NOT_REACHED();
+ return 0;
}
- if (shouldAvoidResolveGlobal()) {
- emitOpcode(op_resolve);
- instructions().append(propDst->index());
- instructions().append(addConstant(property));
- return baseDst;
+}
+
+RegisterID* BytecodeGenerator::emitPutStaticVar(const ResolveResult& resolveResult, RegisterID* value)
+{
+ switch (resolveResult.type()) {
+ case ResolveResult::Register:
+ case ResolveResult::ReadOnlyRegister:
+ return moveToDestinationIfNeeded(resolveResult.local(), value);
+
+ case ResolveResult::Lexical:
+ case ResolveResult::ReadOnlyLexical:
+ emitOpcode(op_put_scoped_var);
+ instructions().append(resolveResult.index());
+ instructions().append(resolveResult.depth());
+ instructions().append(value->index());
+ return value;
+
+ case ResolveResult::IndexedGlobal:
+ case ResolveResult::ReadOnlyIndexedGlobal:
+ emitOpcode(op_put_global_var);
+ instructions().append(resolveResult.index());
+ instructions().append(value->index());
+ return value;
+
+ default:
+ ASSERT_NOT_REACHED();
+ return 0;
}
-#if ENABLE(JIT)
- m_codeBlock->addGlobalResolveInfo(instructions().size());
-#endif
-#if ENABLE(INTERPRETER)
- m_codeBlock->addGlobalResolveInstruction(instructions().size());
-#endif
- emitOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
- instructions().append(propDst->index());
- instructions().append(addConstant(property));
- instructions().append(0);
- instructions().append(0);
- if (requiresDynamicChecks)
- instructions().append(depth);
- return baseDst;
}
void BytecodeGenerator::emitMethodCheck()
@@ -1490,7 +1525,7 @@ RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, co
m_codeBlock->addPropertyAccessInstruction(instructions().size());
#endif
- emitOpcode(op_get_by_id);
+ ValueProfile* profile = emitProfiledOpcode(op_get_by_id);
instructions().append(dst->index());
instructions().append(base->index());
instructions().append(addConstant(property));
@@ -1498,6 +1533,7 @@ RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, co
instructions().append(0);
instructions().append(0);
instructions().append(0);
+ instructions().append(profile);
return dst;
}
@@ -1547,22 +1583,13 @@ RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identif
return value;
}
-RegisterID* BytecodeGenerator::emitPutGetter(RegisterID* base, const Identifier& property, RegisterID* value)
+void BytecodeGenerator::emitPutGetterSetter(RegisterID* base, const Identifier& property, RegisterID* getter, RegisterID* setter)
{
- emitOpcode(op_put_getter);
+ emitOpcode(op_put_getter_setter);
instructions().append(base->index());
instructions().append(addConstant(property));
- instructions().append(value->index());
- return value;
-}
-
-RegisterID* BytecodeGenerator::emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value)
-{
- emitOpcode(op_put_setter);
- instructions().append(base->index());
- instructions().append(addConstant(property));
- instructions().append(value->index());
- return value;
+ instructions().append(getter->index());
+ instructions().append(setter->index());
}
RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property)
@@ -1576,11 +1603,12 @@ RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base,
RegisterID* BytecodeGenerator::emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
{
- emitOpcode(op_get_argument_by_val);
+ ValueProfile* profile = emitProfiledOpcode(op_get_argument_by_val);
instructions().append(dst->index());
ASSERT(base->index() == m_codeBlock->argumentsRegister());
instructions().append(base->index());
instructions().append(property->index());
+ instructions().append(profile);
return dst;
}
@@ -1599,10 +1627,11 @@ RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, R
return dst;
}
}
- emitOpcode(op_get_by_val);
+ ValueProfile* profile = emitProfiledOpcode(op_get_by_val);
instructions().append(dst->index());
instructions().append(base->index());
instructions().append(property->index());
+ instructions().append(profile);
return dst;
}
@@ -1824,8 +1853,9 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
instructions().append(0);
instructions().append(0);
if (dst != ignoredResult()) {
- emitOpcode(op_call_put_result);
+ ValueProfile* profile = emitProfiledOpcode(op_call_put_result);
instructions().append(dst->index()); // dst
+ instructions().append(profile);
}
if (m_shouldEmitProfileHooks) {
@@ -1853,8 +1883,9 @@ RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func
instructions().append(arguments->index());
instructions().append(firstFreeRegister->index());
if (dst != ignoredResult()) {
- emitOpcode(op_call_put_result);
+ ValueProfile* profile = emitProfiledOpcode(op_call_put_result);
instructions().append(dst->index());
+ instructions().append(profile);
}
if (m_shouldEmitProfileHooks) {
emitOpcode(op_profile_did_call);
@@ -1926,8 +1957,9 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
instructions().append(0);
instructions().append(0);
if (dst != ignoredResult()) {
- emitOpcode(op_call_put_result);
+ ValueProfile* profile = emitProfiledOpcode(op_call_put_result);
instructions().append(dst->index()); // dst
+ instructions().append(profile);
}
if (m_shouldEmitProfileHooks) {
@@ -2362,7 +2394,7 @@ void BytecodeGenerator::setIsNumericCompareFunction(bool isNumericCompareFunctio
bool BytecodeGenerator::isArgumentNumber(const Identifier& ident, int argumentNumber)
{
- RegisterID* registerID = registerFor(ident);
+ RegisterID* registerID = resolve(ident).local();
if (!registerID || registerID->index() >= 0)
return 0;
return registerID->index() == CallFrame::argumentOffset(argumentNumber);
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index 3ff5f2343..c9ec5d852 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+ * Copyright (C) 2012 Igalia, S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -85,6 +86,144 @@ namespace JSC {
RefPtr<RegisterID> propertyRegister;
};
+ class ResolveResult {
+ public:
+ enum Flags {
+ // The property is locally bound, in a register.
+ RegisterFlag = 0x1,
+ // We need to traverse the scope chain at runtime, checking for
+ // non-strict eval and/or `with' nodes.
+ DynamicFlag = 0x2,
+ // The property was resolved to a definite location, and the
+ // identifier is not needed any more.
+ StaticFlag = 0x4,
+ // Once we have the base object, the property will be located at a
+ // known index.
+ IndexedFlag = 0x8,
+ // Skip some number of objects in the scope chain, given by "depth".
+ ScopedFlag = 0x10,
+ // The resolved binding is immutable.
+ ReadOnlyFlag = 0x20,
+ // The base object is the global object.
+ GlobalFlag = 0x40
+ };
+ enum Type {
+ // The property is local, and stored in a register.
+ Register = RegisterFlag | StaticFlag,
+ // A read-only local, created by "const".
+ ReadOnlyRegister = RegisterFlag | ReadOnlyFlag | StaticFlag,
+ // The property is statically scoped free variable. Its coordinates
+ // are in "index" and "depth".
+ Lexical = IndexedFlag | ScopedFlag | StaticFlag,
+ // A read-only Lexical, created by "const".
+ ReadOnlyLexical = IndexedFlag | ScopedFlag | ReadOnlyFlag | StaticFlag,
+ // The property was not bound lexically, so at runtime we should
+ // look directly in the global object.
+ Global = GlobalFlag,
+ // Like Global, but we could actually resolve the property to a
+ // DontDelete property in the global object, for instance, any
+ // binding created with "var" at the top level. At runtime we'll
+ // just index into the global object.
+ IndexedGlobal = IndexedFlag | GlobalFlag | StaticFlag,
+ // Like IndexedGlobal, but the property is also read-only, like NaN,
+ // Infinity, or undefined.
+ ReadOnlyIndexedGlobal = IndexedFlag | ReadOnlyFlag | GlobalFlag | StaticFlag,
+ // The property could not be resolved statically, due to the
+ // presence of `with' blocks. At runtime we'll have to walk the
+ // scope chain. ScopedFlag is set to indicate that "depth" will
+ // hold some number of nodes to skip in the scope chain, before
+ // beginning the search.
+ Dynamic = DynamicFlag | ScopedFlag,
+ // The property was located as a statically scoped free variable,
+ // but while traversing the scope chain, there was an intermediate
+ // activation that used non-strict `eval'. At runtime we'll have to
+ // check for the absence of this property in those intervening
+ // scopes.
+ DynamicLexical = DynamicFlag | IndexedFlag | ScopedFlag,
+ // Like ReadOnlyLexical, but with intervening non-strict `eval'.
+ DynamicReadOnlyLexical = DynamicFlag | IndexedFlag | ScopedFlag | ReadOnlyFlag,
+ // Like Global, but with intervening non-strict `eval'. As with
+ // Dynamic, ScopeFlag is set to indicate that "depth" does indeed
+ // store a number of frames to skip before doing the dynamic checks.
+ DynamicGlobal = DynamicFlag | GlobalFlag | ScopedFlag,
+ // Like IndexedGlobal, but with intervening non-strict `eval'.
+ DynamicIndexedGlobal = DynamicFlag | IndexedFlag | GlobalFlag | ScopedFlag,
+ // Like ReadOnlyIndexedGlobal, but with intervening non-strict
+ // `eval'.
+ DynamicReadOnlyIndexedGlobal = DynamicFlag | IndexedFlag | ReadOnlyFlag | GlobalFlag | ScopedFlag,
+ };
+
+ static ResolveResult registerResolve(RegisterID *local, unsigned flags)
+ {
+ return ResolveResult(Register | flags, local, missingSymbolMarker(), 0, 0);
+ }
+ static ResolveResult dynamicResolve(size_t depth)
+ {
+ return ResolveResult(Dynamic, 0, missingSymbolMarker(), depth, 0);
+ }
+ static ResolveResult lexicalResolve(int index, size_t depth, unsigned flags)
+ {
+ unsigned type = (flags & DynamicFlag) ? DynamicLexical : Lexical;
+ return ResolveResult(type | flags, 0, index, depth, 0);
+ }
+ static ResolveResult indexedGlobalResolve(int index, JSObject *globalObject, unsigned flags)
+ {
+ return ResolveResult(IndexedGlobal | flags, 0, index, 0, globalObject);
+ }
+ static ResolveResult dynamicIndexedGlobalResolve(int index, size_t depth, JSObject *globalObject, unsigned flags)
+ {
+ return ResolveResult(DynamicIndexedGlobal | flags, 0, index, depth, globalObject);
+ }
+ static ResolveResult globalResolve(JSObject *globalObject)
+ {
+ return ResolveResult(Global, 0, missingSymbolMarker(), 0, globalObject);
+ }
+ static ResolveResult dynamicGlobalResolve(size_t dynamicDepth, JSObject *globalObject)
+ {
+ return ResolveResult(DynamicGlobal, 0, missingSymbolMarker(), dynamicDepth, globalObject);
+ }
+
+ unsigned type() const { return m_type; }
+ // Returns the register corresponding to a local variable, or 0 if no
+ // such register exists. Registers returned by ResolveResult::local() do
+ // not require explicit reference counting.
+ RegisterID* local() const { return m_local; }
+ int index() const { ASSERT (isIndexed() || isRegister()); return m_index; }
+ size_t depth() const { ASSERT(isScoped()); return m_depth; }
+ JSObject* globalObject() const { ASSERT(isGlobal()); ASSERT(m_globalObject); return m_globalObject; }
+
+ bool isRegister() const { return m_type & RegisterFlag; }
+ bool isDynamic() const { return m_type & DynamicFlag; }
+ bool isStatic() const { return m_type & StaticFlag; }
+ bool isIndexed() const { return m_type & IndexedFlag; }
+ bool isScoped() const { return m_type & ScopedFlag; }
+ bool isReadOnly() const { return (m_type & ReadOnlyFlag) && !isDynamic(); }
+ bool isGlobal() const { return m_type & GlobalFlag; }
+
+ private:
+ ResolveResult(unsigned type, RegisterID* local, int index, size_t depth, JSObject* globalObject)
+ : m_type(type)
+ , m_index(index)
+ , m_local(local)
+ , m_depth(depth)
+ , m_globalObject(globalObject)
+ {
+#ifndef NDEBUG
+ checkValidity();
+#endif
+ }
+
+#ifndef NDEBUG
+ void checkValidity();
+#endif
+
+ unsigned m_type;
+ int m_index; // Index in scope, if IndexedFlag is set
+ RegisterID* m_local; // Local register, if RegisterFlag is set
+ size_t m_depth; // Depth in scope chain, if ScopedFlag is set
+ JSObject* m_globalObject; // If GlobalFlag is set.
+ };
+
class BytecodeGenerator {
WTF_MAKE_FAST_ALLOCATED;
public:
@@ -107,11 +246,6 @@ namespace JSC {
JSObject* generate();
- // Returns the register corresponding to a local variable, or 0 if no
- // such register exists. Registers returned by registerFor do not
- // require explicit reference counting.
- RegisterID* registerFor(const Identifier&);
-
bool isArgumentNumber(const Identifier&, int);
void setIsNumericCompareFunction(bool isNumericCompareFunction);
@@ -119,17 +253,11 @@ namespace JSC {
bool willResolveToArguments(const Identifier&);
RegisterID* uncheckedRegisterForArguments();
- // Behaves as registerFor does, but ignores dynamic scope as
+ // Resolve an identifier, given the current compile-time scope chain.
+ ResolveResult resolve(const Identifier&);
+ // Behaves as resolve does, but ignores dynamic scope as
// dynamic scope should not interfere with const initialisation
- RegisterID* constRegisterFor(const Identifier&);
-
- // Searches the scope chain in an attempt to statically locate the requested
- // property. Returns false if for any reason the property cannot be safely
- // optimised at all. Otherwise it will return the index and depth of the
- // VariableObject that defines the property. If the property cannot be found
- // statically, depth will contain the depth of the scope chain where dynamic
- // lookup must begin.
- bool findScopedProperty(const Identifier&, int& index, size_t& depth, bool forWriting, bool& includesDynamicScopes, JSObject*& globalObject);
+ ResolveResult resolveConstDecl(const Identifier&);
// Returns the register storing "this"
RegisterID* thisRegister() { return &m_thisRegister; }
@@ -274,7 +402,7 @@ namespace JSC {
return dst;
}
- return PassRefPtr<RegisterID>(emitNode(n));
+ return emitNode(n);
}
RegisterID* emitLoad(RegisterID* dst, bool);
@@ -309,14 +437,14 @@ namespace JSC {
RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); }
RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); }
- RegisterID* emitResolve(RegisterID* dst, const Identifier& property);
- RegisterID* emitGetScopedVar(RegisterID* dst, size_t skip, int index, JSValue globalObject);
- RegisterID* emitPutScopedVar(size_t skip, int index, RegisterID* value, JSValue globalObject);
+ RegisterID* emitGetStaticVar(RegisterID* dst, const ResolveResult&);
+ RegisterID* emitPutStaticVar(const ResolveResult&, RegisterID* value);
- RegisterID* emitResolveBase(RegisterID* dst, const Identifier& property);
- RegisterID* emitResolveBaseForPut(RegisterID* dst, const Identifier& property);
- RegisterID* emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property);
- RegisterID* emitResolveWithThis(RegisterID* baseDst, RegisterID* propDst, const Identifier& property);
+ RegisterID* emitResolve(RegisterID* dst, const ResolveResult&, const Identifier& property);
+ RegisterID* emitResolveBase(RegisterID* dst, const ResolveResult&, const Identifier& property);
+ RegisterID* emitResolveBaseForPut(RegisterID* dst, const ResolveResult&, const Identifier& property);
+ RegisterID* emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const ResolveResult&, const Identifier& property);
+ RegisterID* emitResolveWithThis(RegisterID* baseDst, RegisterID* propDst, const ResolveResult&, const Identifier& property);
void emitMethodCheck();
@@ -330,8 +458,7 @@ namespace JSC {
RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
RegisterID* emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
RegisterID* emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value);
- RegisterID* emitPutGetter(RegisterID* base, const Identifier& property, RegisterID* value);
- RegisterID* emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value);
+ void emitPutGetterSetter(RegisterID* base, const Identifier& property, RegisterID* getter, RegisterID* setter);
RegisterID* emitCall(RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
@@ -409,6 +536,7 @@ namespace JSC {
private:
void emitOpcode(OpcodeID);
+ ValueProfile* emitProfiledOpcode(OpcodeID);
void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
ALWAYS_INLINE void rewindBinaryOp();
@@ -466,12 +594,12 @@ namespace JSC {
FunctionExecutable* makeFunction(ExecState* exec, FunctionBodyNode* body)
{
- return FunctionExecutable::create(exec, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
+ return FunctionExecutable::create(exec, body->ident(), body->inferredName(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
}
FunctionExecutable* makeFunction(JSGlobalData* globalData, FunctionBodyNode* body)
{
- return FunctionExecutable::create(*globalData, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
+ return FunctionExecutable::create(*globalData, body->ident(), body->inferredName(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
}
JSString* addStringConstant(const Identifier&);
diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index a0127d8d7..46ec698de 100644
--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -5,6 +5,7 @@
* Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
* Copyright (C) 2007 Maks Orlovich
* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2012 Igalia, S.L.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -146,14 +147,15 @@ bool ResolveNode::isPure(BytecodeGenerator& generator) const
RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- if (RegisterID* local = generator.registerFor(m_ident)) {
+ ResolveResult resolveResult = generator.resolve(m_ident);
+ if (RegisterID* local = resolveResult.local()) {
if (dst == generator.ignoredResult())
return 0;
return generator.moveToDestinationIfNeeded(dst, local);
}
generator.emitExpressionInfo(m_startOffset + m_ident.length(), m_ident.length(), 0);
- return generator.emitResolve(generator.finalDestination(dst), m_ident);
+ return generator.emitResolve(generator.finalDestination(dst), resolveResult, m_ident);
}
// ------------------------------ ArrayNode ------------------------------------
@@ -236,27 +238,79 @@ RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, Registe
generator.emitNewObject(newObj.get());
- for (PropertyListNode* p = this; p; p = p->m_next) {
- RegisterID* value = generator.emitNode(p->m_node->m_assign);
-
- switch (p->m_node->m_type) {
- case PropertyNode::Constant: {
- generator.emitDirectPutById(newObj.get(), p->m_node->name(), value);
- break;
- }
- case PropertyNode::Getter: {
- generator.emitPutGetter(newObj.get(), p->m_node->name(), value);
- break;
+ // Fast case: this loop just handles regular value properties.
+ PropertyListNode* p = this;
+ for (; p && p->m_node->m_type == PropertyNode::Constant; p = p->m_next)
+ generator.emitDirectPutById(newObj.get(), p->m_node->name(), generator.emitNode(p->m_node->m_assign));
+
+ // Were there any get/set properties?
+ if (p) {
+ typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair;
+ typedef HashMap<StringImpl*, GetterSetterPair> GetterSetterMap;
+ GetterSetterMap map;
+
+ // Build a map, pairing get/set values together.
+ for (PropertyListNode* q = p; q; q = q->m_next) {
+ PropertyNode* node = q->m_node;
+ if (node->m_type == PropertyNode::Constant)
+ continue;
+
+ GetterSetterPair pair(node, 0);
+ std::pair<GetterSetterMap::iterator, bool> result = map.add(node->name().impl(), pair);
+ if (!result.second)
+ result.first->second.second = node;
+ }
+
+ // Iterate over the remaining properties in the list.
+ for (; p; p = p->m_next) {
+ PropertyNode* node = p->m_node;
+ RegisterID* value = generator.emitNode(node->m_assign);
+
+ // Handle regular values.
+ if (node->m_type == PropertyNode::Constant) {
+ generator.emitDirectPutById(newObj.get(), node->name(), value);
+ continue;
}
- case PropertyNode::Setter: {
- generator.emitPutSetter(newObj.get(), p->m_node->name(), value);
- break;
+
+ // This is a get/set property, find its entry in the map.
+ ASSERT(node->m_type == PropertyNode::Getter || node->m_type == PropertyNode::Setter);
+ GetterSetterMap::iterator it = map.find(node->name().impl());
+ ASSERT(it != map.end());
+ GetterSetterPair& pair = it->second;
+
+ // Was this already generated as a part of its partner?
+ if (pair.second == node)
+ continue;
+
+ // Generate the paired node now.
+ RefPtr<RegisterID> getterReg;
+ RefPtr<RegisterID> setterReg;
+
+ if (node->m_type == PropertyNode::Getter) {
+ getterReg = value;
+ if (pair.second) {
+ ASSERT(pair.second->m_type == PropertyNode::Setter);
+ setterReg = generator.emitNode(pair.second->m_assign);
+ } else {
+ setterReg = generator.newTemporary();
+ generator.emitLoad(setterReg.get(), jsUndefined());
+ }
+ } else {
+ ASSERT(node->m_type == PropertyNode::Setter);
+ setterReg = value;
+ if (pair.second) {
+ ASSERT(pair.second->m_type == PropertyNode::Getter);
+ getterReg = generator.emitNode(pair.second->m_assign);
+ } else {
+ getterReg = generator.newTemporary();
+ generator.emitLoad(getterReg.get(), jsUndefined());
+ }
}
- default:
- ASSERT_NOT_REACHED();
+
+ generator.emitPutGetterSetter(newObj.get(), node->name(), getterReg.get(), setterReg.get());
}
}
-
+
return generator.moveToDestinationIfNeeded(dst, newObj.get());
}
@@ -346,7 +400,7 @@ RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, Reg
RefPtr<RegisterID> func = generator.tempDestination(dst);
CallArguments callArguments(generator, m_args);
generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0);
- generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), generator.propertyNames().eval);
+ generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), generator.resolve(generator.propertyNames().eval), generator.propertyNames().eval);
return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
}
@@ -364,19 +418,19 @@ RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, Re
RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) {
+ ResolveResult resolveResult = generator.resolve(m_ident);
+
+ if (RegisterID* local = resolveResult.local()) {
+ RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
CallArguments callArguments(generator, m_args);
generator.emitLoad(callArguments.thisRegister(), jsUndefined());
- return generator.emitCall(generator.finalDestinationOrIgnored(dst, callArguments.thisRegister()), local.get(), callArguments, divot(), startOffset(), endOffset());
+ return generator.emitCall(generator.finalDestinationOrIgnored(dst, callArguments.thisRegister()), func.get(), callArguments, divot(), startOffset(), endOffset());
}
- int index = 0;
- size_t depth = 0;
- JSObject* globalObject = 0;
- bool requiresDynamicChecks = false;
- if (generator.findScopedProperty(m_ident, index, depth, false, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
- RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
+ if (resolveResult.isStatic()) {
+ RefPtr<RegisterID> func = generator.newTemporary();
CallArguments callArguments(generator, m_args);
+ generator.emitGetStaticVar(func.get(), resolveResult);
generator.emitLoad(callArguments.thisRegister(), jsUndefined());
return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
}
@@ -384,8 +438,9 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator,
RefPtr<RegisterID> func = generator.newTemporary();
CallArguments callArguments(generator, m_args);
int identifierStart = divot() - startOffset();
+
generator.emitExpressionInfo(identifierStart + m_ident.length(), m_ident.length(), 0);
- generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), m_ident);
+ generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), resolveResult, m_ident);
return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
}
@@ -505,6 +560,7 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
RefPtr<RegisterID> profileHookRegister;
if (generator.shouldEmitProfileHooks())
profileHookRegister = generator.newTemporary();
+ RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
RefPtr<RegisterID> argsRegister;
ArgumentListNode* args = m_args->m_listNode->m_next;
@@ -518,7 +574,7 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
while ((args = args->m_next))
generator.emitNode(args->m_expr);
- generator.emitCallVarargs(finalDestinationOrIgnored.get(), base.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), profileHookRegister.get(), divot(), startOffset(), endOffset());
+ generator.emitCallVarargs(finalDestinationOrIgnored.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), profileHookRegister.get(), divot(), startOffset(), endOffset());
}
generator.emitJump(end.get());
}
@@ -548,24 +604,21 @@ static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* ds
RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- if (RegisterID* local = generator.registerFor(m_ident)) {
- if (generator.isLocalConstant(m_ident)) {
+ ResolveResult resolveResult = generator.resolve(m_ident);
+
+ if (RegisterID* local = resolveResult.local()) {
+ if (resolveResult.isReadOnly()) {
if (dst == generator.ignoredResult())
return 0;
return generator.emitToJSNumber(generator.finalDestination(dst), local);
}
-
if (dst == generator.ignoredResult())
return emitPreIncOrDec(generator, local, m_operator);
return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator);
}
- int index = 0;
- size_t depth = 0;
- JSObject* globalObject = 0;
- bool requiresDynamicChecks = false;
- if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
- RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
+ if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {
+ RefPtr<RegisterID> value = generator.emitGetStaticVar(generator.newTemporary(), resolveResult);
RegisterID* oldValue;
if (dst == generator.ignoredResult()) {
oldValue = 0;
@@ -573,13 +626,13 @@ RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, Regis
} else {
oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
}
- generator.emitPutScopedVar(depth, index, value.get(), globalObject);
+ generator.emitPutStaticVar(resolveResult, value.get());
return oldValue;
}
-
+
generator.emitExpressionInfo(divot(), startOffset(), endOffset());
RefPtr<RegisterID> value = generator.newTemporary();
- RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
+ RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), resolveResult, m_ident);
RegisterID* oldValue;
if (dst == generator.ignoredResult()) {
oldValue = 0;
@@ -651,11 +704,12 @@ RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, Registe
RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- if (generator.registerFor(m_ident))
+ ResolveResult resolveResult = generator.resolve(m_ident);
+ if (resolveResult.isRegister())
return generator.emitLoad(generator.finalDestination(dst), false);
generator.emitExpressionInfo(divot(), startOffset(), endOffset());
- RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
+ RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), resolveResult, m_ident);
return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
}
@@ -706,13 +760,14 @@ RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst
RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- if (RegisterID* local = generator.registerFor(m_ident)) {
+ ResolveResult resolveResult = generator.resolve(m_ident);
+ if (RegisterID* local = resolveResult.local()) {
if (dst == generator.ignoredResult())
return 0;
return generator.emitTypeOf(generator.finalDestination(dst), local);
}
- RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
+ RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), resolveResult, m_ident);
generator.emitGetById(scratch.get(), scratch.get(), m_ident);
if (dst == generator.ignoredResult())
return 0;
@@ -735,32 +790,28 @@ RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, Register
RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- if (RegisterID* local = generator.registerFor(m_ident)) {
+ ResolveResult resolveResult = generator.resolve(m_ident);
+ if (RegisterID* local = resolveResult.local()) {
if (generator.isLocalConstant(m_ident)) {
if (dst == generator.ignoredResult())
return 0;
RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0);
return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes());
}
-
emitPreIncOrDec(generator, local, m_operator);
return generator.moveToDestinationIfNeeded(dst, local);
}
- int index = 0;
- size_t depth = 0;
- JSObject* globalObject = 0;
- bool requiresDynamicChecks = false;
- if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
- RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
+ if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {
+ RefPtr<RegisterID> propDst = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult);
emitPreIncOrDec(generator, propDst.get(), m_operator);
- generator.emitPutScopedVar(depth, index, propDst.get(), globalObject);
+ generator.emitPutStaticVar(resolveResult, propDst.get());
return generator.moveToDestinationIfNeeded(dst, propDst.get());
}
generator.emitExpressionInfo(divot(), startOffset(), endOffset());
RefPtr<RegisterID> propDst = generator.tempDestination(dst);
- RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
+ RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), resolveResult, m_ident);
emitPreIncOrDec(generator, propDst.get(), m_operator);
generator.emitPutById(base.get(), m_ident, propDst.get());
return generator.moveToDestinationIfNeeded(dst, propDst.get());
@@ -1148,10 +1199,11 @@ static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& gen
RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- if (RegisterID* local = generator.registerFor(m_ident)) {
- if (generator.isLocalConstant(m_ident)) {
+ ResolveResult resolveResult = generator.resolve(m_ident);
+
+ if (RegisterID *local = resolveResult.local()) {
+ if (resolveResult.isReadOnly())
return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
- }
if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
RefPtr<RegisterID> result = generator.newTemporary();
@@ -1165,20 +1217,16 @@ RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, Re
return generator.moveToDestinationIfNeeded(dst, result);
}
- int index = 0;
- size_t depth = 0;
- JSObject* globalObject = 0;
- bool requiresDynamicChecks = false;
- if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
- RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
+ if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {
+ RefPtr<RegisterID> src1 = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult);
RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
- generator.emitPutScopedVar(depth, index, result, globalObject);
+ generator.emitPutStaticVar(resolveResult, result);
return result;
}
RefPtr<RegisterID> src1 = generator.tempDestination(dst);
generator.emitExpressionInfo(divot() - startOffset() + m_ident.length(), m_ident.length(), 0);
- RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
+ RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), resolveResult, m_ident);
RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
return generator.emitPutById(base.get(), m_ident, result);
}
@@ -1187,27 +1235,24 @@ RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, Re
RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- if (RegisterID* local = generator.registerFor(m_ident)) {
- if (generator.isLocalConstant(m_ident))
+ ResolveResult resolveResult = generator.resolve(m_ident);
+
+ if (RegisterID *local = resolveResult.local()) {
+ if (resolveResult.isReadOnly())
return generator.emitNode(dst, m_right);
-
RegisterID* result = generator.emitNode(local, m_right);
return generator.moveToDestinationIfNeeded(dst, result);
}
- int index = 0;
- size_t depth = 0;
- JSObject* globalObject = 0;
- bool requiresDynamicChecks = false;
- if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
+ if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {
if (dst == generator.ignoredResult())
dst = 0;
RegisterID* value = generator.emitNode(dst, m_right);
- generator.emitPutScopedVar(depth, index, value, globalObject);
+ generator.emitPutStaticVar(resolveResult, value);
return value;
}
- RefPtr<RegisterID> base = generator.emitResolveBaseForPut(generator.newTemporary(), m_ident);
+ RefPtr<RegisterID> base = generator.emitResolveBaseForPut(generator.newTemporary(), resolveResult, m_ident);
if (dst == generator.ignoredResult())
dst = 0;
RegisterID* value = generator.emitNode(dst, m_right);
@@ -1295,8 +1340,10 @@ RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds
RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
{
+ ResolveResult resolveResult = generator.resolveConstDecl(m_ident);
+
// FIXME: This code does not match the behavior of const in Firefox.
- if (RegisterID* local = generator.constRegisterFor(m_ident)) {
+ if (RegisterID* local = resolveResult.local()) {
if (!m_init)
return local;
@@ -1305,27 +1352,15 @@ RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
RefPtr<RegisterID> value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
- ScopeChainIterator iter = generator.scopeChain()->begin();
- ScopeChainIterator end = generator.scopeChain()->end();
- size_t depth = 0;
- for (; iter != end; ++iter, ++depth) {
- JSObject* currentScope = iter->get();
- if (!currentScope->isVariableObject())
- continue;
- JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
- SymbolTableEntry entry = currentVariableObject->symbolTable().get(m_ident.impl());
- if (entry.isNull())
- continue;
-
- return generator.emitPutScopedVar(generator.scopeDepth() + depth, entry.getIndex(), value.get(), currentVariableObject->isGlobalObject() ? currentVariableObject : 0);
- }
-
+ if (resolveResult.isStatic())
+ return generator.emitPutStaticVar(resolveResult, value.get());
+
if (generator.codeType() != EvalCode)
return value.get();
// FIXME: While this code should only be hit in an eval block, it will assign
// to the wrong base if m_ident exists in an intervening with scope.
- RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
+ RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), resolveResult, m_ident);
return generator.emitPutById(base.get(), m_ident, value.get());
}
@@ -1596,11 +1631,12 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds
bool optimizedForinAccess = false;
if (m_lexpr->isResolveNode()) {
const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
- propertyName = generator.registerFor(ident);
+ ResolveResult resolveResult = generator.resolve(ident);
+ propertyName = resolveResult.local();
if (!propertyName) {
propertyName = generator.newTemporary();
RefPtr<RegisterID> protect = propertyName;
- RegisterID* base = generator.emitResolveBaseForPut(generator.newTemporary(), ident);
+ RegisterID* base = generator.emitResolveBaseForPut(generator.newTemporary(), resolveResult, ident);
generator.emitExpressionInfo(divot(), startOffset(), endOffset());
generator.emitPutById(base, ident, propertyName);
@@ -1933,13 +1969,7 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
// Uncaught exception path: the catch block.
RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
- if (m_catchHasEval) {
- RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(generator.newTemporary());
- generator.emitPutById(dynamicScopeObject.get(), m_exceptionIdent, exceptionRegister.get());
- generator.emitMove(exceptionRegister.get(), dynamicScopeObject.get());
- generator.emitPushScope(exceptionRegister.get());
- } else
- generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
+ generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
generator.emitNode(dst, m_catchBlock);
generator.emitPopScope();
generator.emitLabel(catchEndLabel.get());
diff --git a/Source/JavaScriptCore/config.h b/Source/JavaScriptCore/config.h
index d778f63a8..ba65476a5 100644
--- a/Source/JavaScriptCore/config.h
+++ b/Source/JavaScriptCore/config.h
@@ -32,6 +32,9 @@
// WTF cannot depend on JSC even if USE(JSC).
#if USE(JSC) && !defined(BUILDING_WTF)
#include "JSExportMacros.h"
+#elif PLATFORM(CHROMIUM)
+// Chromium doesn't have runtime/ in its include paths.
+#include "runtime/JSExportMacros.h"
#endif
#if OS(WINDOWS)
diff --git a/Source/JavaScriptCore/debugger/Debugger.h b/Source/JavaScriptCore/debugger/Debugger.h
index f48243c45..a23732918 100644
--- a/Source/JavaScriptCore/debugger/Debugger.h
+++ b/Source/JavaScriptCore/debugger/Debugger.h
@@ -58,7 +58,7 @@ namespace JSC {
};
// This function exists only for backwards compatibility with existing WebScriptDebugger clients.
- JSValue evaluateInGlobalCallFrame(const UString&, JSValue& exception, JSGlobalObject*);
+ JS_EXPORT_PRIVATE JSValue evaluateInGlobalCallFrame(const UString&, JSValue& exception, JSGlobalObject*);
} // namespace JSC
diff --git a/Source/JavaScriptCore/debugger/DebuggerActivation.cpp b/Source/JavaScriptCore/debugger/DebuggerActivation.cpp
index 80be310b5..330476da2 100644
--- a/Source/JavaScriptCore/debugger/DebuggerActivation.cpp
+++ b/Source/JavaScriptCore/debugger/DebuggerActivation.cpp
@@ -77,10 +77,10 @@ void DebuggerActivation::put(JSCell* cell, ExecState* exec, const Identifier& pr
thisObject->m_activation->methodTable()->put(thisObject->m_activation.get(), exec, propertyName, value, slot);
}
-void DebuggerActivation::putWithAttributes(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
+void DebuggerActivation::putDirectVirtual(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
{
DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(object);
- thisObject->m_activation->methodTable()->putWithAttributes(thisObject->m_activation.get(), exec, propertyName, value, attributes);
+ thisObject->m_activation->methodTable()->putDirectVirtual(thisObject->m_activation.get(), exec, propertyName, value, attributes);
}
bool DebuggerActivation::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
diff --git a/Source/JavaScriptCore/debugger/DebuggerActivation.h b/Source/JavaScriptCore/debugger/DebuggerActivation.h
index c28d0b3a2..8dba70b80 100644
--- a/Source/JavaScriptCore/debugger/DebuggerActivation.h
+++ b/Source/JavaScriptCore/debugger/DebuggerActivation.h
@@ -45,14 +45,14 @@ namespace JSC {
static UString className(const JSObject*);
static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&);
static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
- static void putWithAttributes(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
+ static void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
static void defineGetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes);
static void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes);
- static const ClassInfo s_info;
+ JS_EXPORTDATA static const ClassInfo s_info;
static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
{
@@ -62,10 +62,10 @@ namespace JSC {
protected:
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | JSObject::StructureFlags;
- void finishCreation(JSGlobalData&, JSObject* activation);
+ JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, JSObject* activation);
private:
- DebuggerActivation(JSGlobalData&);
+ JS_EXPORT_PRIVATE DebuggerActivation(JSGlobalData&);
WriteBarrier<JSActivation> m_activation;
};
diff --git a/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp b/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp
index 08fba4a6b..6a8cdb2dc 100644
--- a/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp
+++ b/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp
@@ -56,10 +56,11 @@ UString DebuggerCallFrame::calculatedFunctionName() const
return UString();
JSObject* function = m_callFrame->callee();
- if (!function || !function->inherits(&JSFunction::s_info))
+
+ if (!function)
return UString();
- return asFunction(function)->calculatedDisplayName(m_callFrame);
+ return getCalculatedDisplayName(m_callFrame, function);
}
DebuggerCallFrame::Type DebuggerCallFrame::type() const
diff --git a/Source/JavaScriptCore/debugger/DebuggerCallFrame.h b/Source/JavaScriptCore/debugger/DebuggerCallFrame.h
index d8fb9dae5..8605af54d 100644
--- a/Source/JavaScriptCore/debugger/DebuggerCallFrame.h
+++ b/Source/JavaScriptCore/debugger/DebuggerCallFrame.h
@@ -50,7 +50,7 @@ namespace JSC {
JSGlobalObject* dynamicGlobalObject() const { return m_callFrame->dynamicGlobalObject(); }
ScopeChainNode* scopeChain() const { return m_callFrame->scopeChain(); }
- const UString* functionName() const;
+ JS_EXPORT_PRIVATE const UString* functionName() const;
JS_EXPORT_PRIVATE UString calculatedFunctionName() const;
JS_EXPORT_PRIVATE Type type() const;
JS_EXPORT_PRIVATE JSObject* thisObject() const;
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index eb00bcb3c..bd35e1d43 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -121,6 +121,8 @@ void AbstractState::initialize(Graph& graph)
root->valuesAtHead.argument(i).set(PredictInt32Array);
else if (isUint8ArrayPrediction(prediction))
root->valuesAtHead.argument(i).set(PredictUint8Array);
+ else if (isUint8ClampedArrayPrediction(prediction))
+ root->valuesAtHead.argument(i).set(PredictUint8ClampedArray);
else if (isUint16ArrayPrediction(prediction))
root->valuesAtHead.argument(i).set(PredictUint16Array);
else if (isUint32ArrayPrediction(prediction))
@@ -151,14 +153,14 @@ bool AbstractState::endBasicBlock(MergeMode mergeMode)
if (mergeMode != DontMerge || !ASSERT_DISABLED) {
for (size_t argument = 0; argument < block->variablesAtTail.numberOfArguments(); ++argument) {
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- printf(" Merging state for argument %lu.\n", argument);
+ printf(" Merging state for argument %zu.\n", argument);
#endif
changed |= mergeStateAtTail(block->valuesAtTail.argument(argument), m_variables.argument(argument), block->variablesAtTail.argument(argument));
}
for (size_t local = 0; local < block->variablesAtTail.numberOfLocals(); ++local) {
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- printf(" Merging state for local %lu.\n", local);
+ printf(" Merging state for local %zu.\n", local);
#endif
changed |= mergeStateAtTail(block->valuesAtTail.local(local), m_variables.local(local), block->variablesAtTail.local(local));
}
@@ -278,7 +280,7 @@ bool AbstractState::execute(NodeIndex nodeIndex)
case ValueAdd:
case ArithAdd: {
- if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()]) && node.canSpeculateInteger()) {
+ if (m_graph.addShouldSpeculateInteger(node, m_codeBlock)) {
forNode(node.child1()).filter(PredictInt32);
forNode(node.child2()).filter(PredictInt32);
forNode(nodeIndex).set(PredictInt32);
@@ -296,7 +298,19 @@ bool AbstractState::execute(NodeIndex nodeIndex)
break;
}
- case ArithSub:
+ case ArithSub: {
+ if (m_graph.addShouldSpeculateInteger(node, m_codeBlock)) {
+ forNode(node.child1()).filter(PredictInt32);
+ forNode(node.child2()).filter(PredictInt32);
+ forNode(nodeIndex).set(PredictInt32);
+ break;
+ }
+ forNode(node.child1()).filter(PredictNumber);
+ forNode(node.child2()).filter(PredictNumber);
+ forNode(nodeIndex).set(PredictDouble);
+ break;
+ }
+
case ArithMul:
case ArithDiv:
case ArithMin:
@@ -448,6 +462,12 @@ bool AbstractState::execute(NodeIndex nodeIndex)
forNode(nodeIndex).set(PredictInt32);
break;
}
+ if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
+ forNode(node.child1()).filter(PredictUint8ClampedArray);
+ forNode(node.child2()).filter(PredictInt32);
+ forNode(nodeIndex).set(PredictInt32);
+ break;
+ }
if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
forNode(node.child1()).filter(PredictUint16Array);
forNode(node.child2()).filter(PredictInt32);
@@ -522,6 +542,12 @@ bool AbstractState::execute(NodeIndex nodeIndex)
forNode(node.child3()).filter(PredictNumber);
break;
}
+ if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
+ forNode(node.child1()).filter(PredictUint8ClampedArray);
+ forNode(node.child2()).filter(PredictInt32);
+ forNode(node.child3()).filter(PredictNumber);
+ break;
+ }
if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
forNode(node.child1()).filter(PredictUint16Array);
forNode(node.child2()).filter(PredictInt32);
@@ -688,6 +714,7 @@ bool AbstractState::execute(NodeIndex nodeIndex)
break;
case GetById:
+ case GetByIdFlush:
if (!node.prediction()) {
m_isValid = false;
break;
@@ -728,6 +755,10 @@ bool AbstractState::execute(NodeIndex nodeIndex)
forNode(node.child1()).filter(PredictUint8Array);
forNode(nodeIndex).set(PredictInt32);
break;
+ case GetUint8ClampedArrayLength:
+ forNode(node.child1()).filter(PredictUint8ClampedArray);
+ forNode(nodeIndex).set(PredictInt32);
+ break;
case GetUint16ArrayLength:
forNode(node.child1()).filter(PredictUint16Array);
forNode(nodeIndex).set(PredictInt32);
@@ -797,6 +828,11 @@ bool AbstractState::execute(NodeIndex nodeIndex)
forNode(nodeIndex).clear();
break;
}
+ if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
+ forNode(node.child1()).filter(PredictUint8ClampedArray);
+ forNode(nodeIndex).clear();
+ break;
+ }
if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
forNode(node.child1()).filter(PredictUint16Array);
forNode(nodeIndex).set(PredictOther);
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractValue.h b/Source/JavaScriptCore/dfg/DFGAbstractValue.h
index ee43b6c4a..15bc0d496 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractValue.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractValue.h
@@ -30,9 +30,9 @@
#if ENABLE(DFG_JIT)
-#include "DFGStructureSet.h"
#include "JSCell.h"
#include "PredictedType.h"
+#include "StructureSet.h"
namespace JSC { namespace DFG {
diff --git a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
index a9dec5062..e0d817c9f 100644
--- a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
+++ b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
@@ -246,6 +246,16 @@ public:
m_assembler.vmov(fpr, payloadGPR, tagGPR);
}
#endif
+
+ enum ExceptionCheckKind { NormalExceptionCheck, InvertedExceptionCheck };
+ Jump emitExceptionCheck(ExceptionCheckKind kind = NormalExceptionCheck)
+ {
+#if USE(JSVALUE64)
+ return branchTestPtr(kind == NormalExceptionCheck ? NonZero : Zero, AbsoluteAddress(&globalData()->exception));
+#elif USE(JSVALUE32_64)
+ return branch32(kind == NormalExceptionCheck ? NotEqual : Equal, AbsoluteAddress(reinterpret_cast<char*>(&globalData()->exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
+#endif
+ }
#if ENABLE(SAMPLING_COUNTERS)
static void emitCount(MacroAssembler& jit, AbstractSamplingCounter& counter, int32_t increment = 1)
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index 964618c43..87c3a23b9 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -28,9 +28,13 @@
#if ENABLE(DFG_JIT)
+#include "CallLinkStatus.h"
+#include "CodeBlock.h"
#include "DFGByteCodeCache.h"
#include "DFGCapabilities.h"
-#include "CodeBlock.h"
+#include "GetByIdStatus.h"
+#include "MethodCallLinkStatus.h"
+#include "PutByIdStatus.h"
#include <wtf/HashMap.h>
#include <wtf/MathExtras.h>
@@ -48,6 +52,7 @@ public:
, m_graph(graph)
, m_currentBlock(0)
, m_currentIndex(0)
+ , m_currentProfilingIndex(0)
, m_constantUndefined(UINT_MAX)
, m_constantNull(UINT_MAX)
, m_constantNaN(UINT_MAX)
@@ -329,7 +334,8 @@ private:
JSValue v = valueOfJSConstant(index);
if (v.isInt32())
return getJSConstant(node.constantNumber());
- // FIXME: We could convert the double ToInteger at this point.
+ if (v.isNumber())
+ return getJSConstantForValue(JSValue(JSC::toInt32(v.asNumber())));
}
return addToGraph(ValueToInt32, index);
@@ -351,6 +357,17 @@ private:
return addToGraph(ValueToNumber, OpInfo(NodeUseBottom), index);
}
+
+ NodeIndex getJSConstantForValue(JSValue constantValue)
+ {
+ unsigned constantIndex = m_codeBlock->addOrFindConstant(constantValue);
+ if (constantIndex >= m_constants.size())
+ m_constants.append(ConstantRecord());
+
+ ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
+
+ return getJSConstant(constantIndex);
+ }
NodeIndex getJSConstant(unsigned constant)
{
@@ -382,16 +399,6 @@ private:
{
return isJSConstant(nodeIndex) && valueOfJSConstant(nodeIndex).isInt32();
}
- bool isSmallInt32Constant(NodeIndex nodeIndex)
- {
- if (!isJSConstant(nodeIndex))
- return false;
- JSValue value = valueOfJSConstant(nodeIndex);
- if (!value.isInt32())
- return false;
- int32_t intValue = value.asInt32();
- return intValue >= -5 && intValue <= 5;
- }
// Convenience methods for getting constant values.
JSValue valueOfJSConstant(NodeIndex index)
{
@@ -403,7 +410,7 @@ private:
ASSERT(isInt32Constant(nodeIndex));
return valueOfJSConstant(nodeIndex).asInt32();
}
-
+
// This method returns a JSConstant with the value 'undefined'.
NodeIndex constantUndefined()
{
@@ -519,7 +526,7 @@ private:
CodeOrigin currentCodeOrigin()
{
- return CodeOrigin(m_currentIndex, m_inlineStackTop->m_inlineCallFrame);
+ return CodeOrigin(m_currentIndex, m_inlineStackTop->m_inlineCallFrame, m_currentProfilingIndex - m_currentIndex);
}
// These methods create a node and add it to the graph. If nodes of this type are
@@ -574,8 +581,10 @@ private:
Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
PredictedType prediction = PredictNone;
- if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
- prediction = getPrediction(m_graph.size(), m_currentIndex + OPCODE_LENGTH(op_call));
+ if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
+ m_currentProfilingIndex = m_currentIndex + OPCODE_LENGTH(op_call);
+ prediction = getPrediction();
+ }
addVarArgChild(get(currentInstruction[1].u.operand));
int argCount = currentInstruction[2].u.operand;
@@ -622,12 +631,12 @@ private:
PredictedType getPredictionWithoutOSRExit()
{
- return getPredictionWithoutOSRExit(m_graph.size(), m_currentIndex);
+ return getPredictionWithoutOSRExit(m_graph.size(), m_currentProfilingIndex);
}
PredictedType getPrediction()
{
- return getPrediction(m_graph.size(), m_currentIndex);
+ return getPrediction(m_graph.size(), m_currentProfilingIndex);
}
NodeIndex makeSafe(NodeIndex nodeIndex)
@@ -700,6 +709,29 @@ private:
return nodeIndex;
}
+ bool willNeedFlush(StructureStubInfo& stubInfo)
+ {
+ PolymorphicAccessStructureList* list;
+ int listSize;
+ switch (stubInfo.accessType) {
+ case access_get_by_id_self_list:
+ list = stubInfo.u.getByIdSelfList.structureList;
+ listSize = stubInfo.u.getByIdSelfList.listSize;
+ break;
+ case access_get_by_id_proto_list:
+ list = stubInfo.u.getByIdProtoList.structureList;
+ listSize = stubInfo.u.getByIdProtoList.listSize;
+ break;
+ default:
+ return false;
+ }
+ for (int i = 0; i < listSize; ++i) {
+ if (!list->list[i].isDirect)
+ return true;
+ }
+ return false;
+ }
+
bool structureChainIsStillValid(bool direct, Structure* previousStructure, StructureChain* chain)
{
if (direct)
@@ -727,6 +759,8 @@ private:
BasicBlock* m_currentBlock;
// The bytecode index of the current instruction being generated.
unsigned m_currentIndex;
+ // The bytecode index of the value profile of the current instruction being generated.
+ unsigned m_currentProfilingIndex;
// We use these values during code generation, and to avoid the need for
// special handling we make sure they are available as constants in the
@@ -890,6 +924,7 @@ private:
m_currentIndex += OPCODE_LENGTH(name); \
return shouldContinueParsing
+
void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentInstruction, NodeType op, CodeSpecializationKind kind)
{
ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
@@ -898,13 +933,15 @@ void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentIn
enum { ConstantFunction, LinkedFunction, UnknownFunction } callType;
#if DFG_ENABLE(DEBUG_VERBOSE)
- printf("Slow case count for call at @%lu bc#%u: %u/%u; exit profile: %d.\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_profiledBlock->executionEntryCount(), m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
+ printf("Slow case count for call at @%zu bc#%u: %u/%u; exit profile: %d.\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_profiledBlock->executionEntryCount(), m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
#endif
-
+
+ CallLinkStatus callLinkStatus = CallLinkStatus::computeFor(
+ m_inlineStackTop->m_profiledBlock, m_currentIndex);
+
if (m_graph.isFunctionConstant(m_codeBlock, callTarget))
callType = ConstantFunction;
- else if (!!m_inlineStackTop->m_profiledBlock->getCallLinkInfo(m_currentIndex).lastSeenCallee
- && !m_inlineStackTop->m_profiledBlock->couldTakeSlowCase(m_currentIndex)
+ else if (callLinkStatus.isSet() && !callLinkStatus.couldTakeSlowPath()
&& !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache))
callType = LinkedFunction;
else
@@ -922,7 +959,8 @@ void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentIn
if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
resultOperand = putInstruction[1].u.operand;
usesResult = true;
- prediction = getPrediction(m_graph.size(), nextOffset);
+ m_currentProfilingIndex = nextOffset;
+ prediction = getPrediction();
nextOffset += OPCODE_LENGTH(op_call_put_result);
}
JSFunction* expectedFunction;
@@ -934,7 +972,7 @@ void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentIn
certainAboutExpectedFunction = true;
} else {
ASSERT(callType == LinkedFunction);
- expectedFunction = m_inlineStackTop->m_profiledBlock->getCallLinkInfo(m_currentIndex).lastSeenCallee.get();
+ expectedFunction = callLinkStatus.callTarget();
intrinsic = expectedFunction->executable()->intrinsicFor(kind);
certainAboutExpectedFunction = false;
}
@@ -1029,7 +1067,7 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c
int inlineCallFrameStart = m_inlineStackTop->remapOperand(registerOffset) - RegisterFile::CallFrameHeaderSize;
// Make sure that the area used by the call frame is reserved.
- for (int arg = inlineCallFrameStart + RegisterFile::CallFrameHeaderSize + codeBlock->m_numVars; arg-- > inlineCallFrameStart + 1;)
+ for (int arg = inlineCallFrameStart + RegisterFile::CallFrameHeaderSize + codeBlock->m_numVars; arg-- > inlineCallFrameStart;)
m_preservedVars.set(m_inlineStackTop->remapOperand(arg));
// Make sure that we have enough locals.
@@ -1044,13 +1082,16 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c
// This is where the actual inlining really happens.
unsigned oldIndex = m_currentIndex;
+ unsigned oldProfilingIndex = m_currentProfilingIndex;
m_currentIndex = 0;
+ m_currentProfilingIndex = 0;
addToGraph(InlineStart);
parseCodeBlock();
m_currentIndex = oldIndex;
+ m_currentProfilingIndex = oldProfilingIndex;
// If the inlined code created some new basic blocks, then we have linking to do.
if (inlineStackEntry.m_callsiteBlockHead != m_graph.m_blocks.size() - 1) {
@@ -1129,7 +1170,7 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c
// Need to create a new basic block for the continuation at the caller.
OwnPtr<BasicBlock> block = adoptPtr(new BasicBlock(nextOffset, m_graph.size(), m_numArguments, m_numLocals));
#if DFG_ENABLE(DEBUG_VERBOSE)
- printf("Creating inline epilogue basic block %p, #%lu for %p bc#%u at inline depth %u.\n", block.get(), m_graph.m_blocks.size(), m_inlineStackTop->executable(), m_currentIndex, CodeOrigin::inlineDepthForCallFrame(m_inlineStackTop->m_inlineCallFrame));
+ printf("Creating inline epilogue basic block %p, #%zu for %p bc#%u at inline depth %u.\n", block.get(), m_graph.m_blocks.size(), m_inlineStackTop->executable(), m_currentIndex, CodeOrigin::inlineDepthForCallFrame(m_inlineStackTop->m_inlineCallFrame));
#endif
m_currentBlock = block.get();
ASSERT(m_inlineStackTop->m_caller->m_blockLinkingTargets.isEmpty() || m_graph.m_blocks[m_inlineStackTop->m_caller->m_blockLinkingTargets.last()]->bytecodeBegin < nextOffset);
@@ -1308,6 +1349,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
}
while (true) {
+ m_currentProfilingIndex = m_currentIndex;
+
// Don't extend over jump destinations.
if (m_currentIndex == limit) {
// Ordinarily we want to plant a jump. But refuse to do this if the block is
@@ -1680,6 +1723,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
}
case op_method_check: {
+ m_currentProfilingIndex += OPCODE_LENGTH(op_method_check);
Instruction* getInstruction = currentInstruction + OPCODE_LENGTH(op_method_check);
PredictedType prediction = getPrediction();
@@ -1691,23 +1735,26 @@ bool ByteCodeParser::parseBlock(unsigned limit)
// Check if the method_check was monomorphic. If so, emit a CheckXYZMethod
// node, which is a lot more efficient.
- StructureStubInfo& stubInfo = m_inlineStackTop->m_profiledBlock->getStubInfo(m_currentIndex);
- MethodCallLinkInfo& methodCall = m_inlineStackTop->m_profiledBlock->getMethodCallLinkInfo(m_currentIndex);
+ GetByIdStatus getByIdStatus = GetByIdStatus::computeFor(
+ m_inlineStackTop->m_profiledBlock,
+ m_currentIndex,
+ m_codeBlock->identifier(identifier));
+ MethodCallLinkStatus methodCallStatus = MethodCallLinkStatus::computeFor(
+ m_inlineStackTop->m_profiledBlock, m_currentIndex);
- if (methodCall.seen
- && !!methodCall.cachedStructure
- && !stubInfo.seen
+ if (methodCallStatus.isSet()
+ && !getByIdStatus.isSet()
&& !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
// It's monomorphic as far as we can tell, since the method_check was linked
// but the slow path (i.e. the normal get_by_id) never fired.
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCall.cachedStructure.get())), base);
- if (methodCall.cachedPrototype.get() != m_inlineStackTop->m_profiledBlock->globalObject()->methodCallDummy())
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCall.cachedPrototypeStructure.get())), cellConstant(methodCall.cachedPrototype.get()));
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCallStatus.structure())), base);
+ if (methodCallStatus.needsPrototypeCheck())
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCallStatus.prototypeStructure())), cellConstant(methodCallStatus.prototype()));
- set(getInstruction[1].u.operand, cellConstant(methodCall.cachedFunction.get()));
+ set(getInstruction[1].u.operand, cellConstant(methodCallStatus.function()));
} else
- set(getInstruction[1].u.operand, addToGraph(GetById, OpInfo(identifier), OpInfo(prediction), base));
+ set(getInstruction[1].u.operand, addToGraph(getByIdStatus.makesCalls() ? GetByIdFlush : GetById, OpInfo(identifier), OpInfo(prediction), base));
m_currentIndex += OPCODE_LENGTH(op_method_check) + OPCODE_LENGTH(op_get_by_id);
continue;
@@ -1737,178 +1784,109 @@ bool ByteCodeParser::parseBlock(unsigned limit)
unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[3].u.operand];
Identifier identifier = m_codeBlock->identifier(identifierNumber);
- StructureStubInfo& stubInfo = m_inlineStackTop->m_profiledBlock->getStubInfo(m_currentIndex);
+ GetByIdStatus getByIdStatus = GetByIdStatus::computeFor(
+ m_inlineStackTop->m_profiledBlock, m_currentIndex, identifier);
#if DFG_ENABLE(DEBUG_VERBOSE)
- printf("Slow case count for GetById @%lu bc#%u: %u; exit profile: %d\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
+ printf("Slow case count for GetById @%zu bc#%u: %u; exit profile: %d\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
#endif
- size_t offset = notFound;
- StructureSet structureSet;
- if (stubInfo.seen
- && !m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)
+ if (getByIdStatus.isSimpleDirect()
&& !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
- switch (stubInfo.accessType) {
- case access_get_by_id_self: {
- Structure* structure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
- offset = structure->get(*m_globalData, identifier);
-
- if (offset != notFound)
- structureSet.add(structure);
-
- if (offset != notFound)
- ASSERT(structureSet.size());
- break;
- }
-
- case access_get_by_id_self_list: {
- PolymorphicAccessStructureList* list = stubInfo.u.getByIdProtoList.structureList;
- unsigned size = stubInfo.u.getByIdProtoList.listSize;
- for (unsigned i = 0; i < size; ++i) {
- if (!list->list[i].isDirect) {
- offset = notFound;
- break;
- }
-
- Structure* structure = list->list[i].base.get();
- if (structureSet.contains(structure))
- continue;
-
- size_t myOffset = structure->get(*m_globalData, identifier);
-
- if (myOffset == notFound) {
- offset = notFound;
- break;
- }
-
- if (!i)
- offset = myOffset;
- else if (offset != myOffset) {
- offset = notFound;
- break;
- }
-
- structureSet.add(structure);
- }
-
- if (offset != notFound)
- ASSERT(structureSet.size());
- break;
- }
-
- default:
- ASSERT(offset == notFound);
- break;
- }
- }
-
- if (offset != notFound) {
- ASSERT(structureSet.size());
+ ASSERT(getByIdStatus.structureSet().size());
// The implementation of GetByOffset does not know to terminate speculative
// execution if it doesn't have a prediction, so we do it manually.
if (prediction == PredictNone)
addToGraph(ForceOSRExit);
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structureSet)), base);
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(getByIdStatus.structureSet())), base);
set(currentInstruction[1].u.operand, addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), addToGraph(GetPropertyStorage, base)));
StorageAccessData storageAccessData;
- storageAccessData.offset = offset;
+ storageAccessData.offset = getByIdStatus.offset();
storageAccessData.identifierNumber = identifierNumber;
m_graph.m_storageAccessData.append(storageAccessData);
} else
- set(currentInstruction[1].u.operand, addToGraph(GetById, OpInfo(identifierNumber), OpInfo(prediction), base));
+ set(currentInstruction[1].u.operand, addToGraph(getByIdStatus.makesCalls() ? GetByIdFlush : GetById, OpInfo(identifierNumber), OpInfo(prediction), base));
NEXT_OPCODE(op_get_by_id);
}
-
case op_put_by_id: {
NodeIndex value = get(currentInstruction[3].u.operand);
NodeIndex base = get(currentInstruction[1].u.operand);
unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
bool direct = currentInstruction[8].u.operand;
- StructureStubInfo& stubInfo = m_inlineStackTop->m_profiledBlock->getStubInfo(m_currentIndex);
- if (!stubInfo.seen)
+ PutByIdStatus putByIdStatus = PutByIdStatus::computeFor(
+ m_inlineStackTop->m_profiledBlock,
+ m_currentIndex,
+ m_codeBlock->identifier(identifierNumber));
+ if (!putByIdStatus.isSet())
addToGraph(ForceOSRExit);
- bool alreadyGenerated = false;
+ bool hasExitSite = m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache);
#if DFG_ENABLE(DEBUG_VERBOSE)
- printf("Slow case count for PutById @%lu bc#%u: %u; exit profile: %d\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
+ printf("Slow case count for PutById @%zu bc#%u: %u; exit profile: %d\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
#endif
- if (stubInfo.seen
- && !m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)
- && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
- switch (stubInfo.accessType) {
- case access_put_by_id_replace: {
- Structure* structure = stubInfo.u.putByIdReplace.baseObjectStructure.get();
- Identifier identifier = m_codeBlock->identifier(identifierNumber);
- size_t offset = structure->get(*m_globalData, identifier);
-
- if (offset != notFound) {
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structure)), base);
- addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
-
- StorageAccessData storageAccessData;
- storageAccessData.offset = offset;
- storageAccessData.identifierNumber = identifierNumber;
- m_graph.m_storageAccessData.append(storageAccessData);
-
- alreadyGenerated = true;
- }
- break;
- }
-
- case access_put_by_id_transition_normal:
- case access_put_by_id_transition_direct: {
- Structure* previousStructure = stubInfo.u.putByIdTransition.previousStructure.get();
- Structure* newStructure = stubInfo.u.putByIdTransition.structure.get();
-
- if (previousStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity())
- break;
-
- StructureChain* structureChain = stubInfo.u.putByIdTransition.chain.get();
-
- Identifier identifier = m_codeBlock->identifier(identifierNumber);
- size_t offset = newStructure->get(*m_globalData, identifier);
+ if (!hasExitSite && putByIdStatus.isSimpleReplace()) {
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure())), base);
+ addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
+
+ StorageAccessData storageAccessData;
+ storageAccessData.offset = putByIdStatus.offset();
+ storageAccessData.identifierNumber = identifierNumber;
+ m_graph.m_storageAccessData.append(storageAccessData);
+ } else if (!hasExitSite
+ && putByIdStatus.isSimpleTransition()
+ && putByIdStatus.oldStructure()->propertyStorageCapacity() == putByIdStatus.newStructure()->propertyStorageCapacity()
+ && structureChainIsStillValid(
+ direct,
+ putByIdStatus.oldStructure(),
+ putByIdStatus.structureChain())) {
+
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure())), base);
+ if (!direct) {
+ if (!putByIdStatus.oldStructure()->storedPrototype().isNull())
+ addToGraph(
+ CheckStructure,
+ OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure()->storedPrototype().asCell()->structure())),
+ cellConstant(putByIdStatus.oldStructure()->storedPrototype().asCell()));
- if (offset != notFound && structureChainIsStillValid(direct, previousStructure, structureChain)) {
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(previousStructure)), base);
- if (!direct) {
- if (!previousStructure->storedPrototype().isNull())
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(previousStructure->storedPrototype().asCell()->structure())), cellConstant(previousStructure->storedPrototype().asCell()));
-
- for (WriteBarrier<Structure>* it = structureChain->head(); *it; ++it) {
- JSValue prototype = (*it)->storedPrototype();
- if (prototype.isNull())
- continue;
- ASSERT(prototype.isCell());
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(prototype.asCell()->structure())), cellConstant(prototype.asCell()));
- }
- }
- addToGraph(PutStructure, OpInfo(m_graph.addStructureTransitionData(StructureTransitionData(previousStructure, newStructure))), base);
-
- addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
-
- StorageAccessData storageAccessData;
- storageAccessData.offset = offset;
- storageAccessData.identifierNumber = identifierNumber;
- m_graph.m_storageAccessData.append(storageAccessData);
-
- alreadyGenerated = true;
+ for (WriteBarrier<Structure>* it = putByIdStatus.structureChain()->head(); *it; ++it) {
+ JSValue prototype = (*it)->storedPrototype();
+ if (prototype.isNull())
+ continue;
+ ASSERT(prototype.isCell());
+ addToGraph(
+ CheckStructure,
+ OpInfo(m_graph.addStructureSet(prototype.asCell()->structure())),
+ cellConstant(prototype.asCell()));
}
- break;
- }
-
- default:
- break;
}
- }
-
- if (!alreadyGenerated) {
+ addToGraph(
+ PutStructure,
+ OpInfo(
+ m_graph.addStructureTransitionData(
+ StructureTransitionData(
+ putByIdStatus.oldStructure(),
+ putByIdStatus.newStructure()))),
+ base);
+
+ addToGraph(
+ PutByOffset,
+ OpInfo(m_graph.m_storageAccessData.size()),
+ base,
+ addToGraph(GetPropertyStorage, base),
+ value);
+
+ StorageAccessData storageAccessData;
+ storageAccessData.offset = putByIdStatus.offset();
+ storageAccessData.identifierNumber = identifierNumber;
+ m_graph.m_storageAccessData.append(storageAccessData);
+ } else {
if (direct)
addToGraph(PutByIdDirect, OpInfo(identifierNumber), base, value);
else
@@ -2570,7 +2548,7 @@ void ByteCodeParser::parseCodeBlock()
} else {
OwnPtr<BasicBlock> block = adoptPtr(new BasicBlock(m_currentIndex, m_graph.size(), m_numArguments, m_numLocals));
#if DFG_ENABLE(DEBUG_VERBOSE)
- printf("Creating basic block %p, #%lu for %p bc#%u at inline depth %u.\n", block.get(), m_graph.m_blocks.size(), m_inlineStackTop->executable(), m_currentIndex, CodeOrigin::inlineDepthForCallFrame(m_inlineStackTop->m_inlineCallFrame));
+ printf("Creating basic block %p, #%zu for %p bc#%u at inline depth %u.\n", block.get(), m_graph.m_blocks.size(), m_inlineStackTop->executable(), m_currentIndex, CodeOrigin::inlineDepthForCallFrame(m_inlineStackTop->m_inlineCallFrame));
#endif
m_currentBlock = block.get();
ASSERT(m_inlineStackTop->m_unlinkedBlocks.isEmpty() || m_graph.m_blocks[m_inlineStackTop->m_unlinkedBlocks.last().m_blockIndex]->bytecodeBegin < m_currentIndex);
@@ -2620,6 +2598,9 @@ bool ByteCodeParser::parse()
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
printf("Processing local variable phis.\n");
#endif
+
+ m_currentProfilingIndex = m_currentIndex;
+
processPhiStack<LocalPhiStack>();
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
printf("Processing argument phis.\n");
diff --git a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
new file mode 100644
index 000000000..3481f99e8
--- /dev/null
+++ b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
@@ -0,0 +1,548 @@
+/*
+ * Copyright (C) 2011 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 DFGCCallHelpers_h
+#define DFGCCallHelpers_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGAssemblyHelpers.h"
+#include "DFGGPRInfo.h"
+
+namespace JSC { namespace DFG {
+
+class CCallHelpers : public AssemblyHelpers {
+public:
+ CCallHelpers(JSGlobalData* globalData, CodeBlock* codeBlock)
+ : AssemblyHelpers(globalData, codeBlock)
+ {
+ }
+
+ // These methods used to sort arguments into the correct registers.
+ // On X86 we use cdecl calling conventions, which pass all arguments on the
+ // stack. On other architectures we may need to sort values into the
+ // correct registers.
+#if !NUMBER_OF_ARGUMENT_REGISTERS
+ unsigned m_callArgumentOffset;
+ void resetCallArguments() { m_callArgumentOffset = 0; }
+
+ // These methods are using internally to implement the callOperation methods.
+ void addCallArgument(GPRReg value)
+ {
+ poke(value, m_callArgumentOffset++);
+ }
+ void addCallArgument(TrustedImm32 imm)
+ {
+ poke(imm, m_callArgumentOffset++);
+ }
+ void addCallArgument(TrustedImmPtr pointer)
+ {
+ poke(pointer, m_callArgumentOffset++);
+ }
+ void addCallArgument(FPRReg value)
+ {
+ storeDouble(value, Address(stackPointerRegister, m_callArgumentOffset * sizeof(void*)));
+ m_callArgumentOffset += sizeof(double) / sizeof(void*);
+ }
+
+ ALWAYS_INLINE void setupArguments(FPRReg arg1)
+ {
+ resetCallArguments();
+ addCallArgument(arg1);
+ }
+
+ ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
+ {
+ resetCallArguments();
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ }
+
+ ALWAYS_INLINE void setupArguments(GPRReg arg1, GPRReg arg2)
+ {
+ resetCallArguments();
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ }
+
+ ALWAYS_INLINE void setupArgumentsExecState()
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ addCallArgument(arg3);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ addCallArgument(arg3);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ addCallArgument(arg3);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImmPtr arg3)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ addCallArgument(arg3);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ addCallArgument(arg3);
+ addCallArgument(arg4);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ addCallArgument(arg3);
+ addCallArgument(arg4);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImm32 arg4)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ addCallArgument(arg3);
+ addCallArgument(arg4);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3, GPRReg arg4)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ addCallArgument(arg3);
+ addCallArgument(arg4);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ addCallArgument(arg3);
+ addCallArgument(arg4);
+ addCallArgument(arg5);
+ }
+#endif // !NUMBER_OF_ARGUMENT_REGISTERS
+ // These methods are suitable for any calling convention that provides for
+ // at least 4 argument registers, e.g. X86_64, ARMv7.
+#if NUMBER_OF_ARGUMENT_REGISTERS >= 4
+ template<GPRReg destA, GPRReg destB>
+ void setupTwoStubArgs(GPRReg srcA, GPRReg srcB)
+ {
+ // Assuming that srcA != srcB, there are 7 interesting states the registers may be in:
+ // (1) both are already in arg regs, the right way around.
+ // (2) both are already in arg regs, the wrong way around.
+ // (3) neither are currently in arg registers.
+ // (4) srcA in in its correct reg.
+ // (5) srcA in in the incorrect reg.
+ // (6) srcB in in its correct reg.
+ // (7) srcB in in the incorrect reg.
+ //
+ // The trivial approach is to simply emit two moves, to put srcA in place then srcB in
+ // place (the MacroAssembler will omit redundant moves). This apporach will be safe in
+ // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2
+ // (requires a swap) and 7 (must move srcB first, to avoid trampling.)
+
+ if (srcB != destA) {
+ // Handle the easy cases - two simple moves.
+ move(srcA, destA);
+ move(srcB, destB);
+ } else if (srcA != destB) {
+ // Handle the non-swap case - just put srcB in place first.
+ move(srcB, destB);
+ move(srcA, destA);
+ } else
+ swap(destA, destB);
+ }
+#if CPU(X86_64)
+ template<FPRReg destA, FPRReg destB>
+ void setupTwoStubArgs(FPRReg srcA, FPRReg srcB)
+ {
+ // Assuming that srcA != srcB, there are 7 interesting states the registers may be in:
+ // (1) both are already in arg regs, the right way around.
+ // (2) both are already in arg regs, the wrong way around.
+ // (3) neither are currently in arg registers.
+ // (4) srcA in in its correct reg.
+ // (5) srcA in in the incorrect reg.
+ // (6) srcB in in its correct reg.
+ // (7) srcB in in the incorrect reg.
+ //
+ // The trivial approach is to simply emit two moves, to put srcA in place then srcB in
+ // place (the MacroAssembler will omit redundant moves). This apporach will be safe in
+ // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2
+ // (requires a swap) and 7 (must move srcB first, to avoid trampling.)
+
+ if (srcB != destA) {
+ // Handle the easy cases - two simple moves.
+ moveDouble(srcA, destA);
+ moveDouble(srcB, destB);
+ return;
+ }
+
+ if (srcA != destB) {
+ // Handle the non-swap case - just put srcB in place first.
+ moveDouble(srcB, destB);
+ moveDouble(srcA, destA);
+ return;
+ }
+
+ ASSERT(srcB == destA && srcA == destB);
+ // Need to swap; pick a temporary register.
+ FPRReg temp;
+ if (destA != FPRInfo::argumentFPR3 && destA != FPRInfo::argumentFPR3)
+ temp = FPRInfo::argumentFPR3;
+ else if (destA != FPRInfo::argumentFPR2 && destA != FPRInfo::argumentFPR2)
+ temp = FPRInfo::argumentFPR2;
+ else {
+ ASSERT(destA != FPRInfo::argumentFPR1 && destA != FPRInfo::argumentFPR1);
+ temp = FPRInfo::argumentFPR1;
+ }
+ moveDouble(destA, temp);
+ moveDouble(destB, destA);
+ moveDouble(temp, destB);
+ }
+#endif
+ void setupStubArguments(GPRReg arg1, GPRReg arg2)
+ {
+ setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(arg1, arg2);
+ }
+ void setupStubArguments(GPRReg arg1, GPRReg arg2, GPRReg arg3)
+ {
+ // If neither of arg2/arg3 are in our way, then we can move arg1 into place.
+ // Then we can use setupTwoStubArgs to fix arg2/arg3.
+ if (arg2 != GPRInfo::argumentGPR1 && arg3 != GPRInfo::argumentGPR1) {
+ move(arg1, GPRInfo::argumentGPR1);
+ setupTwoStubArgs<GPRInfo::argumentGPR2, GPRInfo::argumentGPR3>(arg2, arg3);
+ return;
+ }
+
+ // If neither of arg1/arg3 are in our way, then we can move arg2 into place.
+ // Then we can use setupTwoStubArgs to fix arg1/arg3.
+ if (arg1 != GPRInfo::argumentGPR2 && arg3 != GPRInfo::argumentGPR2) {
+ move(arg2, GPRInfo::argumentGPR2);
+ setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR3>(arg1, arg3);
+ return;
+ }
+
+ // If neither of arg1/arg2 are in our way, then we can move arg3 into place.
+ // Then we can use setupTwoStubArgs to fix arg1/arg2.
+ if (arg1 != GPRInfo::argumentGPR3 && arg2 != GPRInfo::argumentGPR3) {
+ move(arg3, GPRInfo::argumentGPR3);
+ setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(arg1, arg2);
+ return;
+ }
+
+ // If we get here, we haven't been able to move any of arg1/arg2/arg3.
+ // Since all three are blocked, then all three must already be in the argument register.
+ // But are they in the right ones?
+
+ // First, ensure arg1 is in place.
+ if (arg1 != GPRInfo::argumentGPR1) {
+ swap(arg1, GPRInfo::argumentGPR1);
+
+ // If arg1 wasn't in argumentGPR1, one of arg2/arg3 must be.
+ ASSERT(arg2 == GPRInfo::argumentGPR1 || arg3 == GPRInfo::argumentGPR1);
+ // If arg2 was in argumentGPR1 it no longer is (due to the swap).
+ // Otherwise arg3 must have been. Mark him as moved.
+ if (arg2 == GPRInfo::argumentGPR1)
+ arg2 = arg1;
+ else
+ arg3 = arg1;
+ }
+
+ // Either arg2 & arg3 need swapping, or we're all done.
+ ASSERT((arg2 == GPRInfo::argumentGPR2 || arg3 == GPRInfo::argumentGPR3)
+ || (arg2 == GPRInfo::argumentGPR3 || arg3 == GPRInfo::argumentGPR2));
+
+ if (arg2 != GPRInfo::argumentGPR2)
+ swap(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3);
+ }
+
+#if CPU(X86_64)
+ ALWAYS_INLINE void setupArguments(FPRReg arg1)
+ {
+ moveDouble(arg1, FPRInfo::argumentFPR0);
+ }
+
+ ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
+ {
+ setupTwoStubArgs<FPRInfo::argumentFPR0, FPRInfo::argumentFPR1>(arg1, arg2);
+ }
+#else
+ ALWAYS_INLINE void setupArguments(FPRReg arg1)
+ {
+ assembler().vmov(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, arg1);
+ }
+
+ ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
+ {
+ assembler().vmov(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, arg1);
+ assembler().vmov(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, arg2);
+ }
+#endif
+
+ ALWAYS_INLINE void setupArguments(GPRReg arg1, GPRReg arg2)
+ {
+ setupTwoStubArgs<GPRInfo::argumentGPR0, GPRInfo::argumentGPR1>(arg1, arg2);
+ }
+
+ ALWAYS_INLINE void setupArgumentsExecState()
+ {
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1)
+ {
+ move(arg1, GPRInfo::argumentGPR1);
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1)
+ {
+ move(arg1, GPRInfo::argumentGPR1);
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2)
+ {
+ setupStubArguments(arg1, arg2);
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2)
+ {
+ move(arg1, GPRInfo::argumentGPR1);
+ move(arg2, GPRInfo::argumentGPR2);
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, GPRReg arg2)
+ {
+ move(arg2, GPRInfo::argumentGPR2); // Move this first, so setting arg1 does not trample!
+ move(arg1, GPRInfo::argumentGPR1);
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2)
+ {
+ move(arg1, GPRInfo::argumentGPR1);
+ move(arg2, GPRInfo::argumentGPR2);
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2)
+ {
+ move(arg1, GPRInfo::argumentGPR1);
+ move(arg2, GPRInfo::argumentGPR2);
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3)
+ {
+ setupStubArguments(arg1, arg2, arg3);
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3)
+ {
+ setupStubArguments(arg1, arg2);
+ move(arg3, GPRInfo::argumentGPR3);
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3)
+ {
+ move(arg1, GPRInfo::argumentGPR1);
+ move(arg2, GPRInfo::argumentGPR2);
+ move(arg3, GPRInfo::argumentGPR3);
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImmPtr arg3)
+ {
+ move(arg1, GPRInfo::argumentGPR1);
+ move(arg2, GPRInfo::argumentGPR2);
+ move(arg3, GPRInfo::argumentGPR3);
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3)
+ {
+ setupStubArguments(arg1, arg2);
+ move(arg3, GPRInfo::argumentGPR3);
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3)
+ {
+ move(arg1, GPRInfo::argumentGPR1);
+ move(arg2, GPRInfo::argumentGPR2);
+ move(arg3, GPRInfo::argumentGPR3);
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
+#endif // NUMBER_OF_ARGUMENT_REGISTERS >= 4
+ // These methods are suitable for any calling convention that provides for
+ // exactly 4 argument registers, e.g. ARMv7.
+#if NUMBER_OF_ARGUMENT_REGISTERS == 4
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4)
+ {
+ poke(arg4);
+ setupArgumentsWithExecState(arg1, arg2, arg3);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImm32 arg4)
+ {
+ poke(arg4);
+ setupArgumentsWithExecState(arg1, arg2, arg3);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3, GPRReg arg4)
+ {
+ poke(arg4);
+ setupArgumentsWithExecState(arg1, arg2, arg3);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
+ {
+ poke(arg4);
+ setupArgumentsWithExecState(arg1, arg2, arg3);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
+ {
+ poke(arg5, 1);
+ poke(arg4);
+ setupArgumentsWithExecState(arg1, arg2, arg3);
+ }
+#endif // NUMBER_OF_ARGUMENT_REGISTERS == 4
+
+ void setupResults(GPRReg destA, GPRReg destB)
+ {
+ GPRReg srcA = GPRInfo::returnValueGPR;
+ GPRReg srcB = GPRInfo::returnValueGPR2;
+
+ if (srcB != destA) {
+ // Handle the easy cases - two simple moves.
+ move(srcA, destA);
+ move(srcB, destB);
+ } else if (srcA != destB) {
+ // Handle the non-swap case - just put srcB in place first.
+ move(srcB, destB);
+ move(srcA, destA);
+ } else
+ swap(destA, destB);
+ }
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGCCallHelpers_h
+
diff --git a/Source/JavaScriptCore/dfg/DFGDriver.cpp b/Source/JavaScriptCore/dfg/DFGDriver.cpp
index 2143fbc19..27a0dab75 100644
--- a/Source/JavaScriptCore/dfg/DFGDriver.cpp
+++ b/Source/JavaScriptCore/dfg/DFGDriver.cpp
@@ -35,7 +35,7 @@
namespace JSC { namespace DFG {
enum CompileMode { CompileFunction, CompileOther };
-inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck)
+inline bool compile(CompileMode compileMode, JSGlobalData& globalData, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck)
{
SamplingRegion samplingRegion("DFG Compilation (Driver)");
@@ -47,17 +47,16 @@ inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
fprintf(stderr, "DFG compiling code block %p(%p), number of instructions = %u.\n", codeBlock, codeBlock->alternative(), codeBlock->instructionCount());
#endif
- JSGlobalData* globalData = &exec->globalData();
Graph dfg;
- if (!parse(dfg, globalData, codeBlock))
+ if (!parse(dfg, &globalData, codeBlock))
return false;
if (compileMode == CompileFunction)
dfg.predictArgumentTypes(codeBlock);
- propagate(dfg, globalData, codeBlock);
+ propagate(dfg, &globalData, codeBlock);
- JITCompiler dataFlowJIT(globalData, dfg, codeBlock);
+ JITCompiler dataFlowJIT(&globalData, dfg, codeBlock);
if (compileMode == CompileFunction) {
ASSERT(jitCodeWithArityCheck);
@@ -72,14 +71,14 @@ inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
return true;
}
-bool tryCompile(ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode)
+bool tryCompile(JSGlobalData& globalData, CodeBlock* codeBlock, JITCode& jitCode)
{
- return compile(CompileOther, exec, codeBlock, jitCode, 0);
+ return compile(CompileOther, globalData, codeBlock, jitCode, 0);
}
-bool tryCompileFunction(ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)
+bool tryCompileFunction(JSGlobalData& globalData, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)
{
- return compile(CompileFunction, exec, codeBlock, jitCode, &jitCodeWithArityCheck);
+ return compile(CompileFunction, globalData, codeBlock, jitCode, &jitCodeWithArityCheck);
}
} } // namespace JSC::DFG
diff --git a/Source/JavaScriptCore/dfg/DFGDriver.h b/Source/JavaScriptCore/dfg/DFGDriver.h
index dad45f32e..639b13f7a 100644
--- a/Source/JavaScriptCore/dfg/DFGDriver.h
+++ b/Source/JavaScriptCore/dfg/DFGDriver.h
@@ -30,19 +30,19 @@
namespace JSC {
-class ExecState;
class CodeBlock;
class JITCode;
+class JSGlobalData;
class MacroAssemblerCodePtr;
namespace DFG {
#if ENABLE(DFG_JIT)
-bool tryCompile(ExecState*, CodeBlock*, JITCode&);
-bool tryCompileFunction(ExecState*, CodeBlock*, JITCode&, MacroAssemblerCodePtr& jitCodeWithArityCheck);
+bool tryCompile(JSGlobalData&, CodeBlock*, JITCode&);
+bool tryCompileFunction(JSGlobalData&, CodeBlock*, JITCode&, MacroAssemblerCodePtr& jitCodeWithArityCheck);
#else
-inline bool tryCompile(ExecState*, CodeBlock*, JITCode&) { return false; }
-inline bool tryCompileFunction(ExecState*, CodeBlock*, JITCode&, MacroAssemblerCodePtr&) { return false; }
+inline bool tryCompile(JSGlobalData&, CodeBlock*, JITCode&) { return false; }
+inline bool tryCompileFunction(JSGlobalData&, CodeBlock*, JITCode&, MacroAssemblerCodePtr&) { return false; }
#endif
} } // namespace JSC::DFG
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.cpp b/Source/JavaScriptCore/dfg/DFGGraph.cpp
index 2a3e23040..e01bea195 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.cpp
+++ b/Source/JavaScriptCore/dfg/DFGGraph.cpp
@@ -261,10 +261,10 @@ void Graph::dump(NodeIndex nodeIndex, CodeBlock* codeBlock)
if (!skipped) {
if (node.hasVariableAccessData())
printf(" predicting %s, double ratio %lf%s", predictionToString(node.variableAccessData()->prediction()), node.variableAccessData()->doubleVoteRatio(), node.variableAccessData()->shouldUseDoubleFormat() ? ", forcing double" : "");
- else if (node.hasVarNumber())
- printf(" predicting %s", predictionToString(getGlobalVarPrediction(node.varNumber())));
else if (node.hasHeapPrediction())
printf(" predicting %s", predictionToString(node.getHeapPrediction()));
+ else if (node.hasVarNumber())
+ printf(" predicting %s", predictionToString(getGlobalVarPrediction(node.varNumber())));
}
printf("\n");
@@ -353,7 +353,7 @@ void Graph::predictArgumentTypes(CodeBlock* codeBlock)
at(m_arguments[arg]).variableAccessData()->predict(profile->computeUpdatedPrediction());
#if DFG_ENABLE(DEBUG_VERBOSE)
- printf("Argument [%lu] prediction: %s\n", arg, predictionToString(at(m_arguments[arg]).variableAccessData()->prediction()));
+ printf("Argument [%zu] prediction: %s\n", arg, predictionToString(at(m_arguments[arg]).variableAccessData()->prediction()));
#endif
}
}
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h
index fb729063d..d3f16a0f4 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.h
+++ b/Source/JavaScriptCore/dfg/DFGGraph.h
@@ -137,6 +137,26 @@ public:
return predictionFromValue(node.valueOfJSConstant(codeBlock));
}
+ bool addShouldSpeculateInteger(Node& add, CodeBlock* codeBlock)
+ {
+ ASSERT(add.op == ValueAdd || add.op == ArithAdd || add.op == ArithSub);
+
+ Node& left = at(add.child1());
+ Node& right = at(add.child2());
+
+ if (left.hasConstant())
+ return addImmediateShouldSpeculateInteger(codeBlock, add, right, left);
+ if (right.hasConstant())
+ return addImmediateShouldSpeculateInteger(codeBlock, add, left, right);
+
+ return Node::shouldSpeculateInteger(left, right) && add.canSpeculateInteger();
+ }
+
+ bool addShouldSpeculateInteger(NodeIndex nodeIndex, CodeBlock* codeBlock)
+ {
+ return addShouldSpeculateInteger(at(nodeIndex), codeBlock);
+ }
+
// Helper methods to check nodes for constants.
bool isConstant(NodeIndex nodeIndex)
{
@@ -223,8 +243,7 @@ public:
Node& node = at(nodeIndex);
- switch (node.op) {
- case GetLocal: {
+ if (node.op == GetLocal) {
if (!operandIsArgument(node.local()))
return 0;
int argument = operandToArgument(node.local());
@@ -233,21 +252,10 @@ public:
return profiledBlock->valueProfileForArgument(argument);
}
- // Nodes derives from calls need special handling because the value profile is
- // associated with the op_call_put_result instruction.
- case Call:
- case Construct:
- case ArrayPop:
- case ArrayPush: {
- ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
- return profiledBlock->valueProfileForBytecodeOffset(node.codeOrigin.bytecodeIndex + OPCODE_LENGTH(op_call));
- }
-
- default:
- if (node.hasHeapPrediction())
- return profiledBlock->valueProfileForBytecodeOffset(node.codeOrigin.bytecodeIndex);
- return 0;
- }
+ if (node.hasHeapPrediction())
+ return profiledBlock->valueProfileForBytecodeOffset(node.codeOrigin.bytecodeIndexForValueProfile());
+
+ return 0;
}
Vector< OwnPtr<BasicBlock> , 8> m_blocks;
@@ -263,6 +271,28 @@ public:
unsigned m_parameterSlots;
private:
+ bool addImmediateShouldSpeculateInteger(CodeBlock* codeBlock, Node& add, Node& variable, Node& immediate)
+ {
+ ASSERT(immediate.hasConstant());
+
+ JSValue immediateValue = immediate.valueOfJSConstant(codeBlock);
+ if (!immediateValue.isNumber())
+ return false;
+
+ if (!variable.shouldSpeculateInteger())
+ return false;
+
+ if (immediateValue.isInt32())
+ return add.canSpeculateInteger();
+
+ double doubleImmediate = immediateValue.asDouble();
+ const double twoToThe48 = 281474976710656.0;
+ if (doubleImmediate < -twoToThe48 || doubleImmediate > twoToThe48)
+ return false;
+
+ return nodeCanTruncateInteger(add.arithNodeFlags());
+ }
+
// When a node's refCount goes from 0 to 1, it must (logically) recursively ref all of its children, and vice versa.
void refChildren(NodeIndex);
void derefChildren(NodeIndex);
diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
index 593e4d930..ac5f314a1 100644
--- a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
+++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
@@ -116,7 +116,7 @@ void JITCompiler::link(LinkBuffer& linkBuffer)
{
// Link the code, populate data in CodeBlock data structures.
#if DFG_ENABLE(DEBUG_VERBOSE)
- fprintf(stderr, "JIT code for %p start at [%p, %p). Size = %lu.\n", m_codeBlock, linkBuffer.debugAddress(), static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize(), linkBuffer.debugSize());
+ fprintf(stderr, "JIT code for %p start at [%p, %p). Size = %zu.\n", m_codeBlock, linkBuffer.debugAddress(), static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize(), linkBuffer.debugSize());
#endif
// Link all calls out from the JIT code to their respective functions.
@@ -151,6 +151,7 @@ void JITCompiler::link(LinkBuffer& linkBuffer)
unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_exceptionChecks[i].m_call);
codeOrigins[j].codeOrigin = record.m_codeOrigin;
codeOrigins[j].callReturnOffset = returnAddressOffset;
+ record.m_token.assertCodeOriginIndex(j);
j++;
}
}
@@ -160,6 +161,7 @@ void JITCompiler::link(LinkBuffer& linkBuffer)
for (unsigned i = 0; i < m_propertyAccesses.size(); ++i) {
StructureStubInfo& info = m_codeBlock->structureStubInfo(i);
CodeLocationCall callReturnLocation = linkBuffer.locationOf(m_propertyAccesses[i].m_functionCall);
+ info.codeOrigin = m_propertyAccesses[i].m_codeOrigin;
info.callReturnLocation = callReturnLocation;
info.deltaCheckImmToCall = differenceBetweenCodePtr(linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCheckImmToCall), callReturnLocation);
info.deltaCallToStructCheck = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToStructCheck));
@@ -179,6 +181,7 @@ void JITCompiler::link(LinkBuffer& linkBuffer)
info.valueGPR = m_propertyAccesses[i].m_valueGPR;
#endif
info.scratchGPR = m_propertyAccesses[i].m_scratchGPR;
+ info.registersFlushed = m_propertyAccesses[i].m_registerMode == PropertyAccessRecord::RegistersFlushed;
}
m_codeBlock->setNumberOfCallLinkInfos(m_jsCalls.size());
@@ -209,7 +212,7 @@ void JITCompiler::compile(JITCode& entry)
SpeculativeJIT speculative(*this);
compileBody(speculative);
- LinkBuffer linkBuffer(*m_globalData, this);
+ LinkBuffer linkBuffer(*m_globalData, this, m_codeBlock);
link(linkBuffer);
speculative.linkOSREntries(linkBuffer);
@@ -269,7 +272,7 @@ void JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWi
// === Link ===
- LinkBuffer linkBuffer(*m_globalData, this);
+ LinkBuffer linkBuffer(*m_globalData, this, m_codeBlock);
link(linkBuffer);
speculative.linkOSREntries(linkBuffer);
diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.h b/Source/JavaScriptCore/dfg/DFGJITCompiler.h
index de0475a56..451bee6ca 100644
--- a/Source/JavaScriptCore/dfg/DFGJITCompiler.h
+++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.h
@@ -31,7 +31,7 @@
#include <assembler/LinkBuffer.h>
#include <assembler/MacroAssembler.h>
#include <bytecode/CodeBlock.h>
-#include <dfg/DFGAssemblyHelpers.h>
+#include <dfg/DFGCCallHelpers.h>
#include <dfg/DFGFPRInfo.h>
#include <dfg/DFGGPRInfo.h>
#include <dfg/DFGGraph.h>
@@ -70,37 +70,76 @@ struct CallLinkRecord {
FunctionPtr m_function;
};
+class CallBeginToken {
+public:
+ CallBeginToken()
+#if !ASSERT_DISABLED
+ : m_codeOriginIndex(UINT_MAX)
+#endif
+ {
+ }
+
+ explicit CallBeginToken(unsigned codeOriginIndex)
+#if !ASSERT_DISABLED
+ : m_codeOriginIndex(codeOriginIndex)
+#endif
+ {
+ UNUSED_PARAM(codeOriginIndex);
+ }
+
+ void assertCodeOriginIndex(unsigned codeOriginIndex) const
+ {
+ ASSERT_UNUSED(codeOriginIndex, codeOriginIndex < UINT_MAX);
+ ASSERT_UNUSED(codeOriginIndex, codeOriginIndex == m_codeOriginIndex);
+ }
+
+ void assertNoCodeOriginIndex() const
+ {
+ ASSERT(m_codeOriginIndex == UINT_MAX);
+ }
+private:
+#if !ASSERT_DISABLED
+ unsigned m_codeOriginIndex;
+#endif
+};
+
// === CallExceptionRecord ===
//
// A record of a call out from JIT code that might throw an exception.
// Calls that might throw an exception also record the Jump taken on exception
// (unset if not present) and code origin used to recover handler/source info.
struct CallExceptionRecord {
- CallExceptionRecord(MacroAssembler::Call call, CodeOrigin codeOrigin)
+ CallExceptionRecord(MacroAssembler::Call call, CodeOrigin codeOrigin, CallBeginToken token)
: m_call(call)
, m_codeOrigin(codeOrigin)
+ , m_token(token)
{
}
- CallExceptionRecord(MacroAssembler::Call call, MacroAssembler::Jump exceptionCheck, CodeOrigin codeOrigin)
+ CallExceptionRecord(MacroAssembler::Call call, MacroAssembler::Jump exceptionCheck, CodeOrigin codeOrigin, CallBeginToken token)
: m_call(call)
, m_exceptionCheck(exceptionCheck)
, m_codeOrigin(codeOrigin)
+ , m_token(token)
{
}
MacroAssembler::Call m_call;
MacroAssembler::Jump m_exceptionCheck;
CodeOrigin m_codeOrigin;
+ CallBeginToken m_token;
};
struct PropertyAccessRecord {
+ enum RegisterMode { RegistersFlushed, RegistersInUse };
+
#if USE(JSVALUE64)
- PropertyAccessRecord(MacroAssembler::DataLabelPtr deltaCheckImmToCall, MacroAssembler::Call functionCall, MacroAssembler::Jump deltaCallToStructCheck, MacroAssembler::DataLabelCompact deltaCallToLoadOrStore, MacroAssembler::Label deltaCallToSlowCase, MacroAssembler::Label deltaCallToDone, int8_t baseGPR, int8_t valueGPR, int8_t scratchGPR)
+ PropertyAccessRecord(CodeOrigin codeOrigin, MacroAssembler::DataLabelPtr deltaCheckImmToCall, MacroAssembler::Call functionCall, MacroAssembler::Jump deltaCallToStructCheck, MacroAssembler::DataLabelCompact deltaCallToLoadOrStore, MacroAssembler::Label deltaCallToSlowCase, MacroAssembler::Label deltaCallToDone, int8_t baseGPR, int8_t valueGPR, int8_t scratchGPR, RegisterMode registerMode = RegistersInUse)
#elif USE(JSVALUE32_64)
- PropertyAccessRecord(MacroAssembler::DataLabelPtr deltaCheckImmToCall, MacroAssembler::Call functionCall, MacroAssembler::Jump deltaCallToStructCheck, MacroAssembler::DataLabelCompact deltaCallToTagLoadOrStore, MacroAssembler::DataLabelCompact deltaCallToPayloadLoadOrStore, MacroAssembler::Label deltaCallToSlowCase, MacroAssembler::Label deltaCallToDone, int8_t baseGPR, int8_t valueTagGPR, int8_t valueGPR, int8_t scratchGPR)
+ PropertyAccessRecord(CodeOrigin codeOrigin, MacroAssembler::DataLabelPtr deltaCheckImmToCall, MacroAssembler::Call functionCall, MacroAssembler::Jump deltaCallToStructCheck, MacroAssembler::DataLabelCompact deltaCallToTagLoadOrStore, MacroAssembler::DataLabelCompact deltaCallToPayloadLoadOrStore, MacroAssembler::Label deltaCallToSlowCase, MacroAssembler::Label deltaCallToDone, int8_t baseGPR, int8_t valueTagGPR, int8_t valueGPR, int8_t scratchGPR, RegisterMode registerMode = RegistersInUse)
#endif
- : m_deltaCheckImmToCall(deltaCheckImmToCall)
+ : m_codeOrigin(codeOrigin)
+ , m_deltaCheckImmToCall(deltaCheckImmToCall)
, m_functionCall(functionCall)
, m_deltaCallToStructCheck(deltaCallToStructCheck)
#if USE(JSVALUE64)
@@ -117,9 +156,11 @@ struct PropertyAccessRecord {
#endif
, m_valueGPR(valueGPR)
, m_scratchGPR(scratchGPR)
+ , m_registerMode(registerMode)
{
}
+ CodeOrigin m_codeOrigin;
MacroAssembler::DataLabelPtr m_deltaCheckImmToCall;
MacroAssembler::Call m_functionCall;
MacroAssembler::Jump m_deltaCallToStructCheck;
@@ -137,6 +178,7 @@ struct PropertyAccessRecord {
#endif
int8_t m_valueGPR;
int8_t m_scratchGPR;
+ RegisterMode m_registerMode;
};
// === JITCompiler ===
@@ -147,11 +189,12 @@ struct PropertyAccessRecord {
// relationship). The JITCompiler holds references to information required during
// compilation, and also records information used in linking (e.g. a list of all
// call to be linked).
-class JITCompiler : public AssemblyHelpers {
+class JITCompiler : public CCallHelpers {
public:
JITCompiler(JSGlobalData* globalData, Graph& dfg, CodeBlock* codeBlock)
- : AssemblyHelpers(globalData, codeBlock)
+ : CCallHelpers(globalData, codeBlock)
, m_graph(dfg)
+ , m_currentCodeOriginIndex(0)
{
}
@@ -160,11 +203,32 @@ public:
// Accessors for properties.
Graph& graph() { return m_graph; }
+
+ // Just get a token for beginning a call.
+ CallBeginToken nextCallBeginToken(CodeOrigin codeOrigin)
+ {
+ if (!codeOrigin.inlineCallFrame)
+ return CallBeginToken();
+ return CallBeginToken(m_currentCodeOriginIndex++);
+ }
+
+ // Get a token for beginning a call, and set the current code origin index in
+ // the call frame.
+ CallBeginToken beginCall(CodeOrigin codeOrigin)
+ {
+ unsigned codeOriginIndex;
+ if (!codeOrigin.inlineCallFrame)
+ codeOriginIndex = UINT_MAX;
+ else
+ codeOriginIndex = m_currentCodeOriginIndex++;
+ store32(TrustedImm32(codeOriginIndex), tagFor(static_cast<VirtualRegister>(RegisterFile::ArgumentCount)));
+ return CallBeginToken(codeOriginIndex);
+ }
// Notify the JIT of a call that does not require linking.
- void notifyCall(Call functionCall, CodeOrigin codeOrigin)
+ void notifyCall(Call functionCall, CodeOrigin codeOrigin, CallBeginToken token)
{
- m_exceptionChecks.append(CallExceptionRecord(functionCall, codeOrigin));
+ m_exceptionChecks.append(CallExceptionRecord(functionCall, codeOrigin, token));
}
// Add a call out from JIT code, without an exception check.
@@ -176,25 +240,18 @@ public:
}
// Add a call out from JIT code, with an exception check.
- Call addExceptionCheck(Call functionCall, CodeOrigin codeOrigin)
+ void addExceptionCheck(Call functionCall, CodeOrigin codeOrigin, CallBeginToken token)
{
move(TrustedImm32(m_exceptionChecks.size()), GPRInfo::nonPreservedNonReturnGPR);
-#if USE(JSVALUE64)
- Jump exceptionCheck = branchTestPtr(NonZero, AbsoluteAddress(&globalData()->exception));
-#elif USE(JSVALUE32_64)
- Jump exceptionCheck = branch32(NotEqual, AbsoluteAddress(reinterpret_cast<char*>(&globalData()->exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
-#endif
- m_exceptionChecks.append(CallExceptionRecord(functionCall, exceptionCheck, codeOrigin));
- return functionCall;
+ m_exceptionChecks.append(CallExceptionRecord(functionCall, emitExceptionCheck(), codeOrigin, token));
}
// Add a call out from JIT code, with a fast exception check that tests if the return value is zero.
- Call addFastExceptionCheck(Call functionCall, CodeOrigin codeOrigin)
+ void addFastExceptionCheck(Call functionCall, CodeOrigin codeOrigin, CallBeginToken token)
{
move(TrustedImm32(m_exceptionChecks.size()), GPRInfo::nonPreservedNonReturnGPR);
Jump exceptionCheck = branchTestPtr(Zero, GPRInfo::returnValueGPR);
- m_exceptionChecks.append(CallExceptionRecord(functionCall, exceptionCheck, codeOrigin));
- return functionCall;
+ m_exceptionChecks.append(CallExceptionRecord(functionCall, exceptionCheck, codeOrigin, token));
}
// Helper methods to check nodes for constants.
@@ -325,6 +382,7 @@ private:
Vector<PropertyAccessRecord, 4> m_propertyAccesses;
Vector<JSCallRecord, 4> m_jsCalls;
+ unsigned m_currentCodeOriginIndex;
};
} } // namespace JSC::DFG
diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h
index cb5be691c..7366c1c40 100644
--- a/Source/JavaScriptCore/dfg/DFGNode.h
+++ b/Source/JavaScriptCore/dfg/DFGNode.h
@@ -229,6 +229,7 @@ static inline const char* arithNodeFlagsAsString(ArithNodeFlags flags)
macro(PutByVal, NodeMustGenerate | NodeClobbersWorld) \
macro(PutByValAlias, NodeMustGenerate | NodeClobbersWorld) \
macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
+ macro(GetByIdFlush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
macro(CheckStructure, NodeMustGenerate) \
@@ -244,6 +245,7 @@ static inline const char* arithNodeFlagsAsString(ArithNodeFlags flags)
macro(GetInt16ArrayLength, NodeResultInt32) \
macro(GetInt32ArrayLength, NodeResultInt32) \
macro(GetUint8ArrayLength, NodeResultInt32) \
+ macro(GetUint8ClampedArrayLength, NodeResultInt32) \
macro(GetUint16ArrayLength, NodeResultInt32) \
macro(GetUint32ArrayLength, NodeResultInt32) \
macro(GetFloat32ArrayLength, NodeResultInt32) \
@@ -502,6 +504,7 @@ struct Node {
{
switch (op) {
case GetById:
+ case GetByIdFlush:
case PutById:
case PutByIdDirect:
case Resolve:
@@ -718,6 +721,7 @@ struct Node {
{
switch (op) {
case GetById:
+ case GetByIdFlush:
case GetByVal:
case Call:
case Construct:
@@ -960,6 +964,11 @@ struct Node {
{
return isUint8ArrayPrediction(prediction());
}
+
+ bool shouldSpeculateUint8ClampedArray()
+ {
+ return isUint8ClampedArrayPrediction(prediction());
+ }
bool shouldSpeculateUint16Array()
{
diff --git a/Source/JavaScriptCore/dfg/DFGOSREntry.cpp b/Source/JavaScriptCore/dfg/DFGOSREntry.cpp
index 4510ec7b9..cbcd1319a 100644
--- a/Source/JavaScriptCore/dfg/DFGOSREntry.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSREntry.cpp
@@ -80,7 +80,7 @@ void* prepareOSREntry(ExecState* exec, CodeBlock* codeBlock, unsigned bytecodeIn
for (size_t argument = 0; argument < entry->m_expectedValues.numberOfArguments(); ++argument) {
if (argument >= exec->argumentCountIncludingThis()) {
#if ENABLE(JIT_VERBOSE_OSR)
- printf(" OSR failed because argument %lu was not passed, expected ", argument);
+ printf(" OSR failed because argument %zu was not passed, expected ", argument);
entry->m_expectedValues.argument(argument).dump(stdout);
printf(".\n");
#endif
@@ -95,7 +95,7 @@ void* prepareOSREntry(ExecState* exec, CodeBlock* codeBlock, unsigned bytecodeIn
if (!entry->m_expectedValues.argument(argument).validate(value)) {
#if ENABLE(JIT_VERBOSE_OSR)
- printf(" OSR failed because argument %lu is %s, expected ", argument, value.description());
+ printf(" OSR failed because argument %zu is %s, expected ", argument, value.description());
entry->m_expectedValues.argument(argument).dump(stdout);
printf(".\n");
#endif
@@ -107,7 +107,7 @@ void* prepareOSREntry(ExecState* exec, CodeBlock* codeBlock, unsigned bytecodeIn
if (entry->m_localsForcedDouble.get(local)) {
if (!exec->registers()[local].jsValue().isNumber()) {
#if ENABLE(JIT_VERBOSE_OSR)
- printf(" OSR failed because variable %lu is %s, expected number.\n", local, exec->registers()[local].jsValue().description());
+ printf(" OSR failed because variable %zu is %s, expected number.\n", local, exec->registers()[local].jsValue().description());
#endif
return 0;
}
@@ -115,7 +115,7 @@ void* prepareOSREntry(ExecState* exec, CodeBlock* codeBlock, unsigned bytecodeIn
}
if (!entry->m_expectedValues.local(local).validate(exec->registers()[local].jsValue())) {
#if ENABLE(JIT_VERBOSE_OSR)
- printf(" OSR failed because variable %lu is %s, expected ", local, exec->registers()[local].jsValue().description());
+ printf(" OSR failed because variable %zu is %s, expected ", local, exec->registers()[local].jsValue().description());
entry->m_expectedValues.local(local).dump(stdout);
printf(".\n");
#endif
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
index 3da8189d1..1b88c4ffc 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
@@ -62,7 +62,7 @@ void compileOSRExit(ExecState* exec)
exitCompiler.compileExit(exit, recovery);
- LinkBuffer patchBuffer(*globalData, &jit);
+ LinkBuffer patchBuffer(*globalData, &jit, codeBlock);
exit.m_code = patchBuffer.finalizeCode();
#if DFG_ENABLE(DEBUG_VERBOSE)
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
index 3d27e00e4..4e33d7b02 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
@@ -579,13 +579,13 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco
AssemblyHelpers::Jump lowFailRate = m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, GPRInfo::regT1);
// Reoptimize as soon as possible.
- m_jit.store32(AssemblyHelpers::Imm32(Options::executionCounterValueForOptimizeNextInvocation), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfExecuteCounter()));
+ m_jit.store32(AssemblyHelpers::Imm32(Options::executionCounterValueForOptimizeNextInvocation), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter()));
AssemblyHelpers::Jump doneAdjusting = m_jit.jump();
fewFails.link(&m_jit);
lowFailRate.link(&m_jit);
- m_jit.store32(AssemblyHelpers::Imm32(m_jit.baselineCodeBlock()->counterValueForOptimizeAfterLongWarmUp()), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfExecuteCounter()));
+ m_jit.store32(AssemblyHelpers::Imm32(m_jit.baselineCodeBlock()->counterValueForOptimizeAfterLongWarmUp()), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter()));
doneAdjusting.link(&m_jit);
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
index c6f4a9ed4..98c891ac7 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
@@ -554,13 +554,13 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco
AssemblyHelpers::Jump lowFailRate = m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, GPRInfo::regT1);
// Reoptimize as soon as possible.
- m_jit.store32(AssemblyHelpers::Imm32(Options::executionCounterValueForOptimizeNextInvocation), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfExecuteCounter()));
+ m_jit.store32(AssemblyHelpers::Imm32(Options::executionCounterValueForOptimizeNextInvocation), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter()));
AssemblyHelpers::Jump doneAdjusting = m_jit.jump();
fewFails.link(&m_jit);
lowFailRate.link(&m_jit);
- m_jit.store32(AssemblyHelpers::Imm32(m_jit.baselineCodeBlock()->counterValueForOptimizeAfterLongWarmUp()), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfExecuteCounter()));
+ m_jit.store32(AssemblyHelpers::Imm32(m_jit.baselineCodeBlock()->counterValueForOptimizeAfterLongWarmUp()), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter()));
doneAdjusting.link(&m_jit);
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp
index 2e6fd9276..569b4fe86 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp
@@ -31,6 +31,7 @@
#include "CodeBlock.h"
#include "DFGOSRExit.h"
#include "DFGRepatch.h"
+#include "GetterSetter.h"
#include "InlineASM.h"
#include "Interpreter.h"
#include "JSByteArray.h"
@@ -42,6 +43,7 @@
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, register) \
asm( \
".globl " SYMBOL_STRING(function) "\n" \
+ HIDE_SYMBOL(function) "\n" \
SYMBOL_STRING(function) ":" "\n" \
"mov (%rsp), %" STRINGIZE(register) "\n" \
"jmp " SYMBOL_STRING_RELOCATION(function##WithReturnAddress) "\n" \
@@ -56,6 +58,7 @@
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, offset) \
asm( \
".globl " SYMBOL_STRING(function) "\n" \
+ HIDE_SYMBOL(function) "\n" \
SYMBOL_STRING(function) ":" "\n" \
"mov (%esp), %eax\n" \
"mov %eax, " STRINGIZE(offset) "(%esp)\n" \
@@ -175,6 +178,9 @@ static inline void putByVal(ExecState* exec, JSValue baseValue, uint32_t index,
template<bool strict>
ALWAYS_INLINE static void DFG_OPERATION operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSValue baseValue = JSValue::decode(encodedBase);
JSValue property = JSValue::decode(encodedProperty);
JSValue value = JSValue::decode(encodedValue);
@@ -193,10 +199,9 @@ ALWAYS_INLINE static void DFG_OPERATION operationPutByValInternal(ExecState* exe
}
}
- JSGlobalData* globalData = &exec->globalData();
// Don't put to an object if toString throws an exception.
- Identifier ident(exec, property.toString(exec));
+ Identifier ident(exec, property.toString(exec)->value(exec));
if (!globalData->exception) {
PutPropertySlot slot(strict);
baseValue.put(exec, ident, value, slot);
@@ -207,6 +212,9 @@ extern "C" {
EncodedJSValue DFG_OPERATION operationConvertThis(ExecState* exec, EncodedJSValue encodedOp)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
return JSValue::encode(JSValue::decode(encodedOp).toThisObject(exec));
}
@@ -230,21 +238,33 @@ inline JSCell* createThis(ExecState* exec, JSCell* prototype, JSFunction* constr
JSCell* DFG_OPERATION operationCreateThis(ExecState* exec, JSCell* prototype)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
return createThis(exec, prototype, asFunction(exec->callee()));
}
JSCell* DFG_OPERATION operationCreateThisInlined(ExecState* exec, JSCell* prototype, JSCell* constructor)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
return createThis(exec, prototype, static_cast<JSFunction*>(constructor));
}
JSCell* DFG_OPERATION operationNewObject(ExecState* exec)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
return constructEmptyObject(exec);
}
EncodedJSValue DFG_OPERATION operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSValue op1 = JSValue::decode(encodedOp1);
JSValue op2 = JSValue::decode(encodedOp2);
@@ -253,16 +273,16 @@ EncodedJSValue DFG_OPERATION operationValueAdd(ExecState* exec, EncodedJSValue e
EncodedJSValue DFG_OPERATION operationValueAddNotNumber(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSValue op1 = JSValue::decode(encodedOp1);
JSValue op2 = JSValue::decode(encodedOp2);
ASSERT(!op1.isNumber() || !op2.isNumber());
- if (op1.isString()) {
- if (op2.isString())
- return JSValue::encode(jsString(exec, asString(op1), asString(op2)));
- return JSValue::encode(jsString(exec, asString(op1), op2.toPrimitiveString(exec)));
- }
+ if (op1.isString() && !op2.isObject())
+ return JSValue::encode(jsString(exec, asString(op1), op2.toString(exec)));
return JSValue::encode(jsAddSlowCase(exec, op1, op2));
}
@@ -286,6 +306,9 @@ static inline EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t in
EncodedJSValue DFG_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSValue baseValue = JSValue::decode(encodedBase);
JSValue property = JSValue::decode(encodedProperty);
@@ -305,12 +328,15 @@ EncodedJSValue DFG_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue e
}
}
- Identifier ident(exec, property.toString(exec));
+ Identifier ident(exec, property.toString(exec)->value(exec));
return JSValue::encode(baseValue.get(exec, ident));
}
EncodedJSValue DFG_OPERATION operationGetByValCell(ExecState* exec, JSCell* base, EncodedJSValue encodedProperty)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSValue property = JSValue::decode(encodedProperty);
if (property.isUInt32())
@@ -325,12 +351,15 @@ EncodedJSValue DFG_OPERATION operationGetByValCell(ExecState* exec, JSCell* base
return JSValue::encode(result);
}
- Identifier ident(exec, property.toString(exec));
+ Identifier ident(exec, property.toString(exec)->value(exec));
return JSValue::encode(JSValue(base).get(exec, ident));
}
EncodedJSValue DFG_OPERATION operationGetById(ExecState* exec, EncodedJSValue base, Identifier* propertyName)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSValue baseValue = JSValue::decode(base);
PropertySlot slot(baseValue);
return JSValue::encode(baseValue.get(exec, *propertyName, slot));
@@ -339,6 +368,9 @@ EncodedJSValue DFG_OPERATION operationGetById(ExecState* exec, EncodedJSValue ba
J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(operationGetByIdBuildList);
EncodedJSValue DFG_OPERATION operationGetByIdBuildListWithReturnAddress(ExecState* exec, EncodedJSValue base, Identifier* propertyName, ReturnAddressPtr returnAddress)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSValue baseValue = JSValue::decode(base);
PropertySlot slot(baseValue);
JSValue result = baseValue.get(exec, *propertyName, slot);
@@ -352,6 +384,9 @@ EncodedJSValue DFG_OPERATION operationGetByIdBuildListWithReturnAddress(ExecStat
J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(operationGetByIdProtoBuildList);
EncodedJSValue DFG_OPERATION operationGetByIdProtoBuildListWithReturnAddress(ExecState* exec, EncodedJSValue base, Identifier* propertyName, ReturnAddressPtr returnAddress)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSValue baseValue = JSValue::decode(base);
PropertySlot slot(baseValue);
JSValue result = baseValue.get(exec, *propertyName, slot);
@@ -365,6 +400,9 @@ EncodedJSValue DFG_OPERATION operationGetByIdProtoBuildListWithReturnAddress(Exe
J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(operationGetByIdOptimize);
EncodedJSValue DFG_OPERATION operationGetByIdOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue base, Identifier* propertyName, ReturnAddressPtr returnAddress)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSValue baseValue = JSValue::decode(base);
PropertySlot slot(baseValue);
JSValue result = baseValue.get(exec, *propertyName, slot);
@@ -378,28 +416,65 @@ EncodedJSValue DFG_OPERATION operationGetByIdOptimizeWithReturnAddress(ExecState
return JSValue::encode(result);
}
+EncodedJSValue DFG_OPERATION operationCallCustomGetter(ExecState* exec, JSCell* base, PropertySlot::GetValueFunc function, Identifier* ident)
+{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
+ return JSValue::encode(function(exec, asObject(base), *ident));
+}
+
+EncodedJSValue DFG_OPERATION operationCallGetter(ExecState* exec, JSCell* base, JSCell* value)
+{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
+ GetterSetter* getterSetter = asGetterSetter(value);
+ JSObject* getter = getterSetter->getter();
+ if (!getter)
+ return JSValue::encode(jsUndefined());
+ CallData callData;
+ CallType callType = getter->methodTable()->getCallData(getter, callData);
+ return JSValue::encode(call(exec, getter, callType, callData, asObject(base), ArgList()));
+}
+
void DFG_OPERATION operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
operationPutByValInternal<true>(exec, encodedBase, encodedProperty, encodedValue);
}
void DFG_OPERATION operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
operationPutByValInternal<false>(exec, encodedBase, encodedProperty, encodedValue);
}
void DFG_OPERATION operationPutByValCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
operationPutByValInternal<true>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
}
void DFG_OPERATION operationPutByValCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
operationPutByValInternal<false>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
}
void DFG_OPERATION operationPutByValBeyondArrayBounds(ExecState* exec, JSArray* array, int32_t index, EncodedJSValue encodedValue)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
// We should only get here if index is outside the existing vector.
ASSERT(!array->canSetIndex(index));
JSArray::putByIndex(array, exec, index, JSValue::decode(encodedValue));
@@ -407,42 +482,65 @@ void DFG_OPERATION operationPutByValBeyondArrayBounds(ExecState* exec, JSArray*
EncodedJSValue DFG_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue encodedValue, JSArray* array)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
array->push(exec, JSValue::decode(encodedValue));
return JSValue::encode(jsNumber(array->length()));
}
EncodedJSValue DFG_OPERATION operationArrayPop(ExecState* exec, JSArray* array)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
return JSValue::encode(array->pop(exec));
}
void DFG_OPERATION operationPutByIdStrict(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
PutPropertySlot slot(true);
base->methodTable()->put(base, exec, *propertyName, JSValue::decode(encodedValue), slot);
}
void DFG_OPERATION operationPutByIdNonStrict(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
PutPropertySlot slot(false);
base->methodTable()->put(base, exec, *propertyName, JSValue::decode(encodedValue), slot);
}
void DFG_OPERATION operationPutByIdDirectStrict(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
PutPropertySlot slot(true);
- JSValue(base).putDirect(exec, *propertyName, JSValue::decode(encodedValue), slot);
+ ASSERT(base->isObject());
+ asObject(base)->putDirect(exec->globalData(), *propertyName, JSValue::decode(encodedValue), slot);
}
void DFG_OPERATION operationPutByIdDirectNonStrict(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
PutPropertySlot slot(false);
- JSValue(base).putDirect(exec, *propertyName, JSValue::decode(encodedValue), slot);
+ ASSERT(base->isObject());
+ asObject(base)->putDirect(exec->globalData(), *propertyName, JSValue::decode(encodedValue), slot);
}
V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdStrictOptimize);
void DFG_OPERATION operationPutByIdStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSValue value = JSValue::decode(encodedValue);
JSValue baseValue(base);
PutPropertySlot slot(true);
@@ -459,6 +557,9 @@ void DFG_OPERATION operationPutByIdStrictOptimizeWithReturnAddress(ExecState* ex
V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdNonStrictOptimize);
void DFG_OPERATION operationPutByIdNonStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSValue value = JSValue::decode(encodedValue);
JSValue baseValue(base);
PutPropertySlot slot(false);
@@ -475,15 +576,18 @@ void DFG_OPERATION operationPutByIdNonStrictOptimizeWithReturnAddress(ExecState*
V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdDirectStrictOptimize);
void DFG_OPERATION operationPutByIdDirectStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSValue value = JSValue::decode(encodedValue);
- JSValue baseValue(base);
PutPropertySlot slot(true);
- baseValue.putDirect(exec, *propertyName, value, slot);
+ ASSERT(base->isObject());
+ asObject(base)->putDirect(exec->globalData(), *propertyName, value, slot);
StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
if (stubInfo.seen)
- dfgRepatchPutByID(exec, baseValue, *propertyName, slot, stubInfo, Direct);
+ dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, Direct);
else
stubInfo.seen = true;
}
@@ -491,46 +595,67 @@ void DFG_OPERATION operationPutByIdDirectStrictOptimizeWithReturnAddress(ExecSta
V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdDirectNonStrictOptimize);
void DFG_OPERATION operationPutByIdDirectNonStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSValue value = JSValue::decode(encodedValue);
- JSValue baseValue(base);
PutPropertySlot slot(false);
- baseValue.putDirect(exec, *propertyName, value, slot);
+ ASSERT(base->isObject());
+ asObject(base)->putDirect(exec->globalData(), *propertyName, value, slot);
StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
if (stubInfo.seen)
- dfgRepatchPutByID(exec, baseValue, *propertyName, slot, stubInfo, Direct);
+ dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, Direct);
else
stubInfo.seen = true;
}
size_t DFG_OPERATION operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
return jsLess<true>(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
}
size_t DFG_OPERATION operationCompareLessEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
return jsLessEq<true>(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
}
size_t DFG_OPERATION operationCompareGreater(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
return jsLess<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
}
size_t DFG_OPERATION operationCompareGreaterEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
return jsLessEq<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
}
size_t DFG_OPERATION operationCompareEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
return JSValue::equalSlowCaseInline(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
}
size_t DFG_OPERATION operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSValue op1 = JSValue::decode(encodedOp1);
JSValue op2 = JSValue::decode(encodedOp2);
@@ -542,6 +667,9 @@ size_t DFG_OPERATION operationCompareStrictEqCell(ExecState* exec, EncodedJSValu
size_t DFG_OPERATION operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
return JSValue::strictEqual(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
}
@@ -551,6 +679,7 @@ EncodedJSValue DFG_OPERATION getHostCallReturnValueWithExecState(ExecState*);
#if CPU(X86_64)
asm (
".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
+HIDE_SYMBOL(getHostCallReturnValue) "\n"
SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
"mov -40(%r13), %r13\n"
"mov %r13, %rdi\n"
@@ -559,6 +688,7 @@ SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
#elif CPU(X86)
asm (
".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
+HIDE_SYMBOL(getHostCallReturnValue) "\n"
SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
"mov -40(%edi), %edi\n"
"mov %edi, 4(%esp)\n"
@@ -581,6 +711,9 @@ SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
EncodedJSValue DFG_OPERATION getHostCallReturnValueWithExecState(ExecState* exec)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
return JSValue::encode(exec->globalData().hostCallReturnValue);
}
@@ -635,6 +768,8 @@ inline void* linkFor(ExecState* execCallee, ReturnAddressPtr returnAddress, Code
{
ExecState* exec = execCallee->callerFrame();
JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSValue calleeAsValue = execCallee->calleeAsValue();
JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
if (!calleeAsFunctionCell)
@@ -684,6 +819,9 @@ void* DFG_OPERATION operationLinkConstructWithReturnAddress(ExecState* execCalle
inline void* virtualFor(ExecState* execCallee, CodeSpecializationKind kind)
{
ExecState* exec = execCallee->callerFrame();
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSValue calleeAsValue = execCallee->calleeAsValue();
JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
if (UNLIKELY(!calleeAsFunctionCell))
@@ -704,7 +842,7 @@ inline void* virtualFor(ExecState* execCallee, CodeSpecializationKind kind)
}
void* DFG_OPERATION operationVirtualCall(ExecState* execCallee)
-{
+{
return virtualFor(execCallee, CodeForCall);
}
@@ -715,6 +853,9 @@ void* DFG_OPERATION operationVirtualConstruct(ExecState* execCallee)
EncodedJSValue DFG_OPERATION operationResolve(ExecState* exec, Identifier* propertyName)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
ScopeChainNode* scopeChain = exec->scopeChain();
ScopeChainIterator iter = scopeChain->begin();
ScopeChainIterator end = scopeChain->end();
@@ -732,11 +873,17 @@ EncodedJSValue DFG_OPERATION operationResolve(ExecState* exec, Identifier* prope
EncodedJSValue DFG_OPERATION operationResolveBase(ExecState* exec, Identifier* propertyName)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
return JSValue::encode(resolveBase(exec, *propertyName, exec->scopeChain(), false));
}
EncodedJSValue DFG_OPERATION operationResolveBaseStrictPut(ExecState* exec, Identifier* propertyName)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSValue base = resolveBase(exec, *propertyName, exec->scopeChain(), true);
if (!base)
throwError(exec, createErrorForInvalidGlobalAssignment(exec, propertyName->ustring()));
@@ -745,6 +892,9 @@ EncodedJSValue DFG_OPERATION operationResolveBaseStrictPut(ExecState* exec, Iden
EncodedJSValue DFG_OPERATION operationResolveGlobal(ExecState* exec, GlobalResolveInfo* resolveInfo, Identifier* propertyName)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSGlobalObject* globalObject = exec->lexicalGlobalObject();
PropertySlot slot(globalObject);
@@ -764,16 +914,25 @@ EncodedJSValue DFG_OPERATION operationResolveGlobal(ExecState* exec, GlobalResol
EncodedJSValue DFG_OPERATION operationToPrimitive(ExecState* exec, EncodedJSValue value)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
return JSValue::encode(JSValue::decode(value).toPrimitive(exec));
}
EncodedJSValue DFG_OPERATION operationStrCat(ExecState* exec, void* start, size_t size)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
return JSValue::encode(jsString(exec, static_cast<Register*>(start), size));
}
EncodedJSValue DFG_OPERATION operationNewArray(ExecState* exec, void* start, size_t size)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
return JSValue::encode(constructArray(exec, static_cast<JSValue*>(start), size));
}
@@ -795,6 +954,9 @@ EncodedJSValue DFG_OPERATION operationNewRegexp(ExecState* exec, void* regexpPtr
DFGHandlerEncoded DFG_OPERATION lookupExceptionHandler(ExecState* exec, uint32_t callIndex)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
JSValue exceptionValue = exec->exception();
ASSERT(exceptionValue);
@@ -806,29 +968,60 @@ DFGHandlerEncoded DFG_OPERATION lookupExceptionHandler(ExecState* exec, uint32_t
return dfgHandlerEncoded(exec, catchRoutine);
}
+DFGHandlerEncoded DFG_OPERATION lookupExceptionHandlerInStub(ExecState* exec, StructureStubInfo* stubInfo)
+{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
+ JSValue exceptionValue = exec->exception();
+ ASSERT(exceptionValue);
+
+ CodeOrigin codeOrigin = stubInfo->codeOrigin;
+ while (codeOrigin.inlineCallFrame)
+ codeOrigin = codeOrigin.inlineCallFrame->caller;
+
+ HandlerInfo* handler = exec->globalData().interpreter->throwException(exec, exceptionValue, codeOrigin.bytecodeIndex);
+
+ void* catchRoutine = handler ? handler->nativeCode.executableAddress() : (void*)ctiOpThrowNotCaught;
+ ASSERT(catchRoutine);
+ return dfgHandlerEncoded(exec, catchRoutine);
+}
+
double DFG_OPERATION dfgConvertJSValueToNumber(ExecState* exec, EncodedJSValue value)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
return JSValue::decode(value).toNumber(exec);
}
size_t DFG_OPERATION dfgConvertJSValueToInt32(ExecState* exec, EncodedJSValue value)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
// toInt32/toUInt32 return the same value; we want the value zero extended to fill the register.
return JSValue::decode(value).toUInt32(exec);
}
size_t DFG_OPERATION dfgConvertJSValueToBoolean(ExecState* exec, EncodedJSValue encodedOp)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
return JSValue::decode(encodedOp).toBoolean(exec);
}
#if DFG_ENABLE(VERBOSE_SPECULATION_FAILURE)
-void DFG_OPERATION debugOperationPrintSpeculationFailure(ExecState*, void* debugInfoRaw)
+void DFG_OPERATION debugOperationPrintSpeculationFailure(ExecState* exec, void* debugInfoRaw)
{
+ JSGlobalData* globalData = &exec->globalData();
+ NativeCallFrameTracer tracer(globalData, exec);
+
SpeculationFailureDebugInfo* debugInfo = static_cast<SpeculationFailureDebugInfo*>(debugInfoRaw);
CodeBlock* codeBlock = debugInfo->codeBlock;
CodeBlock* alternative = codeBlock->alternative();
- printf("Speculation failure in %p at @%u with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u, success/fail %u/%u\n", codeBlock, debugInfo->nodeIndex, alternative ? alternative->executeCounter() : 0, alternative ? alternative->reoptimizationRetryCounter() : 0, alternative ? alternative->optimizationDelayCounter() : 0, codeBlock->speculativeSuccessCounter(), codeBlock->speculativeFailCounter());
+ printf("Speculation failure in %p at @%u with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u, success/fail %u/%u\n", codeBlock, debugInfo->nodeIndex, alternative ? alternative->jitExecuteCounter() : 0, alternative ? alternative->reoptimizationRetryCounter() : 0, alternative ? alternative->optimizationDelayCounter() : 0, codeBlock->speculativeSuccessCounter(), codeBlock->speculativeFailCounter());
}
#endif
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h
index b4121dc21..5de9d3af3 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.h
+++ b/Source/JavaScriptCore/dfg/DFGOperations.h
@@ -104,7 +104,8 @@ EncodedJSValue DFG_OPERATION operationGetById(ExecState*, EncodedJSValue, Identi
EncodedJSValue DFG_OPERATION operationGetByIdBuildList(ExecState*, EncodedJSValue, Identifier*);
EncodedJSValue DFG_OPERATION operationGetByIdProtoBuildList(ExecState*, EncodedJSValue, Identifier*);
EncodedJSValue DFG_OPERATION operationGetByIdOptimize(ExecState*, EncodedJSValue, Identifier*);
-EncodedJSValue DFG_OPERATION operationGetMethodOptimize(ExecState*, EncodedJSValue, Identifier*);
+EncodedJSValue DFG_OPERATION operationCallCustomGetter(ExecState*, JSCell*, PropertySlot::GetValueFunc, Identifier*);
+EncodedJSValue DFG_OPERATION operationCallGetter(ExecState*, JSCell*, JSCell*);
EncodedJSValue DFG_OPERATION operationResolve(ExecState*, Identifier*);
EncodedJSValue DFG_OPERATION operationResolveBase(ExecState*, Identifier*);
EncodedJSValue DFG_OPERATION operationResolveBaseStrictPut(ExecState*, Identifier*);
@@ -181,6 +182,7 @@ inline DFGHandlerEncoded dfgHandlerEncoded(ExecState* exec, void* handler)
}
#endif
DFGHandlerEncoded DFG_OPERATION lookupExceptionHandler(ExecState*, uint32_t);
+DFGHandlerEncoded DFG_OPERATION lookupExceptionHandlerInStub(ExecState*, StructureStubInfo*);
// These operations implement the implicitly called ToInt32, ToNumber, and ToBoolean conversions from ES5.
double DFG_OPERATION dfgConvertJSValueToNumber(ExecState*, EncodedJSValue);
diff --git a/Source/JavaScriptCore/dfg/DFGPropagator.cpp b/Source/JavaScriptCore/dfg/DFGPropagator.cpp
index 631e82830..acfd2d364 100644
--- a/Source/JavaScriptCore/dfg/DFGPropagator.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPropagator.cpp
@@ -382,7 +382,7 @@ private:
if (left && right) {
if (isNumberPrediction(left) && isNumberPrediction(right)) {
- if (isInt32Prediction(mergePredictions(left, right)) && nodeCanSpeculateInteger(node.arithNodeFlags()))
+ if (m_graph.addShouldSpeculateInteger(node, m_codeBlock))
changed |= mergePrediction(PredictInt32);
else
changed |= mergePrediction(PredictDouble);
@@ -396,7 +396,19 @@ private:
}
case ArithAdd:
- case ArithSub:
+ case ArithSub: {
+ PredictedType left = m_graph[node.child1()].prediction();
+ PredictedType right = m_graph[node.child2()].prediction();
+
+ if (left && right) {
+ if (m_graph.addShouldSpeculateInteger(node, m_codeBlock))
+ changed |= mergePrediction(PredictInt32);
+ else
+ changed |= mergePrediction(PredictDouble);
+ }
+ break;
+ }
+
case ArithMul:
case ArithMin:
case ArithMax:
@@ -454,16 +466,22 @@ private:
bool isInt16Array = m_graph[node.child1()].shouldSpeculateInt16Array();
bool isInt32Array = m_graph[node.child1()].shouldSpeculateInt32Array();
bool isUint8Array = m_graph[node.child1()].shouldSpeculateUint8Array();
+ bool isUint8ClampedArray = m_graph[node.child1()].shouldSpeculateUint8ClampedArray();
bool isUint16Array = m_graph[node.child1()].shouldSpeculateUint16Array();
bool isUint32Array = m_graph[node.child1()].shouldSpeculateUint32Array();
bool isFloat32Array = m_graph[node.child1()].shouldSpeculateFloat32Array();
bool isFloat64Array = m_graph[node.child1()].shouldSpeculateFloat64Array();
- if (isArray || isString || isByteArray || isInt8Array || isInt16Array || isInt32Array || isUint8Array || isUint16Array || isUint32Array || isFloat32Array || isFloat64Array)
+ if (isArray || isString || isByteArray || isInt8Array || isInt16Array || isInt32Array || isUint8Array || isUint8ClampedArray || isUint16Array || isUint32Array || isFloat32Array || isFloat64Array)
changed |= mergePrediction(PredictInt32);
}
break;
}
+ case GetByIdFlush:
+ if (node.getHeapPrediction())
+ changed |= mergePrediction(node.getHeapPrediction());
+ break;
+
case GetByVal: {
if (m_graph[node.child1()].shouldSpeculateUint32Array() || m_graph[node.child1()].shouldSpeculateFloat32Array() || m_graph[node.child1()].shouldSpeculateFloat64Array())
changed |= mergePrediction(PredictDouble);
@@ -586,6 +604,7 @@ private:
case GetInt16ArrayLength:
case GetInt32ArrayLength:
case GetUint8ArrayLength:
+ case GetUint8ClampedArrayLength:
case GetUint16ArrayLength:
case GetUint32ArrayLength:
case GetFloat32ArrayLength:
@@ -705,7 +724,23 @@ private:
switch (node.op) {
case ValueAdd:
case ArithAdd:
- case ArithSub:
+ case ArithSub: {
+ PredictedType left = m_graph[node.child1()].prediction();
+ PredictedType right = m_graph[node.child2()].prediction();
+
+ VariableAccessData::Ballot ballot;
+
+ if (isNumberPrediction(left) && isNumberPrediction(right)
+ && !m_graph.addShouldSpeculateInteger(node, m_codeBlock))
+ ballot = VariableAccessData::VoteDouble;
+ else
+ ballot = VariableAccessData::VoteValue;
+
+ vote(node.child1(), ballot);
+ vote(node.child2(), ballot);
+ break;
+ }
+
case ArithMul:
case ArithMin:
case ArithMax:
@@ -822,27 +857,21 @@ private:
#endif
switch (op) {
- case ValueAdd: {
- if (!nodeCanSpeculateInteger(node.arithNodeFlags())) {
- toDouble(node.child1());
- toDouble(node.child2());
- break;
- }
-
+ case ValueAdd:
+ case ArithAdd:
+ case ArithSub: {
PredictedType left = m_graph[node.child1()].prediction();
PredictedType right = m_graph[node.child2()].prediction();
if (left && right
&& isNumberPrediction(left) && isNumberPrediction(right)
- && ((left & PredictDouble) || (right & PredictDouble))) {
+ && !m_graph.addShouldSpeculateInteger(node, m_codeBlock)) {
toDouble(node.child1());
toDouble(node.child2());
}
break;
}
- case ArithAdd:
- case ArithSub:
case ArithMul:
case ArithMin:
case ArithMax:
@@ -894,11 +923,12 @@ private:
bool isInt16Array = m_graph[node.child1()].shouldSpeculateInt16Array();
bool isInt32Array = m_graph[node.child1()].shouldSpeculateInt32Array();
bool isUint8Array = m_graph[node.child1()].shouldSpeculateUint8Array();
+ bool isUint8ClampedArray = m_graph[node.child1()].shouldSpeculateUint8ClampedArray();
bool isUint16Array = m_graph[node.child1()].shouldSpeculateUint16Array();
bool isUint32Array = m_graph[node.child1()].shouldSpeculateUint32Array();
bool isFloat32Array = m_graph[node.child1()].shouldSpeculateFloat32Array();
bool isFloat64Array = m_graph[node.child1()].shouldSpeculateFloat64Array();
- if (!isArray && !isString && !isByteArray && !isInt8Array && !isInt16Array && !isInt32Array && !isUint8Array && !isUint16Array && !isUint32Array && !isFloat32Array && !isFloat64Array)
+ if (!isArray && !isString && !isByteArray && !isInt8Array && !isInt16Array && !isInt32Array && !isUint8Array && !isUint8ClampedArray && !isUint16Array && !isUint32Array && !isFloat32Array && !isFloat64Array)
break;
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
@@ -918,6 +948,8 @@ private:
node.op = GetInt32ArrayLength;
else if (isUint8Array)
node.op = GetUint8ArrayLength;
+ else if (isUint8ClampedArray)
+ node.op = GetUint8ClampedArrayLength;
else if (isUint16Array)
node.op = GetUint16ArrayLength;
else if (isUint32Array)
@@ -1517,6 +1549,7 @@ private:
case GetInt16ArrayLength:
case GetInt32ArrayLength:
case GetUint8ArrayLength:
+ case GetUint8ClampedArrayLength:
case GetUint16ArrayLength:
case GetUint32ArrayLength:
case GetFloat32ArrayLength:
diff --git a/Source/JavaScriptCore/dfg/DFGRepatch.cpp b/Source/JavaScriptCore/dfg/DFGRepatch.cpp
index ae4a44ffe..f2928c290 100644
--- a/Source/JavaScriptCore/dfg/DFGRepatch.cpp
+++ b/Source/JavaScriptCore/dfg/DFGRepatch.cpp
@@ -28,6 +28,7 @@
#if ENABLE(DFG_JIT)
+#include "DFGCCallHelpers.h"
#include "DFGSpeculativeJIT.h"
#include "LinkBuffer.h"
#include "Operations.h"
@@ -149,7 +150,7 @@ static void generateProtoChainAccessStub(ExecState* exec, StructureStubInfo& stu
emitRestoreScratch(stubJit, needToRestoreScratch, scratchGPR, success, fail, failureCases);
- LinkBuffer patchBuffer(*globalData, &stubJit);
+ LinkBuffer patchBuffer(*globalData, &stubJit, exec->codeBlock());
linkRestoreScratch(patchBuffer, needToRestoreScratch, success, fail, failureCases, successLabel, slowCaseLabel);
@@ -200,7 +201,7 @@ static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier
emitRestoreScratch(stubJit, needToRestoreScratch, scratchGPR, success, fail, failureCases);
- LinkBuffer patchBuffer(*globalData, &stubJit);
+ LinkBuffer patchBuffer(*globalData, &stubJit, codeBlock);
linkRestoreScratch(patchBuffer, needToRestoreScratch, stubInfo, success, fail, failureCases);
@@ -227,8 +228,10 @@ static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier
// Optimize self access.
if (slot.slotBase() == baseValue) {
- if ((slot.cachedPropertyType() != PropertySlot::Value) || ((slot.cachedOffset() * sizeof(JSValue)) > (unsigned)MacroAssembler::MaximumCompactPtrAlignedAddressOffset))
- return false;
+ if ((slot.cachedPropertyType() != PropertySlot::Value) || ((slot.cachedOffset() * sizeof(JSValue)) > (unsigned)MacroAssembler::MaximumCompactPtrAlignedAddressOffset)) {
+ dfgRepatchCall(codeBlock, stubInfo.callReturnLocation, operationGetByIdBuildList);
+ return true;
+ }
dfgRepatchByIdSelfAccess(codeBlock, stubInfo, structure, slot.cachedOffset(), operationGetByIdBuildList, true);
stubInfo.initGetByIdSelf(*globalData, codeBlock->ownerExecutable(), structure);
@@ -268,16 +271,22 @@ void dfgRepatchGetByID(ExecState* exec, JSValue baseValue, const Identifier& pro
dfgRepatchCall(exec->codeBlock(), stubInfo.callReturnLocation, operationGetById);
}
-static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identifier&, const PropertySlot& slot, StructureStubInfo& stubInfo)
+static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identifier& ident, const PropertySlot& slot, StructureStubInfo& stubInfo)
{
if (!baseValue.isCell()
|| !slot.isCacheable()
|| baseValue.asCell()->structure()->isUncacheableDictionary()
- || slot.slotBase() != baseValue
- || slot.cachedPropertyType() != PropertySlot::Value
- || (slot.cachedOffset() * sizeof(JSValue)) > (unsigned)MacroAssembler::MaximumCompactPtrAlignedAddressOffset)
+ || slot.slotBase() != baseValue)
return false;
+ if (!stubInfo.registersFlushed) {
+ // We cannot do as much inline caching if the registers were not flushed prior to this GetById. In particular,
+ // non-Value cached properties require planting calls, which requires registers to have been flushed. Thus,
+ // if registers were not flushed, don't do non-Value caching.
+ if (slot.cachedPropertyType() != PropertySlot::Value)
+ return false;
+ }
+
CodeBlock* codeBlock = exec->codeBlock();
JSCell* baseCell = baseValue.asCell();
Structure* structure = baseCell->structure();
@@ -286,12 +295,18 @@ static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identi
ASSERT(slot.slotBase().isObject());
PolymorphicAccessStructureList* polymorphicStructureList;
- int listIndex = 1;
+ int listIndex;
- if (stubInfo.accessType == access_get_by_id_self) {
+ if (stubInfo.accessType == access_unset) {
+ ASSERT(!stubInfo.stubRoutine);
+ polymorphicStructureList = new PolymorphicAccessStructureList();
+ stubInfo.initGetByIdSelfList(polymorphicStructureList, 0);
+ listIndex = 0;
+ } else if (stubInfo.accessType == access_get_by_id_self) {
ASSERT(!stubInfo.stubRoutine);
polymorphicStructureList = new PolymorphicAccessStructureList(*globalData, codeBlock->ownerExecutable(), MacroAssemblerCodeRef::createSelfManagedCodeRef(stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase)), stubInfo.u.getByIdSelf.baseObjectStructure.get(), true);
stubInfo.initGetByIdSelfList(polymorphicStructureList, 1);
+ listIndex = 1;
} else {
polymorphicStructureList = stubInfo.u.getByIdSelfList.structureList;
listIndex = stubInfo.u.getByIdSelfList.listSize;
@@ -305,32 +320,93 @@ static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identi
GPRReg resultTagGPR = static_cast<GPRReg>(stubInfo.valueTagGPR);
#endif
GPRReg resultGPR = static_cast<GPRReg>(stubInfo.valueGPR);
+ GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.scratchGPR);
- MacroAssembler stubJit;
+ CCallHelpers stubJit(globalData, codeBlock);
MacroAssembler::Jump wrongStruct = stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(structure));
-
- stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
+
+ // The strategy we use for stubs is as follows:
+ // 1) Call DFG helper that calls the getter.
+ // 2) Check if there was an exception, and if there was, call yet another
+ // helper.
+
+ bool isDirect = false;
+ MacroAssembler::Call operationCall;
+ MacroAssembler::Call handlerCall;
+ FunctionPtr operationFunction;
+ MacroAssembler::Jump success;
+
+ if (slot.cachedPropertyType() == PropertySlot::Getter
+ || slot.cachedPropertyType() == PropertySlot::Custom) {
+ if (slot.cachedPropertyType() == PropertySlot::Getter) {
+ ASSERT(baseGPR != scratchGPR);
+ stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
#if USE(JSVALUE64)
- stubJit.loadPtr(MacroAssembler::Address(resultGPR, slot.cachedOffset() * sizeof(JSValue)), resultGPR);
+ stubJit.loadPtr(MacroAssembler::Address(scratchGPR, slot.cachedOffset() * sizeof(JSValue)), scratchGPR);
#elif USE(JSVALUE32_64)
- stubJit.load32(MacroAssembler::Address(resultGPR, slot.cachedOffset() * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR);
- stubJit.load32(MacroAssembler::Address(resultGPR, slot.cachedOffset() * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultGPR);
+ stubJit.load32(MacroAssembler::Address(scratchGPR, slot.cachedOffset() * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), scratchGPR);
#endif
+ stubJit.setupArgumentsWithExecState(baseGPR, scratchGPR);
+ operationFunction = operationCallGetter;
+ } else {
+ stubJit.setupArgumentsWithExecState(
+ baseGPR,
+ MacroAssembler::TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()),
+ MacroAssembler::TrustedImmPtr(const_cast<Identifier*>(&ident)));
+ operationFunction = operationCallCustomGetter;
+ }
+
+ // Need to make sure that whenever this call is made in the future, we remember the
+ // place that we made it from. It just so happens to be the place that we are at
+ // right now!
+ stubJit.store32(
+ MacroAssembler::TrustedImm32(exec->codeOriginIndexForDFGWithInlining()),
+ CCallHelpers::tagFor(static_cast<VirtualRegister>(RegisterFile::ArgumentCount)));
+
+ operationCall = stubJit.call();
+#if USE(JSVALUE64)
+ stubJit.move(GPRInfo::returnValueGPR, resultGPR);
+#else
+ stubJit.setupResults(resultGPR, resultTagGPR);
+#endif
+ success = stubJit.emitExceptionCheck(CCallHelpers::InvertedExceptionCheck);
+
+ stubJit.setupArgumentsWithExecState(
+ MacroAssembler::TrustedImmPtr(&stubInfo));
+ handlerCall = stubJit.call();
+ stubJit.jump(GPRInfo::returnValueGPR2);
+ } else {
+ stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
+#if USE(JSVALUE64)
+ stubJit.loadPtr(MacroAssembler::Address(resultGPR, slot.cachedOffset() * sizeof(JSValue)), resultGPR);
+#elif USE(JSVALUE32_64)
+ stubJit.load32(MacroAssembler::Address(resultGPR, slot.cachedOffset() * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR);
+ stubJit.load32(MacroAssembler::Address(resultGPR, slot.cachedOffset() * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultGPR);
+#endif
+ success = stubJit.jump();
+ isDirect = true;
+ }
- MacroAssembler::Jump success = stubJit.jump();
-
- LinkBuffer patchBuffer(*globalData, &stubJit);
+ LinkBuffer patchBuffer(*globalData, &stubJit, codeBlock);
- CodeLocationLabel lastProtoBegin = CodeLocationLabel(polymorphicStructureList->list[listIndex - 1].stubRoutine.code());
+ CodeLocationLabel lastProtoBegin;
+ if (listIndex)
+ lastProtoBegin = CodeLocationLabel(polymorphicStructureList->list[listIndex - 1].stubRoutine.code());
+ else
+ lastProtoBegin = stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase);
ASSERT(!!lastProtoBegin);
patchBuffer.link(wrongStruct, lastProtoBegin);
patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToDone));
+ if (!isDirect) {
+ patchBuffer.link(operationCall, operationFunction);
+ patchBuffer.link(handlerCall, lookupExceptionHandlerInStub);
+ }
MacroAssemblerCodeRef stubRoutine = patchBuffer.finalizeCode();
- polymorphicStructureList->list[listIndex].set(*globalData, codeBlock->ownerExecutable(), stubRoutine, structure, true);
+ polymorphicStructureList->list[listIndex].set(*globalData, codeBlock->ownerExecutable(), stubRoutine, structure, isDirect);
CodeLocationJump jumpLocation = stubInfo.callReturnLocation.jumpAtOffset(stubInfo.deltaCallToStructCheck);
RepatchBuffer repatchBuffer(codeBlock);
@@ -538,7 +614,7 @@ static bool tryCachePutByID(ExecState* exec, JSValue baseValue, const Identifier
} else
success = stubJit.jump();
- LinkBuffer patchBuffer(*globalData, &stubJit);
+ LinkBuffer patchBuffer(*globalData, &stubJit, codeBlock);
patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToDone));
if (needToRestoreScratch)
patchBuffer.link(failure, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase));
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index feb705ab8..e647fb87a 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -1112,6 +1112,11 @@ void SpeculativeJIT::checkArgumentTypes()
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
+ } else if (isUint8ClampedArrayPrediction(predictedType)) {
+ GPRTemporary temp(this);
+ m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ClampedArrayDescriptor().m_classInfo)));
} else if (isUint16ArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
@@ -1174,6 +1179,12 @@ void SpeculativeJIT::checkArgumentTypes()
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
+ } else if (isUint8ClampedArrayPrediction(predictedType)) {
+ GPRTemporary temp(this);
+ m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+ m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ClampedArrayDescriptor().m_classInfo)));
} else if (isUint16ArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
@@ -1529,6 +1540,28 @@ void SpeculativeJIT::compileUInt32ToNumber(Node& node)
integerResult(result.gpr(), m_compileIndex, op1.format());
}
+static double clampDoubleToByte(double d)
+{
+ d += 0.5;
+ if (!(d > 0))
+ d = 0;
+ else if (d > 255)
+ d = 255;
+ return d;
+}
+
+static void compileClampIntegerToByte(JITCompiler& jit, GPRReg result)
+{
+ MacroAssembler::Jump inBounds = jit.branch32(MacroAssembler::BelowOrEqual, result, JITCompiler::TrustedImm32(0xff));
+ MacroAssembler::Jump tooBig = jit.branch32(MacroAssembler::GreaterThan, result, JITCompiler::TrustedImm32(0xff));
+ jit.xorPtr(result, result);
+ MacroAssembler::Jump clamped = jit.jump();
+ tooBig.link(&jit);
+ jit.move(JITCompiler::TrustedImm32(255), result);
+ clamped.link(&jit);
+ inBounds.link(&jit);
+}
+
static void compileClampDoubleToByte(JITCompiler& jit, GPRReg result, FPRReg source, FPRReg scratch)
{
// Unordered compare so we pick up NaN
@@ -1576,15 +1609,10 @@ void SpeculativeJIT::compilePutByValForByteArray(GPRReg base, GPRReg property, N
noResult(m_compileIndex);
return;
}
- double d = jsValue.asNumber();
- d += 0.5;
- if (!(d > 0))
- d = 0;
- else if (d > 255)
- d = 255;
+ int clampedValue = clampDoubleToByte(jsValue.asNumber());
GPRTemporary scratch(this);
GPRReg scratchReg = scratch.gpr();
- m_jit.move(Imm32((int)d), scratchReg);
+ m_jit.move(Imm32(clampedValue), scratchReg);
value.adopt(scratch);
valueGPR = scratchReg;
} else if (!at(valueIndex).shouldNotSpeculateInteger()) {
@@ -1592,14 +1620,7 @@ void SpeculativeJIT::compilePutByValForByteArray(GPRReg base, GPRReg property, N
GPRTemporary scratch(this);
GPRReg scratchReg = scratch.gpr();
m_jit.move(valueOp.gpr(), scratchReg);
- MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::BelowOrEqual, scratchReg, TrustedImm32(0xff));
- MacroAssembler::Jump tooBig = m_jit.branch32(MacroAssembler::GreaterThan, scratchReg, TrustedImm32(0xff));
- m_jit.xorPtr(scratchReg, scratchReg);
- MacroAssembler::Jump clamped = m_jit.jump();
- tooBig.link(&m_jit);
- m_jit.move(TrustedImm32(255), scratchReg);
- clamped.link(&m_jit);
- inBounds.link(&m_jit);
+ compileClampIntegerToByte(m_jit, scratchReg);
value.adopt(scratch);
valueGPR = scratchReg;
} else {
@@ -1722,7 +1743,7 @@ void SpeculativeJIT::compileGetByValOnIntTypedArray(const TypedArrayDescriptor&
}
}
-void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements, TypedArraySignedness signedness)
+void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements, TypedArraySignedness signedness, TypedArrayRounding rounding)
{
NodeIndex baseIndex = node.child1();
NodeIndex valueIndex = node.child3();
@@ -1740,9 +1761,13 @@ void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor&
return;
}
double d = jsValue.asNumber();
+ if (rounding == ClampRounding) {
+ ASSERT(elementSize == 1);
+ d = clampDoubleToByte(d);
+ }
GPRTemporary scratch(this);
GPRReg scratchReg = scratch.gpr();
- m_jit.move(Imm32((int)d), scratchReg);
+ m_jit.move(Imm32(static_cast<int>(d)), scratchReg);
value.adopt(scratch);
valueGPR = scratchReg;
} else if (!at(valueIndex).shouldNotSpeculateInteger()) {
@@ -1750,8 +1775,22 @@ void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor&
GPRTemporary scratch(this);
GPRReg scratchReg = scratch.gpr();
m_jit.move(valueOp.gpr(), scratchReg);
+ if (rounding == ClampRounding) {
+ ASSERT(elementSize == 1);
+ compileClampIntegerToByte(m_jit, scratchReg);
+ }
value.adopt(scratch);
valueGPR = scratchReg;
+ } else if (rounding == ClampRounding) {
+ ASSERT(elementSize == 1);
+ SpeculateDoubleOperand valueOp(this, valueIndex);
+ GPRTemporary result(this);
+ FPRTemporary floatScratch(this);
+ FPRReg fpr = valueOp.fpr();
+ GPRReg gpr = result.gpr();
+ compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr());
+ value.adopt(result);
+ valueGPR = gpr;
} else {
SpeculateDoubleOperand valueOp(this, valueIndex);
GPRTemporary result(this);
@@ -1761,17 +1800,17 @@ void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor&
m_jit.xorPtr(gpr, gpr);
MacroAssembler::Jump fixed = m_jit.jump();
notNaN.link(&m_jit);
-
+
MacroAssembler::Jump done;
if (signedness == SignedTypedArray)
done = m_jit.branchTruncateDoubleToInt32(fpr, gpr, MacroAssembler::BranchIfTruncateSuccessful);
else
done = m_jit.branchTruncateDoubleToUint32(fpr, gpr, MacroAssembler::BranchIfTruncateSuccessful);
-
+
silentSpillAllRegisters(gpr);
callOperation(toInt32, gpr, fpr);
silentFillAllRegisters(gpr);
-
+
done.link(&m_jit);
fixed.link(&m_jit);
value.adopt(result);
@@ -2157,6 +2196,144 @@ void SpeculativeJIT::compileSoftModulo(Node& node)
#endif
}
+void SpeculativeJIT::compileAdd(Node& node)
+{
+ if (m_jit.graph().addShouldSpeculateInteger(node, m_jit.codeBlock())) {
+ if (isNumberConstant(node.child1())) {
+ int32_t imm1 = valueOfNumberConstantAsInt32(node.child1());
+ SpeculateIntegerOperand op2(this, node.child2());
+ GPRTemporary result(this);
+
+ if (nodeCanTruncateInteger(node.arithNodeFlags())) {
+ m_jit.move(op2.gpr(), result.gpr());
+ m_jit.add32(Imm32(imm1), result.gpr());
+ } else
+ speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
+
+ integerResult(result.gpr(), m_compileIndex);
+ return;
+ }
+
+ if (isNumberConstant(node.child2())) {
+ SpeculateIntegerOperand op1(this, node.child1());
+ int32_t imm2 = valueOfNumberConstantAsInt32(node.child2());
+ GPRTemporary result(this);
+
+ if (nodeCanTruncateInteger(node.arithNodeFlags())) {
+ m_jit.move(op1.gpr(), result.gpr());
+ m_jit.add32(Imm32(imm2), result.gpr());
+ } else
+ speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
+
+ integerResult(result.gpr(), m_compileIndex);
+ return;
+ }
+
+ SpeculateIntegerOperand op1(this, node.child1());
+ SpeculateIntegerOperand op2(this, node.child2());
+ GPRTemporary result(this, op1, op2);
+
+ GPRReg gpr1 = op1.gpr();
+ GPRReg gpr2 = op2.gpr();
+ GPRReg gprResult = result.gpr();
+
+ if (nodeCanTruncateInteger(node.arithNodeFlags())) {
+ if (gpr1 == gprResult)
+ m_jit.add32(gpr2, gprResult);
+ else {
+ m_jit.move(gpr2, gprResult);
+ m_jit.add32(gpr1, gprResult);
+ }
+ } else {
+ MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
+
+ if (gpr1 == gprResult)
+ speculationCheck(Overflow, JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
+ else if (gpr2 == gprResult)
+ speculationCheck(Overflow, JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
+ else
+ speculationCheck(Overflow, JSValueRegs(), NoNode, check);
+ }
+
+ integerResult(gprResult, m_compileIndex);
+ return;
+ }
+
+ if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
+ SpeculateDoubleOperand op1(this, node.child1());
+ SpeculateDoubleOperand op2(this, node.child2());
+ FPRTemporary result(this, op1, op2);
+
+ FPRReg reg1 = op1.fpr();
+ FPRReg reg2 = op2.fpr();
+ m_jit.addDouble(reg1, reg2, result.fpr());
+
+ doubleResult(result.fpr(), m_compileIndex);
+ return;
+ }
+
+ ASSERT(node.op == ValueAdd);
+ compileValueAdd(node);
+}
+
+void SpeculativeJIT::compileArithSub(Node& node)
+{
+ if (m_jit.graph().addShouldSpeculateInteger(node, m_jit.codeBlock())) {
+ if (isNumberConstant(node.child2())) {
+ SpeculateIntegerOperand op1(this, node.child1());
+ int32_t imm2 = valueOfNumberConstantAsInt32(node.child2());
+ GPRTemporary result(this);
+
+ if (nodeCanTruncateInteger(node.arithNodeFlags())) {
+ m_jit.move(op1.gpr(), result.gpr());
+ m_jit.sub32(Imm32(imm2), result.gpr());
+ } else
+ speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
+
+ integerResult(result.gpr(), m_compileIndex);
+ return;
+ }
+
+ if (isNumberConstant(node.child1())) {
+ int32_t imm1 = valueOfNumberConstantAsInt32(node.child1());
+ SpeculateIntegerOperand op2(this, node.child2());
+ GPRTemporary result(this);
+
+ m_jit.move(Imm32(imm1), result.gpr());
+ if (nodeCanTruncateInteger(node.arithNodeFlags()))
+ m_jit.sub32(op2.gpr(), result.gpr());
+ else
+ speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op2.gpr(), result.gpr()));
+
+ integerResult(result.gpr(), m_compileIndex);
+ return;
+ }
+
+ SpeculateIntegerOperand op1(this, node.child1());
+ SpeculateIntegerOperand op2(this, node.child2());
+ GPRTemporary result(this);
+
+ if (nodeCanTruncateInteger(node.arithNodeFlags())) {
+ m_jit.move(op1.gpr(), result.gpr());
+ m_jit.sub32(op2.gpr(), result.gpr());
+ } else
+ speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
+
+ integerResult(result.gpr(), m_compileIndex);
+ return;
+ }
+
+ SpeculateDoubleOperand op1(this, node.child1());
+ SpeculateDoubleOperand op2(this, node.child2());
+ FPRTemporary result(this, op1);
+
+ FPRReg reg1 = op1.fpr();
+ FPRReg reg2 = op2.fpr();
+ m_jit.subDouble(reg1, reg2, result.fpr());
+
+ doubleResult(result.fpr(), m_compileIndex);
+}
+
void SpeculativeJIT::compileArithMul(Node& node)
{
if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
@@ -2451,6 +2628,11 @@ void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node)
if (!isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type))
speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
+ } else if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
+ const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint8ClampedArrayDescriptor();
+ if (!isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type))
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
+ m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else if (at(node.child1()).shouldSpeculateUint16Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint16ArrayDescriptor();
if (!isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type))
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index 3b709400d..0098da3a1 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -325,18 +325,21 @@ public:
void writeBarrier(GPRReg ownerGPR, JSCell* value, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg, GPRReg scratchGPR2 = InvalidGPRReg);
void writeBarrier(JSCell* owner, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg);
- static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg)
+ static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg, GPRReg preserve4 = InvalidGPRReg)
{
- if (preserve1 != GPRInfo::regT0 && preserve2 != GPRInfo::regT0 && preserve3 != GPRInfo::regT0)
+ if (preserve1 != GPRInfo::regT0 && preserve2 != GPRInfo::regT0 && preserve3 != GPRInfo::regT0 && preserve4 != GPRInfo::regT0)
return GPRInfo::regT0;
- if (preserve1 != GPRInfo::regT1 && preserve2 != GPRInfo::regT1 && preserve3 != GPRInfo::regT1)
+ if (preserve1 != GPRInfo::regT1 && preserve2 != GPRInfo::regT1 && preserve3 != GPRInfo::regT1 && preserve4 != GPRInfo::regT1)
return GPRInfo::regT1;
- if (preserve1 != GPRInfo::regT2 && preserve2 != GPRInfo::regT2 && preserve3 != GPRInfo::regT2)
+ if (preserve1 != GPRInfo::regT2 && preserve2 != GPRInfo::regT2 && preserve3 != GPRInfo::regT2 && preserve4 != GPRInfo::regT2)
return GPRInfo::regT2;
- return GPRInfo::regT3;
+ if (preserve1 != GPRInfo::regT3 && preserve2 != GPRInfo::regT3 && preserve3 != GPRInfo::regT3 && preserve4 != GPRInfo::regT3)
+ return GPRInfo::regT3;
+
+ return GPRInfo::regT4;
}
// Called by the speculative operand types, below, to fill operand to
@@ -727,6 +730,12 @@ private:
bool isFunctionConstant(NodeIndex nodeIndex) { return m_jit.isFunctionConstant(nodeIndex); }
int32_t valueOfInt32Constant(NodeIndex nodeIndex) { return m_jit.valueOfInt32Constant(nodeIndex); }
double valueOfNumberConstant(NodeIndex nodeIndex) { return m_jit.valueOfNumberConstant(nodeIndex); }
+ int32_t valueOfNumberConstantAsInt32(NodeIndex nodeIndex)
+ {
+ if (isInt32Constant(nodeIndex))
+ return valueOfInt32Constant(nodeIndex);
+ return JSC::toInt32(valueOfNumberConstant(nodeIndex));
+ }
#if USE(JSVALUE32_64)
void* addressOfDoubleConstant(NodeIndex nodeIndex) { return m_jit.addressOfDoubleConstant(nodeIndex); }
#endif
@@ -872,12 +881,13 @@ private:
void nonSpeculativeValueToInt32(Node&);
void nonSpeculativeUInt32ToNumber(Node&);
+ enum SpillRegistersMode { NeedToSpill, DontSpill };
#if USE(JSVALUE64)
- JITCompiler::Call cachedGetById(GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
- void cachedPutById(GPRReg base, GPRReg value, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
+ JITCompiler::Call cachedGetById(CodeOrigin, GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill);
+ void cachedPutById(CodeOrigin, GPRReg base, GPRReg value, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
#elif USE(JSVALUE32_64)
- JITCompiler::Call cachedGetById(GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
- void cachedPutById(GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
+ JITCompiler::Call cachedGetById(CodeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill);
+ void cachedPutById(CodeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
#endif
void nonSpeculativeNonPeepholeCompareNull(NodeIndex operand, bool invert = false);
@@ -1060,457 +1070,6 @@ private:
m_generationInfo[node.virtualRegister()].initConstant(nodeIndex, node.refCount());
}
- // These methods used to sort arguments into the correct registers.
- // On X86 we use cdecl calling conventions, which pass all arguments on the
- // stack. On other architectures we may need to sort values into the
- // correct registers.
-#if !NUMBER_OF_ARGUMENT_REGISTERS
- unsigned m_callArgumentOffset;
- void resetCallArguments() { m_callArgumentOffset = 0; }
-
- // These methods are using internally to implement the callOperation methods.
- void addCallArgument(GPRReg value)
- {
- m_jit.poke(value, m_callArgumentOffset++);
- }
- void addCallArgument(TrustedImm32 imm)
- {
- m_jit.poke(imm, m_callArgumentOffset++);
- }
- void addCallArgument(TrustedImmPtr pointer)
- {
- m_jit.poke(pointer, m_callArgumentOffset++);
- }
- void addCallArgument(FPRReg value)
- {
- m_jit.storeDouble(value, JITCompiler::Address(JITCompiler::stackPointerRegister, m_callArgumentOffset * sizeof(void*)));
- m_callArgumentOffset += sizeof(double) / sizeof(void*);
- }
-
- ALWAYS_INLINE void setupArguments(FPRReg arg1)
- {
- resetCallArguments();
- addCallArgument(arg1);
- }
-
- ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
- {
- resetCallArguments();
- addCallArgument(arg1);
- addCallArgument(arg2);
- }
-
- ALWAYS_INLINE void setupArgumentsExecState()
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- addCallArgument(arg2);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- addCallArgument(arg2);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- addCallArgument(arg2);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- addCallArgument(arg2);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- addCallArgument(arg2);
- addCallArgument(arg3);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- addCallArgument(arg2);
- addCallArgument(arg3);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- addCallArgument(arg2);
- addCallArgument(arg3);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- addCallArgument(arg2);
- addCallArgument(arg3);
- addCallArgument(arg4);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- addCallArgument(arg2);
- addCallArgument(arg3);
- addCallArgument(arg4);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImm32 arg4)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- addCallArgument(arg2);
- addCallArgument(arg3);
- addCallArgument(arg4);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3, GPRReg arg4)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- addCallArgument(arg2);
- addCallArgument(arg3);
- addCallArgument(arg4);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- addCallArgument(arg2);
- addCallArgument(arg3);
- addCallArgument(arg4);
- addCallArgument(arg5);
- }
-#endif // !NUMBER_OF_ARGUMENT_REGISTERS
- // These methods are suitable for any calling convention that provides for
- // at least 4 argument registers, e.g. X86_64, ARMv7.
-#if NUMBER_OF_ARGUMENT_REGISTERS >= 4
- template<GPRReg destA, GPRReg destB>
- void setupTwoStubArgs(GPRReg srcA, GPRReg srcB)
- {
- // Assuming that srcA != srcB, there are 7 interesting states the registers may be in:
- // (1) both are already in arg regs, the right way around.
- // (2) both are already in arg regs, the wrong way around.
- // (3) neither are currently in arg registers.
- // (4) srcA in in its correct reg.
- // (5) srcA in in the incorrect reg.
- // (6) srcB in in its correct reg.
- // (7) srcB in in the incorrect reg.
- //
- // The trivial approach is to simply emit two moves, to put srcA in place then srcB in
- // place (the MacroAssembler will omit redundant moves). This apporach will be safe in
- // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2
- // (requires a swap) and 7 (must move srcB first, to avoid trampling.)
-
- if (srcB != destA) {
- // Handle the easy cases - two simple moves.
- m_jit.move(srcA, destA);
- m_jit.move(srcB, destB);
- } else if (srcA != destB) {
- // Handle the non-swap case - just put srcB in place first.
- m_jit.move(srcB, destB);
- m_jit.move(srcA, destA);
- } else
- m_jit.swap(destA, destB);
- }
-#if CPU(X86_64)
- template<FPRReg destA, FPRReg destB>
- void setupTwoStubArgs(FPRReg srcA, FPRReg srcB)
- {
- // Assuming that srcA != srcB, there are 7 interesting states the registers may be in:
- // (1) both are already in arg regs, the right way around.
- // (2) both are already in arg regs, the wrong way around.
- // (3) neither are currently in arg registers.
- // (4) srcA in in its correct reg.
- // (5) srcA in in the incorrect reg.
- // (6) srcB in in its correct reg.
- // (7) srcB in in the incorrect reg.
- //
- // The trivial approach is to simply emit two moves, to put srcA in place then srcB in
- // place (the MacroAssembler will omit redundant moves). This apporach will be safe in
- // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2
- // (requires a swap) and 7 (must move srcB first, to avoid trampling.)
-
- if (srcB != destA) {
- // Handle the easy cases - two simple moves.
- m_jit.moveDouble(srcA, destA);
- m_jit.moveDouble(srcB, destB);
- return;
- }
-
- if (srcA != destB) {
- // Handle the non-swap case - just put srcB in place first.
- m_jit.moveDouble(srcB, destB);
- m_jit.moveDouble(srcA, destA);
- return;
- }
-
- ASSERT(srcB == destA && srcA == destB);
- // Need to swap; pick a temporary register.
- FPRReg temp;
- if (destA != FPRInfo::argumentFPR3 && destA != FPRInfo::argumentFPR3)
- temp = FPRInfo::argumentFPR3;
- else if (destA != FPRInfo::argumentFPR2 && destA != FPRInfo::argumentFPR2)
- temp = FPRInfo::argumentFPR2;
- else {
- ASSERT(destA != FPRInfo::argumentFPR1 && destA != FPRInfo::argumentFPR1);
- temp = FPRInfo::argumentFPR1;
- }
- m_jit.moveDouble(destA, temp);
- m_jit.moveDouble(destB, destA);
- m_jit.moveDouble(temp, destB);
- }
-#endif
- void setupStubArguments(GPRReg arg1, GPRReg arg2)
- {
- setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(arg1, arg2);
- }
- void setupStubArguments(GPRReg arg1, GPRReg arg2, GPRReg arg3)
- {
- // If neither of arg2/arg3 are in our way, then we can move arg1 into place.
- // Then we can use setupTwoStubArgs to fix arg2/arg3.
- if (arg2 != GPRInfo::argumentGPR1 && arg3 != GPRInfo::argumentGPR1) {
- m_jit.move(arg1, GPRInfo::argumentGPR1);
- setupTwoStubArgs<GPRInfo::argumentGPR2, GPRInfo::argumentGPR3>(arg2, arg3);
- return;
- }
-
- // If neither of arg1/arg3 are in our way, then we can move arg2 into place.
- // Then we can use setupTwoStubArgs to fix arg1/arg3.
- if (arg1 != GPRInfo::argumentGPR2 && arg3 != GPRInfo::argumentGPR2) {
- m_jit.move(arg2, GPRInfo::argumentGPR2);
- setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR3>(arg1, arg3);
- return;
- }
-
- // If neither of arg1/arg2 are in our way, then we can move arg3 into place.
- // Then we can use setupTwoStubArgs to fix arg1/arg2.
- if (arg1 != GPRInfo::argumentGPR3 && arg2 != GPRInfo::argumentGPR3) {
- m_jit.move(arg3, GPRInfo::argumentGPR3);
- setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(arg1, arg2);
- return;
- }
-
- // If we get here, we haven't been able to move any of arg1/arg2/arg3.
- // Since all three are blocked, then all three must already be in the argument register.
- // But are they in the right ones?
-
- // First, ensure arg1 is in place.
- if (arg1 != GPRInfo::argumentGPR1) {
- m_jit.swap(arg1, GPRInfo::argumentGPR1);
-
- // If arg1 wasn't in argumentGPR1, one of arg2/arg3 must be.
- ASSERT(arg2 == GPRInfo::argumentGPR1 || arg3 == GPRInfo::argumentGPR1);
- // If arg2 was in argumentGPR1 it no longer is (due to the swap).
- // Otherwise arg3 must have been. Mark him as moved.
- if (arg2 == GPRInfo::argumentGPR1)
- arg2 = arg1;
- else
- arg3 = arg1;
- }
-
- // Either arg2 & arg3 need swapping, or we're all done.
- ASSERT((arg2 == GPRInfo::argumentGPR2 || arg3 == GPRInfo::argumentGPR3)
- || (arg2 == GPRInfo::argumentGPR3 || arg3 == GPRInfo::argumentGPR2));
-
- if (arg2 != GPRInfo::argumentGPR2)
- m_jit.swap(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3);
- }
-
-#if CPU(X86_64)
- ALWAYS_INLINE void setupArguments(FPRReg arg1)
- {
- m_jit.moveDouble(arg1, FPRInfo::argumentFPR0);
- }
-
- ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
- {
- setupTwoStubArgs<FPRInfo::argumentFPR0, FPRInfo::argumentFPR1>(arg1, arg2);
- }
-#else
- ALWAYS_INLINE void setupArguments(FPRReg arg1)
- {
- m_jit.assembler().vmov(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, arg1);
- }
-
- ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
- {
- m_jit.assembler().vmov(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, arg1);
- m_jit.assembler().vmov(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, arg2);
- }
-#endif
-
- ALWAYS_INLINE void setupArgumentsExecState()
- {
- m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1)
- {
- m_jit.move(arg1, GPRInfo::argumentGPR1);
- m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1)
- {
- m_jit.move(arg1, GPRInfo::argumentGPR1);
- m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2)
- {
- setupStubArguments(arg1, arg2);
- m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2)
- {
- m_jit.move(arg1, GPRInfo::argumentGPR1);
- m_jit.move(arg2, GPRInfo::argumentGPR2);
- m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, GPRReg arg2)
- {
- m_jit.move(arg2, GPRInfo::argumentGPR2); // Move this first, so setting arg1 does not trample!
- m_jit.move(arg1, GPRInfo::argumentGPR1);
- m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2)
- {
- m_jit.move(arg1, GPRInfo::argumentGPR1);
- m_jit.move(arg2, GPRInfo::argumentGPR2);
- m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2)
- {
- m_jit.move(arg1, GPRInfo::argumentGPR1);
- m_jit.move(arg2, GPRInfo::argumentGPR2);
- m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3)
- {
- setupStubArguments(arg1, arg2, arg3);
- m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3)
- {
- setupStubArguments(arg1, arg2);
- m_jit.move(arg3, GPRInfo::argumentGPR3);
- m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3)
- {
- m_jit.move(arg1, GPRInfo::argumentGPR1);
- m_jit.move(arg2, GPRInfo::argumentGPR2);
- m_jit.move(arg3, GPRInfo::argumentGPR3);
- m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3)
- {
- setupStubArguments(arg1, arg2);
- m_jit.move(arg3, GPRInfo::argumentGPR3);
- m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3)
- {
- m_jit.move(arg1, GPRInfo::argumentGPR1);
- m_jit.move(arg2, GPRInfo::argumentGPR2);
- m_jit.move(arg3, GPRInfo::argumentGPR3);
- m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- }
-
-#endif // NUMBER_OF_ARGUMENT_REGISTERS >= 4
- // These methods are suitable for any calling convention that provides for
- // exactly 4 argument registers, e.g. ARMv7.
-#if NUMBER_OF_ARGUMENT_REGISTERS == 4
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4)
- {
- m_jit.poke(arg4);
- setupArgumentsWithExecState(arg1, arg2, arg3);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImm32 arg4)
- {
- m_jit.poke(arg4);
- setupArgumentsWithExecState(arg1, arg2, arg3);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3, GPRReg arg4)
- {
- m_jit.poke(arg4);
- setupArgumentsWithExecState(arg1, arg2, arg3);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
- {
- m_jit.poke(arg4);
- setupArgumentsWithExecState(arg1, arg2, arg3);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
- {
- m_jit.poke(arg5, 1);
- m_jit.poke(arg4);
- setupArgumentsWithExecState(arg1, arg2, arg3);
- }
-#endif // NUMBER_OF_ARGUMENT_REGISTERS == 4
-
// These methods add calls to C++ helper functions.
// These methods are broadly value representation specific (i.e.
// deal with the fact that a JSValue may be passed in one or two
@@ -1519,314 +1078,314 @@ private:
#if USE(JSVALUE64)
JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg result, void* pointer)
{
- setupArgumentsWithExecState(TrustedImmPtr(pointer));
+ m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer));
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(Z_DFGOperation_D operation, GPRReg result, FPRReg arg1)
{
- setupArguments(arg1);
+ m_jit.setupArguments(arg1);
JITCompiler::Call call = m_jit.appendCall(operation);
m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, result);
return call;
}
JITCompiler::Call callOperation(J_DFGOperation_EGI operation, GPRReg result, GPRReg arg1, Identifier* identifier)
{
- setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
+ m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(J_DFGOperation_EI operation, GPRReg result, Identifier* identifier)
{
- setupArgumentsWithExecState(TrustedImmPtr(identifier));
+ m_jit.setupArgumentsWithExecState(TrustedImmPtr(identifier));
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(J_DFGOperation_EA operation, GPRReg result, GPRReg arg1)
{
- setupArgumentsWithExecState(arg1);
+ m_jit.setupArgumentsWithExecState(arg1);
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(J_DFGOperation_EPS operation, GPRReg result, void* pointer, size_t size)
{
- setupArgumentsWithExecState(TrustedImmPtr(pointer), TrustedImmPtr(size));
+ m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer), TrustedImmPtr(size));
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(J_DFGOperation_ESS operation, GPRReg result, int startConstant, int numConstants)
{
- setupArgumentsWithExecState(Imm32(startConstant), Imm32(numConstants));
+ m_jit.setupArgumentsWithExecState(Imm32(startConstant), Imm32(numConstants));
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(J_DFGOperation_EPP operation, GPRReg result, GPRReg arg1, void* pointer)
{
- setupArgumentsWithExecState(arg1, TrustedImmPtr(pointer));
+ m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(pointer));
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(J_DFGOperation_ECI operation, GPRReg result, GPRReg arg1, Identifier* identifier)
{
- setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
+ m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(J_DFGOperation_EJI operation, GPRReg result, GPRReg arg1, Identifier* identifier)
{
- setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
+ m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(J_DFGOperation_EJA operation, GPRReg result, GPRReg arg1, GPRReg arg2)
{
- setupArgumentsWithExecState(arg1, arg2);
+ m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg result, GPRReg arg1)
{
- setupArgumentsWithExecState(arg1);
+ m_jit.setupArgumentsWithExecState(arg1);
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(C_DFGOperation_E operation, GPRReg result)
{
- setupArgumentsExecState();
+ m_jit.setupArgumentsExecState();
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(C_DFGOperation_EC operation, GPRReg result, GPRReg arg1)
{
- setupArgumentsWithExecState(arg1);
+ m_jit.setupArgumentsWithExecState(arg1);
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(C_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, JSCell* cell)
{
- setupArgumentsWithExecState(arg1, TrustedImmPtr(cell));
+ m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell));
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(S_DFGOperation_EJ operation, GPRReg result, GPRReg arg1)
{
- setupArgumentsWithExecState(arg1);
+ m_jit.setupArgumentsWithExecState(arg1);
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(S_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
{
- setupArgumentsWithExecState(arg1, arg2);
+ m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(J_DFGOperation_EPP operation, GPRReg result, GPRReg arg1, GPRReg arg2)
{
- setupArgumentsWithExecState(arg1, arg2);
+ m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1, MacroAssembler::Imm32 imm)
{
- setupArgumentsWithExecState(arg1, MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm.m_value)))));
+ m_jit.setupArgumentsWithExecState(arg1, MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm.m_value)))));
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg result, MacroAssembler::Imm32 imm, GPRReg arg2)
{
- setupArgumentsWithExecState(MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm.m_value)))), arg2);
+ m_jit.setupArgumentsWithExecState(MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm.m_value)))), arg2);
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(J_DFGOperation_ECJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
{
- setupArgumentsWithExecState(arg1, arg2);
+ m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(V_DFGOperation_EJPP operation, GPRReg arg1, GPRReg arg2, void* pointer)
{
- setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(pointer));
+ m_jit.setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(pointer));
return appendCallWithExceptionCheck(operation);
}
JITCompiler::Call callOperation(V_DFGOperation_EJCI operation, GPRReg arg1, GPRReg arg2, Identifier* identifier)
{
- setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(identifier));
+ m_jit.setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(identifier));
return appendCallWithExceptionCheck(operation);
}
JITCompiler::Call callOperation(V_DFGOperation_EJJJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
{
- setupArgumentsWithExecState(arg1, arg2, arg3);
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
return appendCallWithExceptionCheck(operation);
}
JITCompiler::Call callOperation(V_DFGOperation_EPZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
{
- setupArgumentsWithExecState(arg1, arg2, arg3);
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
return appendCallWithExceptionCheck(operation);
}
JITCompiler::Call callOperation(V_DFGOperation_EAZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
{
- setupArgumentsWithExecState(arg1, arg2, arg3);
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
return appendCallWithExceptionCheck(operation);
}
JITCompiler::Call callOperation(V_DFGOperation_ECJJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
{
- setupArgumentsWithExecState(arg1, arg2, arg3);
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
return appendCallWithExceptionCheck(operation);
}
JITCompiler::Call callOperation(D_DFGOperation_EJ operation, FPRReg result, GPRReg arg1)
{
- setupArgumentsWithExecState(arg1);
+ m_jit.setupArgumentsWithExecState(arg1);
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(D_DFGOperation_DD operation, FPRReg result, FPRReg arg1, FPRReg arg2)
{
- setupArguments(arg1, arg2);
+ m_jit.setupArguments(arg1, arg2);
return appendCallSetResult(operation, result);
}
#else
JITCompiler::Call callOperation(Z_DFGOperation_D operation, GPRReg result, FPRReg arg1)
{
- setupArguments(arg1);
+ m_jit.setupArguments(arg1);
JITCompiler::Call call = m_jit.appendCall(operation);
m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, result);
return call;
}
JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg resultTag, GPRReg resultPayload, void* pointer)
{
- setupArgumentsWithExecState(TrustedImmPtr(pointer));
+ m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer));
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_DFGOperation_EPP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, void* pointer)
{
- setupArgumentsWithExecState(arg1, TrustedImmPtr(pointer));
+ m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(pointer));
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_DFGOperation_EGI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, Identifier* identifier)
{
- setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
+ m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1)
{
- setupArgumentsWithExecState(arg1);
+ m_jit.setupArgumentsWithExecState(arg1);
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_DFGOperation_EI operation, GPRReg resultTag, GPRReg resultPayload, Identifier* identifier)
{
- setupArgumentsWithExecState(TrustedImmPtr(identifier));
+ m_jit.setupArgumentsWithExecState(TrustedImmPtr(identifier));
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_DFGOperation_EA operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1)
{
- setupArgumentsWithExecState(arg1);
+ m_jit.setupArgumentsWithExecState(arg1);
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_DFGOperation_EPS operation, GPRReg resultTag, GPRReg resultPayload, void* pointer, size_t size)
{
- setupArgumentsWithExecState(TrustedImmPtr(pointer), TrustedImmPtr(size));
+ m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer), TrustedImmPtr(size));
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_DFGOperation_ESS operation, GPRReg resultTag, GPRReg resultPayload, int startConstant, int numConstants)
{
- setupArgumentsWithExecState(TrustedImm32(startConstant), TrustedImm32(numConstants));
+ m_jit.setupArgumentsWithExecState(TrustedImm32(startConstant), TrustedImm32(numConstants));
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_DFGOperation_EJP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, void* pointer)
{
- setupArgumentsWithExecState(arg1Payload, arg1Tag, ImmPtr(pointer));
+ m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, ImmPtr(pointer));
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_DFGOperation_EJP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2)
{
- setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2);
+ m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2);
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_DFGOperation_ECI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, Identifier* identifier)
{
- setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
+ m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_DFGOperation_EJI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, Identifier* identifier)
{
- setupArgumentsWithExecState(arg1Payload, arg1Tag, TrustedImmPtr(identifier));
+ m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, TrustedImmPtr(identifier));
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_DFGOperation_EJI operation, GPRReg resultTag, GPRReg resultPayload, int32_t arg1Tag, GPRReg arg1Payload, Identifier* identifier)
{
- setupArgumentsWithExecState(arg1Payload, TrustedImm32(arg1Tag), TrustedImmPtr(identifier));
+ m_jit.setupArgumentsWithExecState(arg1Payload, TrustedImm32(arg1Tag), TrustedImmPtr(identifier));
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_DFGOperation_EJA operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2)
{
- setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2);
+ m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2);
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_DFGOperation_EJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload)
{
- setupArgumentsWithExecState(arg1Payload, arg1Tag);
+ m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag);
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(C_DFGOperation_E operation, GPRReg result)
{
- setupArgumentsExecState();
+ m_jit.setupArgumentsExecState();
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(C_DFGOperation_EC operation, GPRReg result, GPRReg arg1)
{
- setupArgumentsWithExecState(arg1);
+ m_jit.setupArgumentsWithExecState(arg1);
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(C_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, JSCell* cell)
{
- setupArgumentsWithExecState(arg1, TrustedImmPtr(cell));
+ m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell));
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(S_DFGOperation_EJ operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload)
{
- setupArgumentsWithExecState(arg1Payload, arg1Tag);
+ m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag);
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(S_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload)
{
- setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2Payload, arg2Tag);
+ m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2Payload, arg2Tag);
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload)
{
- setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2Payload, arg2Tag);
+ m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2Payload, arg2Tag);
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, MacroAssembler::Imm32 imm)
{
- setupArgumentsWithExecState(arg1Payload, arg1Tag, imm, TrustedImm32(JSValue::Int32Tag));
+ m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, imm, TrustedImm32(JSValue::Int32Tag));
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, MacroAssembler::Imm32 imm, GPRReg arg2Tag, GPRReg arg2Payload)
{
- setupArgumentsWithExecState(imm, TrustedImm32(JSValue::Int32Tag), arg2Payload, arg2Tag);
+ m_jit.setupArgumentsWithExecState(imm, TrustedImm32(JSValue::Int32Tag), arg2Payload, arg2Tag);
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_DFGOperation_ECJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload)
{
- setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag);
+ m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag);
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(V_DFGOperation_EJPP operation, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2, void* pointer)
{
- setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2, TrustedImmPtr(pointer));
+ m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2, TrustedImmPtr(pointer));
return appendCallWithExceptionCheck(operation);
}
JITCompiler::Call callOperation(V_DFGOperation_EJCI operation, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2, Identifier* identifier)
{
- setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2, TrustedImmPtr(identifier));
+ m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2, TrustedImmPtr(identifier));
return appendCallWithExceptionCheck(operation);
}
JITCompiler::Call callOperation(V_DFGOperation_ECJJ operation, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload, GPRReg arg3Tag, GPRReg arg3Payload)
{
- setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag, arg3Payload, arg3Tag);
+ m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag, arg3Payload, arg3Tag);
return appendCallWithExceptionCheck(operation);
}
JITCompiler::Call callOperation(V_DFGOperation_EPZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3Tag, GPRReg arg3Payload)
{
- setupArgumentsWithExecState(arg1, arg2, arg3Payload, arg3Tag);
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3Payload, arg3Tag);
return appendCallWithExceptionCheck(operation);
}
JITCompiler::Call callOperation(V_DFGOperation_EAZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3Tag, GPRReg arg3Payload)
{
- setupArgumentsWithExecState(arg1, arg2, arg3Payload, arg3Tag);
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3Payload, arg3Tag);
return appendCallWithExceptionCheck(operation);
}
JITCompiler::Call callOperation(D_DFGOperation_EJ operation, FPRReg result, GPRReg arg1Tag, GPRReg arg1Payload)
{
- setupArgumentsWithExecState(arg1Payload, arg1Tag);
+ m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag);
return appendCallWithExceptionCheckSetResult(operation, result);
}
JITCompiler::Call callOperation(D_DFGOperation_DD operation, FPRReg result, FPRReg arg1, FPRReg arg2)
{
- setupArguments(arg1, arg2);
+ m_jit.setupArguments(arg1, arg2);
return appendCallSetResult(operation, result);
}
#endif
@@ -1834,7 +1393,11 @@ private:
// These methods add call instructions, with optional exception checks & setting results.
JITCompiler::Call appendCallWithExceptionCheck(const FunctionPtr& function)
{
- return m_jit.addExceptionCheck(m_jit.appendCall(function), at(m_compileIndex).codeOrigin);
+ CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin;
+ CallBeginToken token = m_jit.beginCall(codeOrigin);
+ JITCompiler::Call call = m_jit.appendCall(function);
+ m_jit.addExceptionCheck(call, codeOrigin, token);
+ return call;
}
JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, GPRReg result)
{
@@ -1842,26 +1405,10 @@ private:
m_jit.move(GPRInfo::returnValueGPR, result);
return call;
}
- void setupResults(GPRReg destA, GPRReg destB)
- {
- GPRReg srcA = GPRInfo::returnValueGPR;
- GPRReg srcB = GPRInfo::returnValueGPR2;
-
- if (srcB != destA) {
- // Handle the easy cases - two simple moves.
- m_jit.move(srcA, destA);
- m_jit.move(srcB, destB);
- } else if (srcA != destB) {
- // Handle the non-swap case - just put srcB in place first.
- m_jit.move(srcB, destB);
- m_jit.move(srcA, destA);
- } else
- m_jit.swap(destA, destB);
- }
JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, GPRReg result1, GPRReg result2)
{
JITCompiler::Call call = appendCallWithExceptionCheck(function);
- setupResults(result1, result2);
+ m_jit.setupResults(result1, result2);
return call;
}
#if CPU(X86)
@@ -1975,6 +1522,8 @@ private:
void compileUInt32ToNumber(Node&);
void compileGetByValOnByteArray(Node&);
void compilePutByValForByteArray(GPRReg base, GPRReg property, Node&);
+ void compileAdd(Node&);
+ void compileArithSub(Node&);
void compileArithMul(Node&);
void compileArithMod(Node&);
void compileSoftModulo(Node&);
@@ -1988,9 +1537,13 @@ private:
SignedTypedArray,
UnsignedTypedArray
};
+ enum TypedArrayRounding {
+ TruncateRounding,
+ ClampRounding
+ };
void compileGetIndexedPropertyStorage(Node&);
void compileGetByValOnIntTypedArray(const TypedArrayDescriptor&, Node&, size_t elementSize, TypedArraySpeculationRequirements, TypedArraySignedness);
- void compilePutByValForIntTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property, Node&, size_t elementSize, TypedArraySpeculationRequirements, TypedArraySignedness);
+ void compilePutByValForIntTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property, Node&, size_t elementSize, TypedArraySpeculationRequirements, TypedArraySignedness, TypedArrayRounding = TruncateRounding);
void compileGetByValOnFloatTypedArray(const TypedArrayDescriptor&, Node&, size_t elementSize, TypedArraySpeculationRequirements);
void compilePutByValForFloatTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property, Node&, size_t elementSize, TypedArraySpeculationRequirements);
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index d6a82b1cc..e1f92ba9e 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -493,7 +493,7 @@ void SpeculativeJIT::nonSpeculativeUInt32ToNumber(Node& node)
jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
}
-JITCompiler::Call SpeculativeJIT::cachedGetById(GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget)
+JITCompiler::Call SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
{
m_jit.beginUninterruptedSequence();
JITCompiler::DataLabelPtr structureToCompare;
@@ -513,24 +513,26 @@ JITCompiler::Call SpeculativeJIT::cachedGetById(GPRReg baseTagGPROrNone, GPRReg
JITCompiler::Label slowCase = m_jit.label();
- silentSpillAllRegisters(resultTagGPR, resultPayloadGPR);
+ if (spillMode == NeedToSpill)
+ silentSpillAllRegisters(resultTagGPR, resultPayloadGPR);
JITCompiler::Call functionCall;
if (baseTagGPROrNone == InvalidGPRReg)
functionCall = callOperation(operationGetByIdOptimize, resultTagGPR, resultPayloadGPR, JSValue::CellTag, basePayloadGPR, identifier(identifierNumber));
else
functionCall = callOperation(operationGetByIdOptimize, resultTagGPR, resultPayloadGPR, baseTagGPROrNone, basePayloadGPR, identifier(identifierNumber));
- silentFillAllRegisters(resultTagGPR, resultPayloadGPR);
+ if (spillMode == NeedToSpill)
+ silentFillAllRegisters(resultTagGPR, resultPayloadGPR);
done.link(&m_jit);
JITCompiler::Label doneLabel = m_jit.label();
- m_jit.addPropertyAccess(PropertyAccessRecord(structureToCompare, functionCall, structureCheck, tagLoadWithPatch, payloadLoadWithPatch, slowCase, doneLabel, safeCast<int8_t>(basePayloadGPR), safeCast<int8_t>(resultTagGPR), safeCast<int8_t>(resultPayloadGPR), safeCast<int8_t>(scratchGPR)));
+ m_jit.addPropertyAccess(PropertyAccessRecord(codeOrigin, structureToCompare, functionCall, structureCheck, tagLoadWithPatch, payloadLoadWithPatch, slowCase, doneLabel, safeCast<int8_t>(basePayloadGPR), safeCast<int8_t>(resultTagGPR), safeCast<int8_t>(resultPayloadGPR), safeCast<int8_t>(scratchGPR), spillMode == NeedToSpill ? PropertyAccessRecord::RegistersInUse : PropertyAccessRecord::RegistersFlushed));
return functionCall;
}
-void SpeculativeJIT::cachedPutById(GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget)
+void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget)
{
m_jit.beginUninterruptedSequence();
JITCompiler::DataLabelPtr structureToCompare;
@@ -571,7 +573,7 @@ void SpeculativeJIT::cachedPutById(GPRReg basePayloadGPR, GPRReg valueTagGPR, GP
done.link(&m_jit);
JITCompiler::Label doneLabel = m_jit.label();
- m_jit.addPropertyAccess(PropertyAccessRecord(structureToCompare, functionCall, structureCheck, JITCompiler::DataLabelCompact(tagStoreWithPatch.label()), JITCompiler::DataLabelCompact(payloadStoreWithPatch.label()), slowCase, doneLabel, safeCast<int8_t>(basePayloadGPR), safeCast<int8_t>(valueTagGPR), safeCast<int8_t>(valuePayloadGPR), safeCast<int8_t>(scratchGPR)));
+ m_jit.addPropertyAccess(PropertyAccessRecord(codeOrigin, structureToCompare, functionCall, structureCheck, JITCompiler::DataLabelCompact(tagStoreWithPatch.label()), JITCompiler::DataLabelCompact(payloadStoreWithPatch.label()), slowCase, doneLabel, safeCast<int8_t>(basePayloadGPR), safeCast<int8_t>(valueTagGPR), safeCast<int8_t>(valuePayloadGPR), safeCast<int8_t>(scratchGPR)));
}
void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(NodeIndex operand, bool invert)
@@ -950,8 +952,10 @@ void SpeculativeJIT::emitCall(Node& node)
m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
+ CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin;
+ CallBeginToken token = m_jit.nextCallBeginToken(codeOrigin);
JITCompiler::Call fastCall = m_jit.nearCall();
- m_jit.notifyCall(fastCall, at(m_compileIndex).codeOrigin);
+ m_jit.notifyCall(fastCall, codeOrigin, token);
JITCompiler::Jump done = m_jit.jump();
@@ -959,13 +963,17 @@ void SpeculativeJIT::emitCall(Node& node)
m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
m_jit.poke(GPRInfo::argumentGPR0);
- JITCompiler::Call slowCall = m_jit.addFastExceptionCheck(m_jit.appendCall(slowCallFunction), at(m_compileIndex).codeOrigin);
+ token = m_jit.beginCall(codeOrigin);
+ JITCompiler::Call slowCall = m_jit.appendCall(slowCallFunction);
+ m_jit.addFastExceptionCheck(slowCall, codeOrigin, token);
m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
- m_jit.notifyCall(m_jit.call(GPRInfo::returnValueGPR), at(m_compileIndex).codeOrigin);
+ token = m_jit.nextCallBeginToken(codeOrigin);
+ JITCompiler::Call theCall = m_jit.call(GPRInfo::returnValueGPR);
+ m_jit.notifyCall(theCall, codeOrigin, token);
done.link(&m_jit);
- setupResults(resultPayloadGPR, resultTagGPR);
+ m_jit.setupResults(resultPayloadGPR, resultTagGPR);
jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, DataFormatJS, UseChildrenCalledExplicitly);
@@ -1878,133 +1886,17 @@ void SpeculativeJIT::compile(Node& node)
}
case ValueAdd:
- case ArithAdd: {
- if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
- if (isInt32Constant(node.child1())) {
- int32_t imm1 = valueOfInt32Constant(node.child1());
- SpeculateIntegerOperand op2(this, node.child2());
- GPRTemporary result(this);
-
- if (nodeCanTruncateInteger(node.arithNodeFlags())) {
- m_jit.move(op2.gpr(), result.gpr());
- m_jit.add32(Imm32(imm1), result.gpr());
- } else
- speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
-
- integerResult(result.gpr(), m_compileIndex);
- break;
- }
-
- if (isInt32Constant(node.child2())) {
- SpeculateIntegerOperand op1(this, node.child1());
- int32_t imm2 = valueOfInt32Constant(node.child2());
- GPRTemporary result(this);
-
- if (nodeCanTruncateInteger(node.arithNodeFlags())) {
- m_jit.move(op1.gpr(), result.gpr());
- m_jit.add32(Imm32(imm2), result.gpr());
- } else
- speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
-
- integerResult(result.gpr(), m_compileIndex);
- break;
- }
-
- SpeculateIntegerOperand op1(this, node.child1());
- SpeculateIntegerOperand op2(this, node.child2());
- GPRTemporary result(this, op1, op2);
-
- GPRReg gpr1 = op1.gpr();
- GPRReg gpr2 = op2.gpr();
- GPRReg gprResult = result.gpr();
-
- if (nodeCanTruncateInteger(node.arithNodeFlags())) {
- if (gpr1 == gprResult)
- m_jit.add32(gpr2, gprResult);
- else {
- m_jit.move(gpr2, gprResult);
- m_jit.add32(gpr1, gprResult);
- }
- } else {
- MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
-
- if (gpr1 == gprResult)
- speculationCheck(Overflow, JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
- else if (gpr2 == gprResult)
- speculationCheck(Overflow, JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
- else
- speculationCheck(Overflow, JSValueRegs(), NoNode, check);
- }
-
- integerResult(gprResult, m_compileIndex);
- break;
- }
-
- if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
- SpeculateDoubleOperand op1(this, node.child1());
- SpeculateDoubleOperand op2(this, node.child2());
- FPRTemporary result(this, op1, op2);
-
- FPRReg reg1 = op1.fpr();
- FPRReg reg2 = op2.fpr();
- m_jit.addDouble(reg1, reg2, result.fpr());
-
- doubleResult(result.fpr(), m_compileIndex);
- break;
- }
-
- ASSERT(op == ValueAdd);
- compileValueAdd(node);
+ case ArithAdd:
+ compileAdd(node);
break;
- }
-
- case ArithSub: {
- if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
- if (isInt32Constant(node.child2())) {
- SpeculateIntegerOperand op1(this, node.child1());
- int32_t imm2 = valueOfInt32Constant(node.child2());
- GPRTemporary result(this);
-
- if (nodeCanTruncateInteger(node.arithNodeFlags())) {
- m_jit.move(op1.gpr(), result.gpr());
- m_jit.sub32(Imm32(imm2), result.gpr());
- } else
- speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
-
- integerResult(result.gpr(), m_compileIndex);
- break;
- }
-
- SpeculateIntegerOperand op1(this, node.child1());
- SpeculateIntegerOperand op2(this, node.child2());
- GPRTemporary result(this);
- if (nodeCanTruncateInteger(node.arithNodeFlags())) {
- m_jit.move(op1.gpr(), result.gpr());
- m_jit.sub32(op2.gpr(), result.gpr());
- } else
- speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
-
- integerResult(result.gpr(), m_compileIndex);
- break;
- }
-
- SpeculateDoubleOperand op1(this, node.child1());
- SpeculateDoubleOperand op2(this, node.child2());
- FPRTemporary result(this, op1);
-
- FPRReg reg1 = op1.fpr();
- FPRReg reg2 = op2.fpr();
- m_jit.subDouble(reg1, reg2, result.fpr());
-
- doubleResult(result.fpr(), m_compileIndex);
+ case ArithSub:
+ compileArithSub(node);
break;
- }
- case ArithMul: {
+ case ArithMul:
compileArithMul(node);
break;
- }
case ArithDiv: {
if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
@@ -2292,7 +2184,14 @@ void SpeculativeJIT::compile(Node& node)
return;
break;
}
-
+
+ if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
+ compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, sizeof(uint8_t), isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ if (!m_compileOkay)
+ return;
+ break;
+ }
+
if (at(node.child1()).shouldSpeculateUint16Array()) {
compileGetByValOnIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), node, sizeof(uint16_t), isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
@@ -2417,6 +2316,13 @@ void SpeculativeJIT::compile(Node& node)
break;
}
+ if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray, ClampRounding);
+ if (!m_compileOkay)
+ return;
+ break;
+ }
+
if (at(node.child1()).shouldSpeculateUint16Array()) {
compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
@@ -2552,7 +2458,14 @@ void SpeculativeJIT::compile(Node& node)
return;
break;
}
-
+
+ if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), NoTypedArraySpecCheck, UnsignedTypedArray, ClampRounding);
+ if (!m_compileOkay)
+ return;
+ break;
+ }
+
if (at(node.child1()).shouldSpeculateUint16Array()) {
compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), NoTypedArraySpecCheck, UnsignedTypedArray);
if (!m_compileOkay)
@@ -3126,7 +3039,7 @@ void SpeculativeJIT::compile(Node& node)
base.use();
- cachedGetById(InvalidGPRReg, baseGPR, resultTagGPR, resultPayloadGPR, scratchGPR, node.identifierNumber());
+ cachedGetById(node.codeOrigin, InvalidGPRReg, baseGPR, resultTagGPR, resultPayloadGPR, scratchGPR, node.identifierNumber());
jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
break;
@@ -3151,7 +3064,58 @@ void SpeculativeJIT::compile(Node& node)
JITCompiler::Jump notCell = m_jit.branch32(JITCompiler::NotEqual, baseTagGPR, TrustedImm32(JSValue::CellTag));
- cachedGetById(baseTagGPR, basePayloadGPR, resultTagGPR, resultPayloadGPR, scratchGPR, node.identifierNumber(), notCell);
+ cachedGetById(node.codeOrigin, baseTagGPR, basePayloadGPR, resultTagGPR, resultPayloadGPR, scratchGPR, node.identifierNumber(), notCell);
+
+ jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
+ break;
+ }
+
+ case GetByIdFlush: {
+ if (!node.prediction()) {
+ terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+ break;
+ }
+
+ if (isCellPrediction(at(node.child1()).prediction())) {
+ SpeculateCellOperand base(this, node.child1());
+
+ GPRReg baseGPR = base.gpr();
+
+ GPRResult resultTag(this);
+ GPRResult2 resultPayload(this);
+ GPRReg resultTagGPR = resultTag.gpr();
+ GPRReg resultPayloadGPR = resultPayload.gpr();
+
+ GPRReg scratchGPR = selectScratchGPR(baseGPR, resultTagGPR, resultPayloadGPR);
+
+ base.use();
+
+ flushRegisters();
+
+ cachedGetById(node.codeOrigin, InvalidGPRReg, baseGPR, resultTagGPR, resultPayloadGPR, scratchGPR, node.identifierNumber(), JITCompiler::Jump(), DontSpill);
+
+ jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
+ break;
+ }
+
+ JSValueOperand base(this, node.child1());
+ GPRReg baseTagGPR = base.tagGPR();
+ GPRReg basePayloadGPR = base.payloadGPR();
+
+ GPRResult resultTag(this);
+ GPRResult2 resultPayload(this);
+ GPRReg resultTagGPR = resultTag.gpr();
+ GPRReg resultPayloadGPR = resultPayload.gpr();
+
+ GPRReg scratchGPR = selectScratchGPR(baseTagGPR, basePayloadGPR, resultTagGPR, resultPayloadGPR);
+
+ base.use();
+
+ flushRegisters();
+
+ JITCompiler::Jump notCell = m_jit.branch32(JITCompiler::NotEqual, baseTagGPR, TrustedImm32(JSValue::CellTag));
+
+ cachedGetById(node.codeOrigin, baseTagGPR, basePayloadGPR, resultTagGPR, resultPayloadGPR, scratchGPR, node.identifierNumber(), notCell, DontSpill);
jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
break;
@@ -3224,6 +3188,10 @@ void SpeculativeJIT::compile(Node& node)
compileGetTypedArrayLength(m_jit.globalData()->uint8ArrayDescriptor(), node, !isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type));
break;
}
+ case GetUint8ClampedArrayLength: {
+ compileGetTypedArrayLength(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, !isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type));
+ break;
+ }
case GetUint16ArrayLength: {
compileGetTypedArrayLength(m_jit.globalData()->uint16ArrayDescriptor(), node, !isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type));
break;
@@ -3372,7 +3340,7 @@ void SpeculativeJIT::compile(Node& node)
base.use();
value.use();
- cachedPutById(baseGPR, valueTagGPR, valuePayloadGPR, node.child2(), scratchGPR, node.identifierNumber(), NotDirect);
+ cachedPutById(node.codeOrigin, baseGPR, valueTagGPR, valuePayloadGPR, node.child2(), scratchGPR, node.identifierNumber(), NotDirect);
noResult(m_compileIndex, UseChildrenCalledExplicitly);
break;
@@ -3391,7 +3359,7 @@ void SpeculativeJIT::compile(Node& node)
base.use();
value.use();
- cachedPutById(baseGPR, valueTagGPR, valuePayloadGPR, node.child2(), scratchGPR, node.identifierNumber(), Direct);
+ cachedPutById(node.codeOrigin, baseGPR, valueTagGPR, valuePayloadGPR, node.child2(), scratchGPR, node.identifierNumber(), Direct);
noResult(m_compileIndex, UseChildrenCalledExplicitly);
break;
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index 7e36165f3..139dedded 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -477,7 +477,7 @@ void SpeculativeJIT::nonSpeculativeUInt32ToNumber(Node& node)
jsValueResult(result.gpr(), m_compileIndex);
}
-JITCompiler::Call SpeculativeJIT::cachedGetById(GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget)
+JITCompiler::Call SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
{
JITCompiler::DataLabelPtr structureToCompare;
JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
@@ -494,23 +494,25 @@ JITCompiler::Call SpeculativeJIT::cachedGetById(GPRReg baseGPR, GPRReg resultGPR
JITCompiler::Label slowCase = m_jit.label();
- silentSpillAllRegisters(resultGPR);
+ if (spillMode == NeedToSpill)
+ silentSpillAllRegisters(resultGPR);
JITCompiler::Call functionCall = callOperation(operationGetByIdOptimize, resultGPR, baseGPR, identifier(identifierNumber));
- silentFillAllRegisters(resultGPR);
+ if (spillMode == NeedToSpill)
+ silentFillAllRegisters(resultGPR);
done.link(&m_jit);
JITCompiler::Label doneLabel = m_jit.label();
- m_jit.addPropertyAccess(PropertyAccessRecord(structureToCompare, functionCall, structureCheck, loadWithPatch, slowCase, doneLabel, safeCast<int8_t>(baseGPR), safeCast<int8_t>(resultGPR), safeCast<int8_t>(scratchGPR)));
+ m_jit.addPropertyAccess(PropertyAccessRecord(codeOrigin, structureToCompare, functionCall, structureCheck, loadWithPatch, slowCase, doneLabel, safeCast<int8_t>(baseGPR), safeCast<int8_t>(resultGPR), safeCast<int8_t>(scratchGPR), spillMode == NeedToSpill ? PropertyAccessRecord::RegistersInUse : PropertyAccessRecord::RegistersFlushed));
- if (scratchGPR != resultGPR && scratchGPR != InvalidGPRReg)
+ if (scratchGPR != resultGPR && scratchGPR != InvalidGPRReg && spillMode == NeedToSpill)
unlock(scratchGPR);
return functionCall;
}
-void SpeculativeJIT::cachedPutById(GPRReg baseGPR, GPRReg valueGPR, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget)
+void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg valueGPR, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget)
{
JITCompiler::DataLabelPtr structureToCompare;
@@ -549,7 +551,7 @@ void SpeculativeJIT::cachedPutById(GPRReg baseGPR, GPRReg valueGPR, NodeIndex va
done.link(&m_jit);
JITCompiler::Label doneLabel = m_jit.label();
- m_jit.addPropertyAccess(PropertyAccessRecord(structureToCompare, functionCall, structureCheck, JITCompiler::DataLabelCompact(storeWithPatch.label()), slowCase, doneLabel, safeCast<int8_t>(baseGPR), safeCast<int8_t>(valueGPR), safeCast<int8_t>(scratchGPR)));
+ m_jit.addPropertyAccess(PropertyAccessRecord(codeOrigin, structureToCompare, functionCall, structureCheck, JITCompiler::DataLabelCompact(storeWithPatch.label()), slowCase, doneLabel, safeCast<int8_t>(baseGPR), safeCast<int8_t>(valueGPR), safeCast<int8_t>(scratchGPR)));
}
void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(NodeIndex operand, bool invert)
@@ -951,17 +953,23 @@ void SpeculativeJIT::emitCall(Node& node)
m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
+ CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin;
+ CallBeginToken token = m_jit.nextCallBeginToken(codeOrigin);
JITCompiler::Call fastCall = m_jit.nearCall();
- m_jit.notifyCall(fastCall, at(m_compileIndex).codeOrigin);
+ m_jit.notifyCall(fastCall, codeOrigin, token);
JITCompiler::Jump done = m_jit.jump();
slowPath.link(&m_jit);
m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- JITCompiler::Call slowCall = m_jit.addFastExceptionCheck(m_jit.appendCall(slowCallFunction), at(m_compileIndex).codeOrigin);
+ token = m_jit.beginCall(codeOrigin);
+ JITCompiler::Call slowCall = m_jit.appendCall(slowCallFunction);
+ m_jit.addFastExceptionCheck(slowCall, codeOrigin, token);
m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
- m_jit.notifyCall(m_jit.call(GPRInfo::returnValueGPR), at(m_compileIndex).codeOrigin);
+ token = m_jit.nextCallBeginToken(codeOrigin);
+ JITCompiler::Call theCall = m_jit.call(GPRInfo::returnValueGPR);
+ m_jit.notifyCall(theCall, codeOrigin, token);
done.link(&m_jit);
@@ -1957,133 +1965,17 @@ void SpeculativeJIT::compile(Node& node)
}
case ValueAdd:
- case ArithAdd: {
- if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
- if (isInt32Constant(node.child1())) {
- int32_t imm1 = valueOfInt32Constant(node.child1());
- SpeculateIntegerOperand op2(this, node.child2());
- GPRTemporary result(this);
-
- if (nodeCanTruncateInteger(node.arithNodeFlags())) {
- m_jit.move(op2.gpr(), result.gpr());
- m_jit.add32(Imm32(imm1), result.gpr());
- } else
- speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
-
- integerResult(result.gpr(), m_compileIndex);
- break;
- }
-
- if (isInt32Constant(node.child2())) {
- SpeculateIntegerOperand op1(this, node.child1());
- int32_t imm2 = valueOfInt32Constant(node.child2());
- GPRTemporary result(this);
-
- if (nodeCanTruncateInteger(node.arithNodeFlags())) {
- m_jit.move(op1.gpr(), result.gpr());
- m_jit.add32(Imm32(imm2), result.gpr());
- } else
- speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
-
- integerResult(result.gpr(), m_compileIndex);
- break;
- }
-
- SpeculateIntegerOperand op1(this, node.child1());
- SpeculateIntegerOperand op2(this, node.child2());
- GPRTemporary result(this, op1, op2);
-
- GPRReg gpr1 = op1.gpr();
- GPRReg gpr2 = op2.gpr();
- GPRReg gprResult = result.gpr();
-
- if (nodeCanTruncateInteger(node.arithNodeFlags())) {
- if (gpr1 == gprResult)
- m_jit.add32(gpr2, gprResult);
- else {
- m_jit.move(gpr2, gprResult);
- m_jit.add32(gpr1, gprResult);
- }
- } else {
- MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
-
- if (gpr1 == gprResult)
- speculationCheck(Overflow, JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
- else if (gpr2 == gprResult)
- speculationCheck(Overflow, JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
- else
- speculationCheck(Overflow, JSValueRegs(), NoNode, check);
- }
-
- integerResult(gprResult, m_compileIndex);
- break;
- }
-
- if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
- SpeculateDoubleOperand op1(this, node.child1());
- SpeculateDoubleOperand op2(this, node.child2());
- FPRTemporary result(this, op1, op2);
-
- FPRReg reg1 = op1.fpr();
- FPRReg reg2 = op2.fpr();
- m_jit.addDouble(reg1, reg2, result.fpr());
-
- doubleResult(result.fpr(), m_compileIndex);
- break;
- }
-
- ASSERT(op == ValueAdd);
- compileValueAdd(node);
+ case ArithAdd:
+ compileAdd(node);
break;
- }
-
- case ArithSub: {
- if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
- if (isInt32Constant(node.child2())) {
- SpeculateIntegerOperand op1(this, node.child1());
- int32_t imm2 = valueOfInt32Constant(node.child2());
- GPRTemporary result(this);
-
- if (nodeCanTruncateInteger(node.arithNodeFlags())) {
- m_jit.move(op1.gpr(), result.gpr());
- m_jit.sub32(Imm32(imm2), result.gpr());
- } else
- speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
-
- integerResult(result.gpr(), m_compileIndex);
- break;
- }
-
- SpeculateIntegerOperand op1(this, node.child1());
- SpeculateIntegerOperand op2(this, node.child2());
- GPRTemporary result(this);
-
- if (nodeCanTruncateInteger(node.arithNodeFlags())) {
- m_jit.move(op1.gpr(), result.gpr());
- m_jit.sub32(op2.gpr(), result.gpr());
- } else
- speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
- integerResult(result.gpr(), m_compileIndex);
- break;
- }
-
- SpeculateDoubleOperand op1(this, node.child1());
- SpeculateDoubleOperand op2(this, node.child2());
- FPRTemporary result(this, op1);
-
- FPRReg reg1 = op1.fpr();
- FPRReg reg2 = op2.fpr();
- m_jit.subDouble(reg1, reg2, result.fpr());
-
- doubleResult(result.fpr(), m_compileIndex);
+ case ArithSub:
+ compileArithSub(node);
break;
- }
- case ArithMul: {
+ case ArithMul:
compileArithMul(node);
break;
- }
case ArithDiv: {
if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
@@ -2346,7 +2238,14 @@ void SpeculativeJIT::compile(Node& node)
return;
break;
}
-
+
+ if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
+ compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, sizeof(uint8_t), isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+ if (!m_compileOkay)
+ return;
+ break;
+ }
+
if (at(node.child1()).shouldSpeculateUint16Array()) {
compileGetByValOnIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), node, sizeof(uint16_t), isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
@@ -2458,7 +2357,12 @@ void SpeculativeJIT::compile(Node& node)
return;
break;
}
-
+
+ if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray, ClampRounding);
+ break;
+ }
+
if (at(node.child1()).shouldSpeculateUint16Array()) {
compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
if (!m_compileOkay)
@@ -2591,7 +2495,14 @@ void SpeculativeJIT::compile(Node& node)
return;
break;
}
-
+
+ if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
+ compilePutByValForIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), NoTypedArraySpecCheck, UnsignedTypedArray, ClampRounding);
+ if (!m_compileOkay)
+ return;
+ break;
+ }
+
if (at(node.child1()).shouldSpeculateUint16Array()) {
compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), NoTypedArraySpecCheck, UnsignedTypedArray);
if (!m_compileOkay)
@@ -3123,7 +3034,7 @@ void SpeculativeJIT::compile(Node& node)
base.use();
- cachedGetById(baseGPR, resultGPR, scratchGPR, node.identifierNumber());
+ cachedGetById(node.codeOrigin, baseGPR, resultGPR, scratchGPR, node.identifierNumber());
jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
break;
@@ -3145,7 +3056,53 @@ void SpeculativeJIT::compile(Node& node)
JITCompiler::Jump notCell = m_jit.branchTestPtr(JITCompiler::NonZero, baseGPR, GPRInfo::tagMaskRegister);
- cachedGetById(baseGPR, resultGPR, scratchGPR, node.identifierNumber(), notCell);
+ cachedGetById(node.codeOrigin, baseGPR, resultGPR, scratchGPR, node.identifierNumber(), notCell);
+
+ jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
+
+ break;
+ }
+
+ case GetByIdFlush: {
+ if (!node.prediction()) {
+ terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+ break;
+ }
+
+ if (isCellPrediction(at(node.child1()).prediction())) {
+ SpeculateCellOperand base(this, node.child1());
+ GPRReg baseGPR = base.gpr();
+
+ GPRResult result(this);
+
+ GPRReg resultGPR = result.gpr();
+
+ GPRReg scratchGPR = selectScratchGPR(baseGPR, resultGPR);
+
+ base.use();
+
+ flushRegisters();
+
+ cachedGetById(node.codeOrigin, baseGPR, resultGPR, scratchGPR, node.identifierNumber(), JITCompiler::Jump(), DontSpill);
+
+ jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
+ break;
+ }
+
+ JSValueOperand base(this, node.child1());
+ GPRReg baseGPR = base.gpr();
+
+ GPRResult result(this);
+ GPRReg resultGPR = result.gpr();
+
+ GPRReg scratchGPR = selectScratchGPR(baseGPR, resultGPR);
+
+ base.use();
+ flushRegisters();
+
+ JITCompiler::Jump notCell = m_jit.branchTestPtr(JITCompiler::NonZero, baseGPR, GPRInfo::tagMaskRegister);
+
+ cachedGetById(node.codeOrigin, baseGPR, resultGPR, scratchGPR, node.identifierNumber(), notCell, DontSpill);
jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
@@ -3219,6 +3176,10 @@ void SpeculativeJIT::compile(Node& node)
compileGetTypedArrayLength(m_jit.globalData()->uint8ArrayDescriptor(), node, !isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type));
break;
}
+ case GetUint8ClampedArrayLength: {
+ compileGetTypedArrayLength(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, !isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type));
+ break;
+ }
case GetUint16ArrayLength: {
compileGetTypedArrayLength(m_jit.globalData()->uint16ArrayDescriptor(), node, !isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type));
break;
@@ -3359,7 +3320,7 @@ void SpeculativeJIT::compile(Node& node)
base.use();
value.use();
- cachedPutById(baseGPR, valueGPR, node.child2(), scratchGPR, node.identifierNumber(), NotDirect);
+ cachedPutById(node.codeOrigin, baseGPR, valueGPR, node.child2(), scratchGPR, node.identifierNumber(), NotDirect);
noResult(m_compileIndex, UseChildrenCalledExplicitly);
break;
@@ -3377,7 +3338,7 @@ void SpeculativeJIT::compile(Node& node)
base.use();
value.use();
- cachedPutById(baseGPR, valueGPR, node.child2(), scratchGPR, node.identifierNumber(), Direct);
+ cachedPutById(node.codeOrigin, baseGPR, valueGPR, node.child2(), scratchGPR, node.identifierNumber(), Direct);
noResult(m_compileIndex, UseChildrenCalledExplicitly);
break;
diff --git a/Source/JavaScriptCore/dfg/DFGThunks.cpp b/Source/JavaScriptCore/dfg/DFGThunks.cpp
index fddb656cc..d7c3fab23 100644
--- a/Source/JavaScriptCore/dfg/DFGThunks.cpp
+++ b/Source/JavaScriptCore/dfg/DFGThunks.cpp
@@ -66,7 +66,7 @@ MacroAssemblerCodeRef osrExitGenerationThunkGenerator(JSGlobalData* globalData)
jit.jump(MacroAssembler::AbsoluteAddress(&globalData->osrExitJumpDestination));
- LinkBuffer patchBuffer(*globalData, &jit);
+ LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
patchBuffer.link(functionCall, compileOSRExit);
diff --git a/Source/JavaScriptCore/heap/AllocationSpace.cpp b/Source/JavaScriptCore/heap/AllocationSpace.cpp
deleted file mode 100644
index e363de274..000000000
--- a/Source/JavaScriptCore/heap/AllocationSpace.cpp
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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 "AllocationSpace.h"
-
-#include "Heap.h"
-
-#define COLLECT_ON_EVERY_ALLOCATION 0
-
-namespace JSC {
-
-inline void* AllocationSpace::tryAllocate(MarkedSpace::SizeClass& sizeClass)
-{
- m_heap->m_operationInProgress = Allocation;
- void* result = m_markedSpace.allocate(sizeClass);
- m_heap->m_operationInProgress = NoOperation;
- return result;
-}
-
-void* AllocationSpace::allocateSlowCase(MarkedSpace::SizeClass& sizeClass)
-{
-#if COLLECT_ON_EVERY_ALLOCATION
- m_heap->collectAllGarbage();
- ASSERT(m_heap->m_operationInProgress == NoOperation);
-#endif
-
- void* result = tryAllocate(sizeClass);
-
- if (LIKELY(result != 0))
- return result;
-
- AllocationEffort allocationEffort;
-
- if ((
-#if ENABLE(GGC)
- m_markedSpace.nurseryWaterMark() < m_heap->m_minBytesPerCycle
-#else
- m_markedSpace.waterMark() < m_markedSpace.highWaterMark()
-#endif
- ) || !m_heap->m_isSafeToCollect)
- allocationEffort = AllocationMustSucceed;
- else
- allocationEffort = AllocationCanFail;
-
- MarkedBlock* block = allocateBlock(sizeClass.cellSize, allocationEffort);
- if (block) {
- m_markedSpace.addBlock(sizeClass, block);
- void* result = tryAllocate(sizeClass);
- ASSERT(result);
- return result;
- }
-
- m_heap->collect(Heap::DoNotSweep);
-
- result = tryAllocate(sizeClass);
-
- if (result)
- return result;
-
- ASSERT(m_markedSpace.waterMark() < m_markedSpace.highWaterMark());
-
- m_markedSpace.addBlock(sizeClass, allocateBlock(sizeClass.cellSize, AllocationMustSucceed));
-
- result = tryAllocate(sizeClass);
- ASSERT(result);
- return result;
-}
-
-MarkedBlock* AllocationSpace::allocateBlock(size_t cellSize, AllocationSpace::AllocationEffort allocationEffort)
-{
- MarkedBlock* block;
-
- {
- MutexLocker locker(m_heap->m_freeBlockLock);
- if (m_heap->m_numberOfFreeBlocks) {
- block = m_heap->m_freeBlocks.removeHead();
- ASSERT(block);
- m_heap->m_numberOfFreeBlocks--;
- } else
- block = 0;
- }
- if (block)
- block = MarkedBlock::recycle(block, cellSize);
- else if (allocationEffort == AllocationCanFail)
- return 0;
- else
- block = MarkedBlock::create(m_heap, cellSize);
-
- m_blocks.add(block);
-
- return block;
-}
-
-void AllocationSpace::freeBlocks(MarkedBlock* head)
-{
- MarkedBlock* next;
- for (MarkedBlock* block = head; block; block = next) {
- next = block->next();
-
- m_blocks.remove(block);
- block->sweep();
- MutexLocker locker(m_heap->m_freeBlockLock);
- m_heap->m_freeBlocks.append(block);
- m_heap->m_numberOfFreeBlocks++;
- }
-}
-
-class TakeIfUnmarked {
-public:
- typedef MarkedBlock* ReturnType;
-
- TakeIfUnmarked(MarkedSpace*);
- void operator()(MarkedBlock*);
- ReturnType returnValue();
-
-private:
- MarkedSpace* m_markedSpace;
- DoublyLinkedList<MarkedBlock> m_empties;
-};
-
-inline TakeIfUnmarked::TakeIfUnmarked(MarkedSpace* newSpace)
- : m_markedSpace(newSpace)
-{
-}
-
-inline void TakeIfUnmarked::operator()(MarkedBlock* block)
-{
- if (!block->markCountIsZero())
- return;
-
- m_markedSpace->removeBlock(block);
- m_empties.append(block);
-}
-
-inline TakeIfUnmarked::ReturnType TakeIfUnmarked::returnValue()
-{
- return m_empties.head();
-}
-
-void AllocationSpace::shrink()
-{
- // We record a temporary list of empties to avoid modifying m_blocks while iterating it.
- TakeIfUnmarked takeIfUnmarked(&m_markedSpace);
- freeBlocks(forEachBlock(takeIfUnmarked));
-}
-
-#if ENABLE(GGC)
-class GatherDirtyCells {
- WTF_MAKE_NONCOPYABLE(GatherDirtyCells);
-public:
- typedef void* ReturnType;
-
- explicit GatherDirtyCells(MarkedBlock::DirtyCellVector*);
- void operator()(MarkedBlock*);
- ReturnType returnValue() { return 0; }
-
-private:
- MarkedBlock::DirtyCellVector* m_dirtyCells;
-};
-
-inline GatherDirtyCells::GatherDirtyCells(MarkedBlock::DirtyCellVector* dirtyCells)
- : m_dirtyCells(dirtyCells)
-{
-}
-
-inline void GatherDirtyCells::operator()(MarkedBlock* block)
-{
- block->gatherDirtyCells(*m_dirtyCells);
-}
-
-void AllocationSpace::gatherDirtyCells(MarkedBlock::DirtyCellVector& dirtyCells)
-{
- GatherDirtyCells gatherDirtyCells(&dirtyCells);
- forEachBlock(gatherDirtyCells);
-}
-#endif
-
-}
diff --git a/Source/JavaScriptCore/heap/AllocationSpace.h b/Source/JavaScriptCore/heap/AllocationSpace.h
deleted file mode 100644
index 550cb9aa3..000000000
--- a/Source/JavaScriptCore/heap/AllocationSpace.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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 AllocationSpace_h
-#define AllocationSpace_h
-
-#include "MarkedBlockSet.h"
-#include "MarkedSpace.h"
-
-#include <wtf/HashSet.h>
-
-namespace JSC {
-
-class Heap;
-class MarkedBlock;
-
-class AllocationSpace {
-public:
- AllocationSpace(Heap* heap)
- : m_heap(heap)
- , m_markedSpace(heap)
- {
- }
-
- typedef HashSet<MarkedBlock*>::iterator BlockIterator;
-
- MarkedBlockSet& blocks() { return m_blocks; }
- MarkedSpace::SizeClass& sizeClassFor(size_t bytes) { return m_markedSpace.sizeClassFor(bytes); }
- void setHighWaterMark(size_t bytes) { m_markedSpace.setHighWaterMark(bytes); }
- size_t highWaterMark() { return m_markedSpace.highWaterMark(); }
-
-#if ENABLE(GGC)
- void gatherDirtyCells(MarkedBlock::DirtyCellVector&);
-#endif
-
- template<typename Functor> typename Functor::ReturnType forEachCell(Functor&);
- template<typename Functor> typename Functor::ReturnType forEachCell();
- template<typename Functor> typename Functor::ReturnType forEachBlock(Functor&);
- template<typename Functor> typename Functor::ReturnType forEachBlock();
-
- void canonicalizeCellLivenessData() { m_markedSpace.canonicalizeCellLivenessData(); }
- void resetAllocator() { m_markedSpace.resetAllocator(); }
-
- void* allocate(size_t);
- void freeBlocks(MarkedBlock*);
- void shrink();
-
-private:
- enum AllocationEffort { AllocationMustSucceed, AllocationCanFail };
-
- void* allocate(MarkedSpace::SizeClass&);
- void* tryAllocate(MarkedSpace::SizeClass&);
- void* allocateSlowCase(MarkedSpace::SizeClass&);
- MarkedBlock* allocateBlock(size_t cellSize, AllocationEffort);
-
- Heap* m_heap;
- MarkedSpace m_markedSpace;
- MarkedBlockSet m_blocks;
-};
-
-template<typename Functor> inline typename Functor::ReturnType AllocationSpace::forEachCell(Functor& functor)
-{
- canonicalizeCellLivenessData();
-
- BlockIterator end = m_blocks.set().end();
- for (BlockIterator it = m_blocks.set().begin(); it != end; ++it)
- (*it)->forEachCell(functor);
- return functor.returnValue();
-}
-
-template<typename Functor> inline typename Functor::ReturnType AllocationSpace::forEachCell()
-{
- Functor functor;
- return forEachCell(functor);
-}
-
-template<typename Functor> inline typename Functor::ReturnType AllocationSpace::forEachBlock(Functor& functor)
-{
- BlockIterator end = m_blocks.set().end();
- for (BlockIterator it = m_blocks.set().begin(); it != end; ++it)
- functor(*it);
- return functor.returnValue();
-}
-
-template<typename Functor> inline typename Functor::ReturnType AllocationSpace::forEachBlock()
-{
- Functor functor;
- return forEachBlock(functor);
-}
-
-inline void* AllocationSpace::allocate(MarkedSpace::SizeClass& sizeClass)
-{
- // This is a light-weight fast path to cover the most common case.
- MarkedBlock::FreeCell* firstFreeCell = sizeClass.firstFreeCell;
- if (UNLIKELY(!firstFreeCell))
- return allocateSlowCase(sizeClass);
-
- sizeClass.firstFreeCell = firstFreeCell->next;
- return firstFreeCell;
-}
-
-inline void* AllocationSpace::allocate(size_t bytes)
-{
- MarkedSpace::SizeClass& sizeClass = sizeClassFor(bytes);
- return allocate(sizeClass);
-}
-
-}
-
-#endif
diff --git a/Source/JavaScriptCore/heap/BumpBlock.h b/Source/JavaScriptCore/heap/BumpBlock.h
new file mode 100644
index 000000000..b9f271ca8
--- /dev/null
+++ b/Source/JavaScriptCore/heap/BumpBlock.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 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 BumpBlock_h
+#define BumpBlock_h
+
+#include "HeapBlock.h"
+
+namespace JSC {
+
+class BumpSpace;
+
+class BumpBlock : public HeapBlock {
+ friend class BumpSpace;
+public:
+ BumpBlock(PageAllocationAligned& allocation)
+ : HeapBlock(allocation)
+ , m_offset(m_payload)
+ , m_isPinned(false)
+ {
+ }
+
+private:
+ void* m_offset;
+ uintptr_t m_isPinned;
+ char m_payload[1];
+};
+
+} // namespace JSC
+
+#endif
diff --git a/Source/JavaScriptCore/heap/BumpSpace.cpp b/Source/JavaScriptCore/heap/BumpSpace.cpp
new file mode 100644
index 000000000..4eb0284dd
--- /dev/null
+++ b/Source/JavaScriptCore/heap/BumpSpace.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011 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 "BumpSpace.h"
+
+#include "BumpSpaceInlineMethods.h"
+
+namespace JSC {
+
+CheckedBoolean BumpSpace::tryAllocateSlowCase(size_t bytes, void** outPtr)
+{
+ if (isOversize(bytes))
+ return tryAllocateOversize(bytes, outPtr);
+
+ m_totalMemoryUtilized += static_cast<size_t>(static_cast<char*>(m_currentBlock->m_offset) - m_currentBlock->m_payload);
+ if (!addNewBlock()) {
+ *outPtr = 0;
+ return false;
+ }
+ m_toSpaceFilter.add(reinterpret_cast<Bits>(m_currentBlock));
+ m_toSpaceSet.add(m_currentBlock);
+ *outPtr = allocateFromBlock(m_currentBlock, bytes);
+ return true;
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/heap/BumpSpace.h b/Source/JavaScriptCore/heap/BumpSpace.h
new file mode 100644
index 000000000..30e6b74fe
--- /dev/null
+++ b/Source/JavaScriptCore/heap/BumpSpace.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2011 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 BumpSpace_h
+#define BumpSpace_h
+
+#include "HeapBlock.h"
+#include "TinyBloomFilter.h"
+#include <wtf/Assertions.h>
+#include <wtf/CheckedBoolean.h>
+#include <wtf/DoublyLinkedList.h>
+#include <wtf/HashSet.h>
+#include <wtf/OSAllocator.h>
+#include <wtf/PageAllocationAligned.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/ThreadingPrimitives.h>
+
+namespace JSC {
+
+class Heap;
+class BumpBlock;
+class HeapBlock;
+
+class BumpSpace {
+ friend class SlotVisitor;
+public:
+ BumpSpace(Heap*);
+ void init();
+
+ CheckedBoolean tryAllocate(size_t, void**);
+ CheckedBoolean tryReallocate(void**, size_t, size_t);
+
+ void startedCopying();
+ void doneCopying();
+ bool isInCopyPhase() { return m_inCopyingPhase; }
+
+ void pin(BumpBlock*);
+ bool isPinned(void*);
+
+ bool contains(void*, BumpBlock*&);
+
+ size_t totalMemoryAllocated() { return m_totalMemoryAllocated; }
+ size_t totalMemoryUtilized() { return m_totalMemoryUtilized; }
+
+ static BumpBlock* blockFor(void*);
+
+private:
+ CheckedBoolean tryAllocateSlowCase(size_t, void**);
+ CheckedBoolean addNewBlock();
+ CheckedBoolean allocateNewBlock(BumpBlock**);
+ bool fitsInCurrentBlock(size_t);
+
+ static void* allocateFromBlock(BumpBlock*, size_t);
+ CheckedBoolean tryAllocateOversize(size_t, void**);
+ CheckedBoolean tryReallocateOversize(void**, size_t, size_t);
+
+ static bool isOversize(size_t);
+
+ CheckedBoolean borrowBlock(BumpBlock**);
+ CheckedBoolean getFreshBlock(AllocationEffort, BumpBlock**);
+ void doneFillingBlock(BumpBlock*);
+ void recycleBlock(BumpBlock*);
+ static bool fitsInBlock(BumpBlock*, size_t);
+ static BumpBlock* oversizeBlockFor(void* ptr);
+
+ Heap* m_heap;
+
+ BumpBlock* m_currentBlock;
+
+ TinyBloomFilter m_toSpaceFilter;
+ TinyBloomFilter m_oversizeFilter;
+ HashSet<BumpBlock*> m_toSpaceSet;
+
+ Mutex m_toSpaceLock;
+ Mutex m_memoryStatsLock;
+
+ DoublyLinkedList<HeapBlock>* m_toSpace;
+ DoublyLinkedList<HeapBlock>* m_fromSpace;
+
+ DoublyLinkedList<HeapBlock> m_blocks1;
+ DoublyLinkedList<HeapBlock> m_blocks2;
+ DoublyLinkedList<HeapBlock> m_oversizeBlocks;
+
+ size_t m_totalMemoryAllocated;
+ size_t m_totalMemoryUtilized;
+
+ bool m_inCopyingPhase;
+
+ Mutex m_loanedBlocksLock;
+ ThreadCondition m_loanedBlocksCondition;
+ size_t m_numberOfLoanedBlocks;
+
+ static const size_t s_blockSize = 64 * KB;
+ static const size_t s_maxAllocationSize = 32 * KB;
+ static const size_t s_pageSize = 4 * KB;
+ static const size_t s_pageMask = ~(s_pageSize - 1);
+ static const size_t s_initialBlockNum = 16;
+ static const size_t s_blockMask = ~(s_blockSize - 1);
+};
+
+} // namespace JSC
+
+#endif
diff --git a/Source/JavaScriptCore/heap/BumpSpaceInlineMethods.h b/Source/JavaScriptCore/heap/BumpSpaceInlineMethods.h
new file mode 100644
index 000000000..3454631b0
--- /dev/null
+++ b/Source/JavaScriptCore/heap/BumpSpaceInlineMethods.h
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2011 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 BumpSpaceInlineMethods_h
+#define BumpSpaceInlineMethods_h
+
+#include "BumpBlock.h"
+#include "BumpSpace.h"
+#include "Heap.h"
+#include "HeapBlock.h"
+#include "JSGlobalData.h"
+#include <wtf/CheckedBoolean.h>
+
+namespace JSC {
+
+inline BumpSpace::BumpSpace(Heap* heap)
+ : m_heap(heap)
+ , m_currentBlock(0)
+ , m_toSpace(0)
+ , m_fromSpace(0)
+ , m_totalMemoryAllocated(0)
+ , m_totalMemoryUtilized(0)
+ , m_inCopyingPhase(false)
+ , m_numberOfLoanedBlocks(0)
+{
+}
+
+inline void BumpSpace::init()
+{
+ m_toSpace = &m_blocks1;
+ m_fromSpace = &m_blocks2;
+
+ m_totalMemoryAllocated += s_blockSize * s_initialBlockNum;
+
+ if (!addNewBlock())
+ CRASH();
+}
+
+inline bool BumpSpace::contains(void* ptr, BumpBlock*& result)
+{
+ BumpBlock* block = blockFor(ptr);
+ result = block;
+ return !m_toSpaceFilter.ruleOut(reinterpret_cast<Bits>(block)) && m_toSpaceSet.contains(block);
+}
+
+inline void BumpSpace::pin(BumpBlock* block)
+{
+ block->m_isPinned = true;
+}
+
+inline void BumpSpace::startedCopying()
+{
+ DoublyLinkedList<HeapBlock>* temp = m_fromSpace;
+ m_fromSpace = m_toSpace;
+ m_toSpace = temp;
+
+ m_toSpaceFilter.reset();
+
+ m_totalMemoryUtilized = 0;
+
+ ASSERT(!m_inCopyingPhase);
+ ASSERT(!m_numberOfLoanedBlocks);
+ m_inCopyingPhase = true;
+}
+
+inline void BumpSpace::doneCopying()
+{
+ {
+ MutexLocker locker(m_loanedBlocksLock);
+ while (m_numberOfLoanedBlocks > 0)
+ m_loanedBlocksCondition.wait(m_loanedBlocksLock);
+ }
+
+ ASSERT(m_inCopyingPhase);
+ m_inCopyingPhase = false;
+ while (!m_fromSpace->isEmpty()) {
+ BumpBlock* block = static_cast<BumpBlock*>(m_fromSpace->removeHead());
+ if (block->m_isPinned) {
+ block->m_isPinned = false;
+ m_toSpace->push(block);
+ continue;
+ }
+
+ m_toSpaceSet.remove(block);
+ {
+ MutexLocker locker(m_heap->m_freeBlockLock);
+ m_heap->m_freeBlocks.push(block);
+ m_heap->m_numberOfFreeBlocks++;
+ }
+ }
+
+ BumpBlock* curr = static_cast<BumpBlock*>(m_oversizeBlocks.head());
+ while (curr) {
+ BumpBlock* next = static_cast<BumpBlock*>(curr->next());
+ if (!curr->m_isPinned) {
+ m_oversizeBlocks.remove(curr);
+ m_totalMemoryAllocated -= curr->m_allocation.size();
+ m_totalMemoryUtilized -= curr->m_allocation.size() - sizeof(BumpBlock);
+ curr->m_allocation.deallocate();
+ } else
+ curr->m_isPinned = false;
+ curr = next;
+ }
+
+ if (!(m_currentBlock = static_cast<BumpBlock*>(m_toSpace->head())))
+ if (!addNewBlock())
+ CRASH();
+}
+
+inline void BumpSpace::doneFillingBlock(BumpBlock* block)
+{
+ ASSERT(block);
+ ASSERT(block->m_offset < reinterpret_cast<char*>(block) + s_blockSize);
+ ASSERT(m_inCopyingPhase);
+
+ if (block->m_offset == block->m_payload) {
+ recycleBlock(block);
+ return;
+ }
+
+ {
+ MutexLocker locker(m_toSpaceLock);
+ m_toSpace->push(block);
+ m_toSpaceSet.add(block);
+ m_toSpaceFilter.add(reinterpret_cast<Bits>(block));
+ }
+
+ {
+ MutexLocker locker(m_memoryStatsLock);
+ m_totalMemoryUtilized += static_cast<size_t>(static_cast<char*>(block->m_offset) - block->m_payload);
+ }
+
+ {
+ MutexLocker locker(m_loanedBlocksLock);
+ ASSERT(m_numberOfLoanedBlocks > 0);
+ m_numberOfLoanedBlocks--;
+ if (!m_numberOfLoanedBlocks)
+ m_loanedBlocksCondition.signal();
+ }
+}
+
+inline void BumpSpace::recycleBlock(BumpBlock* block)
+{
+ {
+ MutexLocker locker(m_heap->m_freeBlockLock);
+ m_heap->m_freeBlocks.push(block);
+ m_heap->m_numberOfFreeBlocks++;
+ }
+
+ {
+ MutexLocker locker(m_loanedBlocksLock);
+ ASSERT(m_numberOfLoanedBlocks > 0);
+ m_numberOfLoanedBlocks--;
+ if (!m_numberOfLoanedBlocks)
+ m_loanedBlocksCondition.signal();
+ }
+}
+
+inline CheckedBoolean BumpSpace::getFreshBlock(AllocationEffort allocationEffort, BumpBlock** outBlock)
+{
+ HeapBlock* heapBlock = 0;
+ BumpBlock* block = 0;
+ {
+ MutexLocker locker(m_heap->m_freeBlockLock);
+ if (!m_heap->m_freeBlocks.isEmpty()) {
+ heapBlock = m_heap->m_freeBlocks.removeHead();
+ m_heap->m_numberOfFreeBlocks--;
+ }
+ }
+ if (heapBlock)
+ block = new (NotNull, heapBlock) BumpBlock(heapBlock->m_allocation);
+ else if (allocationEffort == AllocationMustSucceed) {
+ if (!allocateNewBlock(&block)) {
+ *outBlock = 0;
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+ } else {
+ ASSERT(allocationEffort == AllocationCanFail);
+ if (m_heap->waterMark() >= m_heap->highWaterMark() && m_heap->m_isSafeToCollect)
+ m_heap->collect(Heap::DoNotSweep);
+
+ if (!getFreshBlock(AllocationMustSucceed, &block)) {
+ *outBlock = 0;
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+ }
+ ASSERT(block);
+ ASSERT(isPointerAligned(block->m_offset));
+ *outBlock = block;
+ return true;
+}
+
+inline CheckedBoolean BumpSpace::borrowBlock(BumpBlock** outBlock)
+{
+ BumpBlock* block = 0;
+ if (!getFreshBlock(AllocationMustSucceed, &block)) {
+ *outBlock = 0;
+ return false;
+ }
+
+ ASSERT(m_inCopyingPhase);
+ MutexLocker locker(m_loanedBlocksLock);
+ m_numberOfLoanedBlocks++;
+
+ ASSERT(block->m_offset == block->m_payload);
+ *outBlock = block;
+ return true;
+}
+
+inline CheckedBoolean BumpSpace::addNewBlock()
+{
+ BumpBlock* block = 0;
+ if (!getFreshBlock(AllocationCanFail, &block))
+ return false;
+
+ m_toSpace->push(block);
+ m_currentBlock = block;
+ return true;
+}
+
+inline CheckedBoolean BumpSpace::allocateNewBlock(BumpBlock** outBlock)
+{
+ PageAllocationAligned allocation = PageAllocationAligned::allocate(s_blockSize, s_blockSize, OSAllocator::JSGCHeapPages);
+ if (!static_cast<bool>(allocation)) {
+ *outBlock = 0;
+ return false;
+ }
+
+ {
+ MutexLocker locker(m_memoryStatsLock);
+ m_totalMemoryAllocated += s_blockSize;
+ }
+
+ *outBlock = new (NotNull, allocation.base()) BumpBlock(allocation);
+ return true;
+}
+
+inline bool BumpSpace::fitsInBlock(BumpBlock* block, size_t bytes)
+{
+ return static_cast<char*>(block->m_offset) + bytes < reinterpret_cast<char*>(block) + s_blockSize && static_cast<char*>(block->m_offset) + bytes > block->m_offset;
+}
+
+inline bool BumpSpace::fitsInCurrentBlock(size_t bytes)
+{
+ return fitsInBlock(m_currentBlock, bytes);
+}
+
+inline CheckedBoolean BumpSpace::tryAllocate(size_t bytes, void** outPtr)
+{
+ ASSERT(!m_heap->globalData()->isInitializingObject());
+
+ if (isOversize(bytes) || !fitsInCurrentBlock(bytes))
+ return tryAllocateSlowCase(bytes, outPtr);
+
+ *outPtr = allocateFromBlock(m_currentBlock, bytes);
+ return true;
+}
+
+inline CheckedBoolean BumpSpace::tryAllocateOversize(size_t bytes, void** outPtr)
+{
+ ASSERT(isOversize(bytes));
+
+ size_t blockSize = WTF::roundUpToMultipleOf<s_pageSize>(sizeof(BumpBlock) + bytes);
+ PageAllocationAligned allocation = PageAllocationAligned::allocate(blockSize, s_pageSize, OSAllocator::JSGCHeapPages);
+ if (!static_cast<bool>(allocation)) {
+ *outPtr = 0;
+ return false;
+ }
+ BumpBlock* block = new (NotNull, allocation.base()) BumpBlock(allocation);
+ m_oversizeBlocks.push(block);
+ ASSERT(isPointerAligned(block->m_offset));
+
+ m_oversizeFilter.add(reinterpret_cast<Bits>(block));
+
+ m_totalMemoryAllocated += blockSize;
+ m_totalMemoryUtilized += bytes;
+
+ *outPtr = block->m_offset;
+ return true;
+}
+
+inline void* BumpSpace::allocateFromBlock(BumpBlock* block, size_t bytes)
+{
+ ASSERT(!isOversize(bytes));
+ ASSERT(fitsInBlock(block, bytes));
+ ASSERT(isPointerAligned(block->m_offset));
+
+ void* ptr = block->m_offset;
+ ASSERT(block->m_offset >= block->m_payload && block->m_offset < reinterpret_cast<char*>(block) + s_blockSize);
+ block->m_offset = static_cast<void*>((static_cast<char*>(ptr) + bytes));
+ ASSERT(block->m_offset >= block->m_payload && block->m_offset < reinterpret_cast<char*>(block) + s_blockSize);
+
+ ASSERT(isPointerAligned(ptr));
+ return ptr;
+}
+
+inline CheckedBoolean BumpSpace::tryReallocate(void** ptr, size_t oldSize, size_t newSize)
+{
+ if (oldSize >= newSize)
+ return true;
+
+ void* oldPtr = *ptr;
+ ASSERT(!m_heap->globalData()->isInitializingObject());
+
+ if (isOversize(oldSize) || isOversize(newSize))
+ return tryReallocateOversize(ptr, oldSize, newSize);
+
+ if (static_cast<char*>(oldPtr) + oldSize == m_currentBlock->m_offset && oldPtr > m_currentBlock && oldPtr < reinterpret_cast<char*>(m_currentBlock) + s_blockSize) {
+ m_currentBlock->m_offset = oldPtr;
+ if (fitsInCurrentBlock(newSize)) {
+ m_totalMemoryUtilized += newSize - oldSize;
+ return allocateFromBlock(m_currentBlock, newSize);
+ }
+ }
+ m_totalMemoryUtilized -= oldSize;
+
+ void* result = 0;
+ if (!tryAllocate(newSize, &result)) {
+ *ptr = 0;
+ return false;
+ }
+ memcpy(result, oldPtr, oldSize);
+ *ptr = result;
+ return true;
+}
+
+inline CheckedBoolean BumpSpace::tryReallocateOversize(void** ptr, size_t oldSize, size_t newSize)
+{
+ ASSERT(isOversize(oldSize) || isOversize(newSize));
+ ASSERT(newSize > oldSize);
+
+ void* oldPtr = *ptr;
+
+ void* newPtr = 0;
+ if (!tryAllocateOversize(newSize, &newPtr)) {
+ *ptr = 0;
+ return false;
+ }
+ memcpy(newPtr, oldPtr, oldSize);
+
+ if (isOversize(oldSize)) {
+ BumpBlock* oldBlock = oversizeBlockFor(oldPtr);
+ m_oversizeBlocks.remove(oldBlock);
+ oldBlock->m_allocation.deallocate();
+ m_totalMemoryAllocated -= oldSize + sizeof(BumpBlock);
+ }
+
+ m_totalMemoryUtilized -= oldSize;
+
+ *ptr = newPtr;
+ return true;
+}
+
+inline bool BumpSpace::isOversize(size_t bytes)
+{
+ return bytes > s_maxAllocationSize;
+}
+
+inline bool BumpSpace::isPinned(void* ptr)
+{
+ return blockFor(ptr)->m_isPinned;
+}
+
+inline BumpBlock* BumpSpace::oversizeBlockFor(void* ptr)
+{
+ return reinterpret_cast<BumpBlock*>(reinterpret_cast<size_t>(ptr) & s_pageMask);
+}
+
+inline BumpBlock* BumpSpace::blockFor(void* ptr)
+{
+ return reinterpret_cast<BumpBlock*>(reinterpret_cast<size_t>(ptr) & s_blockMask);
+}
+
+} // namespace JSC
+
+#endif
diff --git a/Source/JavaScriptCore/heap/ConservativeRoots.cpp b/Source/JavaScriptCore/heap/ConservativeRoots.cpp
index 05c668c35..a509f06e1 100644
--- a/Source/JavaScriptCore/heap/ConservativeRoots.cpp
+++ b/Source/JavaScriptCore/heap/ConservativeRoots.cpp
@@ -26,6 +26,8 @@
#include "config.h"
#include "ConservativeRoots.h"
+#include "BumpSpace.h"
+#include "BumpSpaceInlineMethods.h"
#include "CodeBlock.h"
#include "DFGCodeBlocks.h"
#include "JSCell.h"
@@ -34,16 +36,12 @@
namespace JSC {
-inline bool isPointerAligned(void* p)
-{
- return !((intptr_t)(p) & (sizeof(char*) - 1));
-}
-
-ConservativeRoots::ConservativeRoots(const MarkedBlockSet* blocks)
+ConservativeRoots::ConservativeRoots(const MarkedBlockSet* blocks, BumpSpace* bumpSpace)
: m_roots(m_inlineRoots)
, m_size(0)
, m_capacity(inlineCapacity)
, m_blocks(blocks)
+ , m_bumpSpace(bumpSpace)
{
}
@@ -74,6 +72,10 @@ inline void ConservativeRoots::genericAddPointer(void* p, TinyBloomFilter filter
{
markHook.mark(p);
+ BumpBlock* block;
+ if (m_bumpSpace->contains(p, block))
+ m_bumpSpace->pin(block);
+
MarkedBlock* candidate = MarkedBlock::blockFor(p);
if (filter.ruleOut(reinterpret_cast<Bits>(candidate))) {
ASSERT(!candidate || !m_blocks->set().contains(candidate));
@@ -110,8 +112,8 @@ void ConservativeRoots::genericAddSpan(void* begin, void* end, MarkHook& markHoo
void ConservativeRoots::add(void* begin, void* end)
{
- DummyMarkHook dummyMarkHook;
- genericAddSpan(begin, end, dummyMarkHook);
+ DummyMarkHook hook;
+ genericAddSpan(begin, end, hook);
}
void ConservativeRoots::add(void* begin, void* end, DFGCodeBlocks& dfgCodeBlocks)
diff --git a/Source/JavaScriptCore/heap/ConservativeRoots.h b/Source/JavaScriptCore/heap/ConservativeRoots.h
index 86dfc5886..40b0996d0 100644
--- a/Source/JavaScriptCore/heap/ConservativeRoots.h
+++ b/Source/JavaScriptCore/heap/ConservativeRoots.h
@@ -38,7 +38,7 @@ class Heap;
class ConservativeRoots {
public:
- ConservativeRoots(const MarkedBlockSet*);
+ ConservativeRoots(const MarkedBlockSet*, BumpSpace*);
~ConservativeRoots();
void add(void* begin, void* end);
@@ -63,6 +63,7 @@ private:
size_t m_size;
size_t m_capacity;
const MarkedBlockSet* m_blocks;
+ BumpSpace* m_bumpSpace;
JSCell* m_inlineRoots[inlineCapacity];
};
diff --git a/Source/JavaScriptCore/heap/HandleHeap.h b/Source/JavaScriptCore/heap/HandleHeap.h
index c577791d8..3b9db37a2 100644
--- a/Source/JavaScriptCore/heap/HandleHeap.h
+++ b/Source/JavaScriptCore/heap/HandleHeap.h
@@ -40,7 +40,7 @@ class JSGlobalData;
class JSValue;
class SlotVisitor;
-class WeakHandleOwner {
+class JS_EXPORT_PRIVATE WeakHandleOwner {
public:
virtual ~WeakHandleOwner();
virtual bool isReachableFromOpaqueRoots(Handle<Unknown>, void* context, SlotVisitor&);
@@ -65,7 +65,7 @@ public:
void visitWeakHandles(HeapRootVisitor&);
void finalizeWeakHandles();
- void writeBarrier(HandleSlot, const JSValue&);
+ JS_EXPORT_PRIVATE void writeBarrier(HandleSlot, const JSValue&);
#if !ASSERT_DISABLED
bool hasWeakOwner(HandleSlot, WeakHandleOwner*);
@@ -111,7 +111,7 @@ private:
static HandleSlot toHandle(Node*);
static Node* toNode(HandleSlot);
- void grow();
+ JS_EXPORT_PRIVATE void grow();
#if ENABLE(GC_VALIDATION) || !ASSERT_DISABLED
bool isValidWeakNode(Node*);
diff --git a/Source/JavaScriptCore/heap/Heap.cpp b/Source/JavaScriptCore/heap/Heap.cpp
index 61eba08a4..a2136083a 100644
--- a/Source/JavaScriptCore/heap/Heap.cpp
+++ b/Source/JavaScriptCore/heap/Heap.cpp
@@ -21,6 +21,8 @@
#include "config.h"
#include "Heap.h"
+#include "BumpSpace.h"
+#include "BumpSpaceInlineMethods.h"
#include "CodeBlock.h"
#include "ConservativeRoots.h"
#include "GCActivityCallback.h"
@@ -311,8 +313,11 @@ Heap::Heap(JSGlobalData* globalData, HeapSize heapSize)
: m_heapSize(heapSize)
, m_minBytesPerCycle(heapSizeForHint(heapSize))
, m_lastFullGCSize(0)
+ , m_waterMark(0)
+ , m_highWaterMark(m_minBytesPerCycle)
, m_operationInProgress(NoOperation)
, m_objectSpace(this)
+ , m_storageSpace(this)
, m_blockFreeingThreadShouldQuit(false)
, m_extraCost(0)
, m_markListSet(0)
@@ -324,12 +329,12 @@ Heap::Heap(JSGlobalData* globalData, HeapSize heapSize)
, m_isSafeToCollect(false)
, m_globalData(globalData)
{
- m_objectSpace.setHighWaterMark(m_minBytesPerCycle);
(*m_activityCallback)();
m_numberOfFreeBlocks = 0;
m_blockFreeingThread = createThread(blockFreeingThreadStartFunc, this, "JavaScriptCore::BlockFree");
ASSERT(m_blockFreeingThread);
+ m_storageSpace.init();
}
Heap::~Heap()
@@ -433,7 +438,7 @@ void Heap::blockFreeingThreadMain()
if (m_numberOfFreeBlocks <= desiredNumberOfFreeBlocks)
block = 0;
else {
- block = m_freeBlocks.removeHead();
+ block = static_cast<MarkedBlock*>(m_freeBlocks.removeHead());
ASSERT(block);
m_numberOfFreeBlocks--;
}
@@ -460,7 +465,7 @@ void Heap::reportExtraMemoryCostSlowCase(size_t cost)
// if a large value survives one garbage collection, there is not much point to
// collecting more frequently as long as it stays alive.
- if (m_extraCost > maxExtraCost && m_extraCost > m_objectSpace.highWaterMark() / 2)
+ if (m_extraCost > maxExtraCost && m_extraCost > highWaterMark() / 2)
collectAllGarbage();
m_extraCost += cost;
}
@@ -509,7 +514,7 @@ void Heap::popTempSortVector(Vector<ValueStringPair>* tempVector)
ASSERT_UNUSED(tempVector, tempVector == m_tempSortingVectors.last());
m_tempSortingVectors.removeLast();
}
-
+
void Heap::markTempSortVectors(HeapRootVisitor& heapRootVisitor)
{
typedef Vector<Vector<ValueStringPair>* > VectorOfValueStringVectors;
@@ -547,7 +552,7 @@ void Heap::getConservativeRegisterRoots(HashSet<JSCell*>& roots)
if (m_operationInProgress != NoOperation)
CRASH();
m_operationInProgress = Collection;
- ConservativeRoots registerFileRoots(&m_objectSpace.blocks());
+ ConservativeRoots registerFileRoots(&m_objectSpace.blocks(), &m_storageSpace);
registerFile().gatherConservativeRoots(registerFileRoots);
size_t registerFileRootCount = registerFileRoots.size();
JSCell** registerRoots = registerFileRoots.roots();
@@ -573,13 +578,13 @@ void Heap::markRoots(bool fullGC)
// We gather conservative roots before clearing mark bits because conservative
// gathering uses the mark bits to determine whether a reference is valid.
- ConservativeRoots machineThreadRoots(&m_objectSpace.blocks());
+ ConservativeRoots machineThreadRoots(&m_objectSpace.blocks(), &m_storageSpace);
{
GCPHASE(GatherConservativeRoots);
m_machineThreads.gatherConservativeRoots(machineThreadRoots, &dummy);
}
- ConservativeRoots registerFileRoots(&m_objectSpace.blocks());
+ ConservativeRoots registerFileRoots(&m_objectSpace.blocks(), &m_storageSpace);
m_dfgCodeBlocks.clearMarks();
{
GCPHASE(GatherRegisterFileRoots);
@@ -597,6 +602,7 @@ void Heap::markRoots(bool fullGC)
clearMarks();
}
+ m_storageSpace.startedCopying();
SlotVisitor& visitor = m_slotVisitor;
HeapRootVisitor heapRootVisitor(visitor);
@@ -700,8 +706,10 @@ void Heap::markRoots(bool fullGC)
}
GCCOUNTER(VisitedValueCount, visitor.visitCount());
+ visitor.doneCopying();
visitor.reset();
m_sharedData.reset();
+ m_storageSpace.doneCopying();
m_operationInProgress = NoOperation;
}
@@ -822,11 +830,11 @@ void Heap::collect(SweepToggle sweepToggle)
// water mark to be proportional to the current size of the heap. The exact
// proportion is a bit arbitrary. A 2X multiplier gives a 1:1 (heap size :
// new bytes allocated) proportion, and seems to work well in benchmarks.
- size_t newSize = size();
+ size_t newSize = size() + m_storageSpace.totalMemoryUtilized();
size_t proportionalBytes = 2 * newSize;
if (fullGC) {
m_lastFullGCSize = newSize;
- m_objectSpace.setHighWaterMark(max(proportionalBytes, m_minBytesPerCycle));
+ setHighWaterMark(max(proportionalBytes, m_minBytesPerCycle));
}
JAVASCRIPTCORE_GC_END();
@@ -887,7 +895,7 @@ void Heap::releaseFreeBlocks()
if (!m_numberOfFreeBlocks)
block = 0;
else {
- block = m_freeBlocks.removeHead();
+ block = static_cast<MarkedBlock*>(m_freeBlocks.removeHead());
ASSERT(block);
m_numberOfFreeBlocks--;
}
diff --git a/Source/JavaScriptCore/heap/Heap.h b/Source/JavaScriptCore/heap/Heap.h
index 1b228253b..40a8376f0 100644
--- a/Source/JavaScriptCore/heap/Heap.h
+++ b/Source/JavaScriptCore/heap/Heap.h
@@ -22,7 +22,6 @@
#ifndef Heap_h
#define Heap_h
-#include "AllocationSpace.h"
#include "DFGCodeBlocks.h"
#include "HandleHeap.h"
#include "HandleStack.h"
@@ -31,12 +30,16 @@
#include "MarkedSpace.h"
#include "SlotVisitor.h"
#include "WriteBarrierSupport.h"
+#include <wtf/DoublyLinkedList.h>
#include <wtf/Forward.h>
#include <wtf/HashCountedSet.h>
#include <wtf/HashSet.h>
+#define COLLECT_ON_EVERY_ALLOCATION 0
+
namespace JSC {
+ class BumpSpace;
class CodeBlock;
class GCActivityCallback;
class GlobalCodeBlock;
@@ -57,7 +60,7 @@ namespace JSC {
typedef HashCountedSet<const char*> TypeCountSet;
enum OperationInProgress { NoOperation, Allocation, Collection };
-
+
// Heap size hint.
enum HeapSize { SmallHeap, LargeHeap };
@@ -65,6 +68,7 @@ namespace JSC {
WTF_MAKE_NONCOPYABLE(Heap);
public:
friend class JIT;
+ friend class MarkStackThreadSharedData;
static Heap* heap(JSValue); // 0 for immediate values
static Heap* heap(JSCell*);
@@ -78,42 +82,44 @@ namespace JSC {
Heap(JSGlobalData*, HeapSize);
~Heap();
- void destroy(); // JSGlobalData must call destroy() before ~Heap().
+ JS_EXPORT_PRIVATE void destroy(); // JSGlobalData must call destroy() before ~Heap().
JSGlobalData* globalData() const { return m_globalData; }
- AllocationSpace& objectSpace() { return m_objectSpace; }
+ MarkedSpace& objectSpace() { return m_objectSpace; }
MachineThreads& machineThreads() { return m_machineThreads; }
- GCActivityCallback* activityCallback();
- void setActivityCallback(PassOwnPtr<GCActivityCallback>);
+ JS_EXPORT_PRIVATE GCActivityCallback* activityCallback();
+ JS_EXPORT_PRIVATE void setActivityCallback(PassOwnPtr<GCActivityCallback>);
// true if an allocation or collection is in progress
inline bool isBusy();
MarkedSpace::SizeClass& sizeClassForObject(size_t bytes) { return m_objectSpace.sizeClassFor(bytes); }
void* allocate(size_t);
+ CheckedBoolean tryAllocateStorage(size_t, void**);
+ CheckedBoolean tryReallocateStorage(void**, size_t, size_t);
typedef void (*Finalizer)(JSCell*);
- void addFinalizer(JSCell*, Finalizer);
+ JS_EXPORT_PRIVATE void addFinalizer(JSCell*, Finalizer);
void notifyIsSafeToCollect() { m_isSafeToCollect = true; }
- void collectAllGarbage();
+ JS_EXPORT_PRIVATE void collectAllGarbage();
void reportExtraMemoryCost(size_t cost);
- void protect(JSValue);
- bool unprotect(JSValue); // True when the protect count drops to 0.
+ JS_EXPORT_PRIVATE void protect(JSValue);
+ JS_EXPORT_PRIVATE bool unprotect(JSValue); // True when the protect count drops to 0.
void jettisonDFGCodeBlock(PassOwnPtr<CodeBlock>);
- size_t size();
- size_t capacity();
- size_t objectCount();
- size_t globalObjectCount();
- size_t protectedObjectCount();
- size_t protectedGlobalObjectCount();
- PassOwnPtr<TypeCountSet> protectedObjectTypeCounts();
- PassOwnPtr<TypeCountSet> objectTypeCounts();
+ JS_EXPORT_PRIVATE size_t size();
+ JS_EXPORT_PRIVATE size_t capacity();
+ JS_EXPORT_PRIVATE size_t objectCount();
+ JS_EXPORT_PRIVATE size_t globalObjectCount();
+ JS_EXPORT_PRIVATE size_t protectedObjectCount();
+ JS_EXPORT_PRIVATE size_t protectedGlobalObjectCount();
+ JS_EXPORT_PRIVATE PassOwnPtr<TypeCountSet> protectedObjectTypeCounts();
+ JS_EXPORT_PRIVATE PassOwnPtr<TypeCountSet> objectTypeCounts();
void pushTempSortVector(Vector<ValueStringPair>*);
void popTempSortVector(Vector<ValueStringPair>*);
@@ -129,11 +135,16 @@ namespace JSC {
void getConservativeRegisterRoots(HashSet<JSCell*>& roots);
private:
+ friend class MarkedSpace;
friend class MarkedBlock;
- friend class AllocationSpace;
+ friend class BumpSpace;
friend class SlotVisitor;
friend class CodeBlock;
+ size_t waterMark();
+ size_t highWaterMark();
+ void setHighWaterMark(size_t);
+
static const size_t minExtraCost = 256;
static const size_t maxExtraCost = 1024 * 1024;
@@ -141,8 +152,8 @@ namespace JSC {
virtual void finalize(Handle<Unknown>, void* context);
};
- bool isValidAllocation(size_t);
- void reportExtraMemoryCostSlowCase(size_t);
+ JS_EXPORT_PRIVATE bool isValidAllocation(size_t);
+ JS_EXPORT_PRIVATE void reportExtraMemoryCostSlowCase(size_t);
// Call this function before any operation that needs to know which cells
// in the heap are live. (For example, call this function before
@@ -175,11 +186,14 @@ namespace JSC {
const HeapSize m_heapSize;
const size_t m_minBytesPerCycle;
size_t m_lastFullGCSize;
+ size_t m_waterMark;
+ size_t m_highWaterMark;
OperationInProgress m_operationInProgress;
- AllocationSpace m_objectSpace;
+ MarkedSpace m_objectSpace;
+ BumpSpace m_storageSpace;
- DoublyLinkedList<MarkedBlock> m_freeBlocks;
+ DoublyLinkedList<HeapBlock> m_freeBlocks;
size_t m_numberOfFreeBlocks;
ThreadIdentifier m_blockFreeingThread;
@@ -246,6 +260,21 @@ namespace JSC {
MarkedBlock::blockFor(cell)->setMarked(cell);
}
+ inline size_t Heap::waterMark()
+ {
+ return m_objectSpace.waterMark() + m_storageSpace.totalMemoryUtilized();
+ }
+
+ inline size_t Heap::highWaterMark()
+ {
+ return m_highWaterMark;
+ }
+
+ inline void Heap::setHighWaterMark(size_t newHighWaterMark)
+ {
+ m_highWaterMark = newHighWaterMark;
+ }
+
#if ENABLE(GGC)
inline uint8_t* Heap::addressOfCardFor(JSCell* cell)
{
@@ -308,6 +337,16 @@ namespace JSC {
ASSERT(isValidAllocation(bytes));
return m_objectSpace.allocate(bytes);
}
+
+ inline CheckedBoolean Heap::tryAllocateStorage(size_t bytes, void** outPtr)
+ {
+ return m_storageSpace.tryAllocate(bytes, outPtr);
+ }
+
+ inline CheckedBoolean Heap::tryReallocateStorage(void** ptr, size_t oldSize, size_t newSize)
+ {
+ return m_storageSpace.tryReallocate(ptr, oldSize, newSize);
+ }
} // namespace JSC
diff --git a/Source/JavaScriptCore/heap/HeapBlock.h b/Source/JavaScriptCore/heap/HeapBlock.h
new file mode 100644
index 000000000..b0ecb2059
--- /dev/null
+++ b/Source/JavaScriptCore/heap/HeapBlock.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2011 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 HeapBlock_h
+#define HeapBlock_h
+
+#include <wtf/DoublyLinkedList.h>
+#include <wtf/PageAllocationAligned.h>
+
+namespace JSC {
+
+enum AllocationEffort { AllocationCanFail, AllocationMustSucceed };
+
+class HeapBlock : public DoublyLinkedListNode<HeapBlock> {
+public:
+ HeapBlock(PageAllocationAligned& allocation)
+ : DoublyLinkedListNode<HeapBlock>()
+ , m_prev(0)
+ , m_next(0)
+ , m_allocation(allocation)
+ {
+ ASSERT(allocation);
+ }
+
+ HeapBlock* m_prev;
+ HeapBlock* m_next;
+ PageAllocationAligned m_allocation;
+};
+
+} // namespace JSC
+
+#endif
diff --git a/Source/JavaScriptCore/heap/MachineStackMarker.cpp b/Source/JavaScriptCore/heap/MachineStackMarker.cpp
index f62ee066f..fd828d5de 100644
--- a/Source/JavaScriptCore/heap/MachineStackMarker.cpp
+++ b/Source/JavaScriptCore/heap/MachineStackMarker.cpp
@@ -193,7 +193,7 @@ void MachineThreads::addCurrentThread()
return;
pthread_setspecific(m_threadSpecific, this);
- Thread* thread = new Thread(getCurrentPlatformThread(), m_heap->globalData()->stack().origin());
+ Thread* thread = new Thread(getCurrentPlatformThread(), wtfThreadData().stack().origin());
MutexLocker lock(m_registeredThreadsMutex);
@@ -257,7 +257,7 @@ void MachineThreads::gatherFromCurrentThread(ConservativeRoots& conservativeRoot
conservativeRoots.add(registersBegin, registersEnd);
void* stackBegin = stackCurrent;
- void* stackEnd = m_heap->globalData()->stack().origin();
+ void* stackEnd = wtfThreadData().stack().origin();
swapIfBackwards(stackBegin, stackEnd);
conservativeRoots.add(stackBegin, stackEnd);
}
diff --git a/Source/JavaScriptCore/heap/MachineStackMarker.h b/Source/JavaScriptCore/heap/MachineStackMarker.h
index 69c4537bd..0f5a4c3aa 100644
--- a/Source/JavaScriptCore/heap/MachineStackMarker.h
+++ b/Source/JavaScriptCore/heap/MachineStackMarker.h
@@ -40,7 +40,7 @@ namespace JSC {
void gatherConservativeRoots(ConservativeRoots&, void* stackCurrent);
void makeUsableFromMultipleThreads();
- void addCurrentThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
+ JS_EXPORT_PRIVATE void addCurrentThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
private:
void gatherFromCurrentThread(ConservativeRoots&, void* stackCurrent);
diff --git a/Source/JavaScriptCore/heap/MarkStack.cpp b/Source/JavaScriptCore/heap/MarkStack.cpp
index 02cf328d4..9a3092396 100644
--- a/Source/JavaScriptCore/heap/MarkStack.cpp
+++ b/Source/JavaScriptCore/heap/MarkStack.cpp
@@ -26,6 +26,8 @@
#include "config.h"
#include "MarkStack.h"
+#include "BumpSpace.h"
+#include "BumpSpaceInlineMethods.h"
#include "ConservativeRoots.h"
#include "Heap.h"
#include "Options.h"
@@ -233,6 +235,7 @@ void* MarkStackThreadSharedData::markingThreadStartFunc(void* shared)
MarkStackThreadSharedData::MarkStackThreadSharedData(JSGlobalData* globalData)
: m_globalData(globalData)
+ , m_bumpSpace(&globalData->heap.m_storageSpace)
, m_sharedMarkStack(m_segmentAllocator)
, m_numberOfActiveParallelMarkers(0)
, m_parallelMarkersShouldExit(false)
@@ -337,7 +340,7 @@ void SlotVisitor::donateSlow()
void SlotVisitor::drain()
{
ASSERT(m_isInParallelMode);
-
+
#if ENABLE(PARALLEL_GC)
if (Options::numberOfGCMarkers > 1) {
while (!m_stack.isEmpty()) {
@@ -398,8 +401,11 @@ void SlotVisitor::drainFromShared(SharedDrainMode sharedDrainMode)
// for us to do.
while (true) {
// Did we reach termination?
- if (!m_shared.m_numberOfActiveParallelMarkers && m_shared.m_sharedMarkStack.isEmpty())
+ if (!m_shared.m_numberOfActiveParallelMarkers && m_shared.m_sharedMarkStack.isEmpty()) {
+ // Let any sleeping slaves know it's time for them to give their private BumpBlocks back
+ m_shared.m_markingCondition.broadcast();
return;
+ }
// Is there work to be done?
if (!m_shared.m_sharedMarkStack.isEmpty())
@@ -415,14 +421,19 @@ void SlotVisitor::drainFromShared(SharedDrainMode sharedDrainMode)
if (!m_shared.m_numberOfActiveParallelMarkers && m_shared.m_sharedMarkStack.isEmpty())
m_shared.m_markingCondition.broadcast();
- while (m_shared.m_sharedMarkStack.isEmpty() && !m_shared.m_parallelMarkersShouldExit)
+ while (m_shared.m_sharedMarkStack.isEmpty() && !m_shared.m_parallelMarkersShouldExit) {
+ if (!m_shared.m_numberOfActiveParallelMarkers && m_shared.m_sharedMarkStack.isEmpty())
+ doneCopying();
m_shared.m_markingCondition.wait(m_shared.m_markingLock);
+ }
// Is the VM exiting? If so, exit this thread.
- if (m_shared.m_parallelMarkersShouldExit)
+ if (m_shared.m_parallelMarkersShouldExit) {
+ doneCopying();
return;
+ }
}
-
+
m_stack.stealSomeCellsFrom(m_shared.m_sharedMarkStack);
m_shared.m_numberOfActiveParallelMarkers++;
}
@@ -445,6 +456,79 @@ void MarkStack::mergeOpaqueRoots()
m_opaqueRoots.clear();
}
+void SlotVisitor::startCopying()
+{
+ ASSERT(!m_copyBlock);
+ if (!m_shared.m_bumpSpace->borrowBlock(&m_copyBlock))
+ CRASH();
+}
+
+void* SlotVisitor::allocateNewSpace(void* ptr, size_t bytes)
+{
+ if (BumpSpace::isOversize(bytes)) {
+ m_shared.m_bumpSpace->pin(BumpSpace::oversizeBlockFor(ptr));
+ return 0;
+ }
+
+ if (m_shared.m_bumpSpace->isPinned(ptr))
+ return 0;
+
+ // The only time it's possible to have a null copy block is if we have just started copying.
+ if (!m_copyBlock)
+ startCopying();
+
+ if (!BumpSpace::fitsInBlock(m_copyBlock, bytes)) {
+ // We don't need to lock across these two calls because the master thread won't
+ // call doneCopying() because this thread is considered active.
+ m_shared.m_bumpSpace->doneFillingBlock(m_copyBlock);
+ if (!m_shared.m_bumpSpace->borrowBlock(&m_copyBlock))
+ CRASH();
+ }
+ return BumpSpace::allocateFromBlock(m_copyBlock, bytes);
+}
+
+void SlotVisitor::copy(void** ptr, size_t bytes)
+{
+ void* newPtr = 0;
+ if (!(newPtr = allocateNewSpace(*ptr, bytes)))
+ return;
+
+ memcpy(newPtr, *ptr, bytes);
+ *ptr = newPtr;
+}
+
+void SlotVisitor::copyAndAppend(void** ptr, size_t bytes, JSValue* values, unsigned length)
+{
+ void* oldPtr = *ptr;
+ void* newPtr = allocateNewSpace(oldPtr, bytes);
+ if (newPtr) {
+ size_t jsValuesOffset = static_cast<size_t>(reinterpret_cast<char*>(values) - static_cast<char*>(oldPtr));
+
+ JSValue* newValues = reinterpret_cast<JSValue*>(static_cast<char*>(newPtr) + jsValuesOffset);
+ for (unsigned i = 0; i < length; i++) {
+ JSValue& value = values[i];
+ newValues[i] = value;
+ if (!value)
+ continue;
+ internalAppend(value);
+ }
+
+ memcpy(newPtr, oldPtr, jsValuesOffset);
+ *ptr = newPtr;
+ } else
+ append(values, length);
+}
+
+void SlotVisitor::doneCopying()
+{
+ if (!m_copyBlock)
+ return;
+
+ m_shared.m_bumpSpace->doneFillingBlock(m_copyBlock);
+
+ m_copyBlock = 0;
+}
+
void SlotVisitor::harvestWeakReferences()
{
for (WeakReferenceHarvester* current = m_shared.m_weakReferenceHarvesters.head(); current; current = current->next())
diff --git a/Source/JavaScriptCore/heap/MarkStack.h b/Source/JavaScriptCore/heap/MarkStack.h
index 1478011d9..6923cdd8a 100644
--- a/Source/JavaScriptCore/heap/MarkStack.h
+++ b/Source/JavaScriptCore/heap/MarkStack.h
@@ -26,6 +26,7 @@
#ifndef MarkStack_h
#define MarkStack_h
+#include "BumpSpace.h"
#include "HandleTypes.h"
#include "Options.h"
#include "JSValue.h"
@@ -111,7 +112,7 @@ namespace JSC {
private:
MarkStackSegment* m_topSegment;
- void expand();
+ JS_EXPORT_PRIVATE void expand();
MarkStackSegmentAllocator& m_allocator;
@@ -181,6 +182,7 @@ namespace JSC {
#endif
JSGlobalData* m_globalData;
+ BumpSpace* m_bumpSpace;
MarkStackSegmentAllocator m_segmentAllocator;
@@ -241,7 +243,7 @@ namespace JSC {
}
protected:
- static void validate(JSCell*);
+ JS_EXPORT_PRIVATE static void validate(JSCell*);
void append(JSValue*);
void append(JSValue*, size_t count);
@@ -250,7 +252,7 @@ namespace JSC {
void internalAppend(JSCell*);
void internalAppend(JSValue);
- void mergeOpaqueRoots();
+ JS_EXPORT_PRIVATE void mergeOpaqueRoots();
void mergeOpaqueRootsIfNecessary()
{
diff --git a/Source/JavaScriptCore/heap/MarkedBlock.cpp b/Source/JavaScriptCore/heap/MarkedBlock.cpp
index 771c9c082..715f25d92 100644
--- a/Source/JavaScriptCore/heap/MarkedBlock.cpp
+++ b/Source/JavaScriptCore/heap/MarkedBlock.cpp
@@ -40,9 +40,9 @@ MarkedBlock* MarkedBlock::create(Heap* heap, size_t cellSize)
return new (NotNull, allocation.base()) MarkedBlock(allocation, heap, cellSize);
}
-MarkedBlock* MarkedBlock::recycle(MarkedBlock* block, size_t cellSize)
+MarkedBlock* MarkedBlock::recycle(MarkedBlock* block, Heap* heap, size_t cellSize)
{
- return new (NotNull, block) MarkedBlock(block->m_allocation, block->m_heap, cellSize);
+ return new (NotNull, block) MarkedBlock(block->m_allocation, heap, cellSize);
}
void MarkedBlock::destroy(MarkedBlock* block)
@@ -50,13 +50,14 @@ void MarkedBlock::destroy(MarkedBlock* block)
block->m_allocation.deallocate();
}
-MarkedBlock::MarkedBlock(const PageAllocationAligned& allocation, Heap* heap, size_t cellSize)
- : m_atomsPerCell((cellSize + atomSize - 1) / atomSize)
+MarkedBlock::MarkedBlock(PageAllocationAligned& allocation, Heap* heap, size_t cellSize)
+ : HeapBlock(allocation)
+ , m_atomsPerCell((cellSize + atomSize - 1) / atomSize)
, m_endAtom(atomsPerBlock - m_atomsPerCell + 1)
, m_state(New) // All cells start out unmarked.
- , m_allocation(allocation)
, m_heap(heap)
{
+ ASSERT(heap);
HEAP_LOG_BLOCK_STATE_TRANSITION(this);
}
diff --git a/Source/JavaScriptCore/heap/MarkedBlock.h b/Source/JavaScriptCore/heap/MarkedBlock.h
index 8c665dd5b..00eb54b1f 100644
--- a/Source/JavaScriptCore/heap/MarkedBlock.h
+++ b/Source/JavaScriptCore/heap/MarkedBlock.h
@@ -23,6 +23,7 @@
#define MarkedBlock_h
#include "CardSet.h"
+#include "HeapBlock.h"
#include <wtf/Bitmap.h>
#include <wtf/DoublyLinkedList.h>
@@ -50,7 +51,6 @@ namespace JSC {
typedef uintptr_t Bits;
- static const size_t KB = 1024;
static const size_t MB = 1024 * 1024;
bool isZapped(const JSCell*);
@@ -63,14 +63,14 @@ namespace JSC {
// size is equal to the difference between the cell size and the object
// size.
- class MarkedBlock : public DoublyLinkedListNode<MarkedBlock> {
+ class MarkedBlock : public HeapBlock {
friend class WTF::DoublyLinkedListNode<MarkedBlock>;
public:
// Ensure natural alignment for native types whilst recognizing that the smallest
// object the heap will commonly allocate is four words.
static const size_t atomSize = 4 * sizeof(void*);
static const size_t atomShift = 5;
- static const size_t blockSize = 16 * KB;
+ static const size_t blockSize = 64 * KB;
static const size_t blockMask = ~(blockSize - 1); // blockSize must be a power of two.
static const size_t atomsPerBlock = blockSize / atomSize; // ~0.4% overhead
@@ -90,7 +90,7 @@ namespace JSC {
};
static MarkedBlock* create(Heap*, size_t cellSize);
- static MarkedBlock* recycle(MarkedBlock*, size_t cellSize);
+ static MarkedBlock* recycle(MarkedBlock*, Heap*, size_t cellSize);
static void destroy(MarkedBlock*);
static bool isAtomAligned(const void*);
@@ -162,7 +162,7 @@ namespace JSC {
typedef char Atom[atomSize];
- MarkedBlock(const PageAllocationAligned&, Heap*, size_t cellSize);
+ MarkedBlock(PageAllocationAligned&, Heap*, size_t cellSize);
Atom* atoms();
size_t atomNumber(const void*);
void callDestructor(JSCell*);
@@ -180,10 +180,7 @@ namespace JSC {
WTF::Bitmap<atomsPerBlock, WTF::BitmapNotAtomic> m_marks;
#endif
BlockState m_state;
- PageAllocationAligned m_allocation;
Heap* m_heap;
- MarkedBlock* m_prev;
- MarkedBlock* m_next;
};
inline size_t MarkedBlock::firstAtom()
diff --git a/Source/JavaScriptCore/heap/MarkedSpace.cpp b/Source/JavaScriptCore/heap/MarkedSpace.cpp
index acbd8acac..fcca188e4 100644
--- a/Source/JavaScriptCore/heap/MarkedSpace.cpp
+++ b/Source/JavaScriptCore/heap/MarkedSpace.cpp
@@ -33,7 +33,6 @@ class Structure;
MarkedSpace::MarkedSpace(Heap* heap)
: m_waterMark(0)
, m_nurseryWaterMark(0)
- , m_highWaterMark(0)
, m_heap(heap)
{
for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep)
@@ -82,4 +81,192 @@ void MarkedSpace::canonicalizeCellLivenessData()
sizeClassFor(cellSize).zapFreeList();
}
+inline void* MarkedSpace::tryAllocateHelper(MarkedSpace::SizeClass& sizeClass)
+{
+ MarkedBlock::FreeCell* firstFreeCell = sizeClass.firstFreeCell;
+ if (!firstFreeCell) {
+ for (MarkedBlock*& block = sizeClass.currentBlock; block; block = static_cast<MarkedBlock*>(block->next())) {
+ firstFreeCell = block->sweep(MarkedBlock::SweepToFreeList);
+ if (firstFreeCell)
+ break;
+ m_nurseryWaterMark += block->capacity() - block->size();
+ m_waterMark += block->capacity();
+ block->didConsumeFreeList();
+ }
+
+ if (!firstFreeCell)
+ return 0;
+ }
+
+ ASSERT(firstFreeCell);
+ sizeClass.firstFreeCell = firstFreeCell->next;
+ return firstFreeCell;
+}
+
+inline void* MarkedSpace::tryAllocate(MarkedSpace::SizeClass& sizeClass)
+{
+ m_heap->m_operationInProgress = Allocation;
+ void* result = tryAllocateHelper(sizeClass);
+ m_heap->m_operationInProgress = NoOperation;
+ return result;
+}
+
+void* MarkedSpace::allocateSlowCase(MarkedSpace::SizeClass& sizeClass)
+{
+#if COLLECT_ON_EVERY_ALLOCATION
+ m_heap->collectAllGarbage();
+ ASSERT(m_heap->m_operationInProgress == NoOperation);
+#endif
+
+ void* result = tryAllocate(sizeClass);
+
+ if (LIKELY(result != 0))
+ return result;
+
+ AllocationEffort allocationEffort;
+
+ if ((
+#if ENABLE(GGC)
+ nurseryWaterMark() < m_heap->m_minBytesPerCycle
+#else
+ m_heap->waterMark() < m_heap->highWaterMark()
+#endif
+ ) || !m_heap->m_isSafeToCollect)
+ allocationEffort = AllocationMustSucceed;
+ else
+ allocationEffort = AllocationCanFail;
+
+ MarkedBlock* block = allocateBlock(sizeClass.cellSize, allocationEffort);
+ if (block) {
+ addBlock(sizeClass, block);
+ void* result = tryAllocate(sizeClass);
+ ASSERT(result);
+ return result;
+ }
+
+ m_heap->collect(Heap::DoNotSweep);
+
+ result = tryAllocate(sizeClass);
+
+ if (result)
+ return result;
+
+ ASSERT(m_heap->waterMark() < m_heap->highWaterMark());
+
+ addBlock(sizeClass, allocateBlock(sizeClass.cellSize, AllocationMustSucceed));
+
+ result = tryAllocate(sizeClass);
+ ASSERT(result);
+ return result;
+}
+
+MarkedBlock* MarkedSpace::allocateBlock(size_t cellSize, AllocationEffort allocationEffort)
+{
+ MarkedBlock* block;
+
+ {
+ MutexLocker locker(m_heap->m_freeBlockLock);
+ if (m_heap->m_numberOfFreeBlocks) {
+ block = static_cast<MarkedBlock*>(m_heap->m_freeBlocks.removeHead());
+ ASSERT(block);
+ m_heap->m_numberOfFreeBlocks--;
+ } else
+ block = 0;
+ }
+ if (block)
+ block = MarkedBlock::recycle(block, m_heap, cellSize);
+ else if (allocationEffort == AllocationCanFail)
+ return 0;
+ else
+ block = MarkedBlock::create(m_heap, cellSize);
+
+ m_blocks.add(block);
+
+ return block;
+}
+
+void MarkedSpace::freeBlocks(MarkedBlock* head)
+{
+ MarkedBlock* next;
+ for (MarkedBlock* block = head; block; block = next) {
+ next = static_cast<MarkedBlock*>(block->next());
+
+ m_blocks.remove(block);
+ block->sweep();
+ MutexLocker locker(m_heap->m_freeBlockLock);
+ m_heap->m_freeBlocks.append(block);
+ m_heap->m_numberOfFreeBlocks++;
+ }
+}
+
+class TakeIfUnmarked {
+public:
+ typedef MarkedBlock* ReturnType;
+
+ TakeIfUnmarked(MarkedSpace*);
+ void operator()(MarkedBlock*);
+ ReturnType returnValue();
+
+private:
+ MarkedSpace* m_markedSpace;
+ DoublyLinkedList<MarkedBlock> m_empties;
+};
+
+inline TakeIfUnmarked::TakeIfUnmarked(MarkedSpace* newSpace)
+ : m_markedSpace(newSpace)
+{
+}
+
+inline void TakeIfUnmarked::operator()(MarkedBlock* block)
+{
+ if (!block->markCountIsZero())
+ return;
+
+ m_markedSpace->removeBlock(block);
+ m_empties.append(block);
+}
+
+inline TakeIfUnmarked::ReturnType TakeIfUnmarked::returnValue()
+{
+ return m_empties.head();
+}
+
+void MarkedSpace::shrink()
+{
+ // We record a temporary list of empties to avoid modifying m_blocks while iterating it.
+ TakeIfUnmarked takeIfUnmarked(this);
+ freeBlocks(forEachBlock(takeIfUnmarked));
+}
+
+#if ENABLE(GGC)
+class GatherDirtyCells {
+ WTF_MAKE_NONCOPYABLE(GatherDirtyCells);
+public:
+ typedef void* ReturnType;
+
+ explicit GatherDirtyCells(MarkedBlock::DirtyCellVector*);
+ void operator()(MarkedBlock*);
+ ReturnType returnValue() { return 0; }
+
+private:
+ MarkedBlock::DirtyCellVector* m_dirtyCells;
+};
+
+inline GatherDirtyCells::GatherDirtyCells(MarkedBlock::DirtyCellVector* dirtyCells)
+ : m_dirtyCells(dirtyCells)
+{
+}
+
+inline void GatherDirtyCells::operator()(MarkedBlock* block)
+{
+ block->gatherDirtyCells(*m_dirtyCells);
+}
+
+void MarkedSpace::gatherDirtyCells(MarkedBlock::DirtyCellVector& dirtyCells)
+{
+ GatherDirtyCells gatherDirtyCells(&dirtyCells);
+ forEachBlock(gatherDirtyCells);
+}
+#endif
+
} // namespace JSC
diff --git a/Source/JavaScriptCore/heap/MarkedSpace.h b/Source/JavaScriptCore/heap/MarkedSpace.h
index 751fe2fee..f7d96c774 100644
--- a/Source/JavaScriptCore/heap/MarkedSpace.h
+++ b/Source/JavaScriptCore/heap/MarkedSpace.h
@@ -24,6 +24,7 @@
#include "MachineStackMarker.h"
#include "MarkedBlock.h"
+#include "MarkedBlockSet.h"
#include "PageAllocationAligned.h"
#include <wtf/Bitmap.h>
#include <wtf/DoublyLinkedList.h>
@@ -54,31 +55,43 @@ public:
MarkedBlock::FreeCell* firstFreeCell;
MarkedBlock* currentBlock;
- DoublyLinkedList<MarkedBlock> blockList;
+ DoublyLinkedList<HeapBlock> blockList;
size_t cellSize;
};
MarkedSpace(Heap*);
SizeClass& sizeClassFor(size_t);
+ void* allocate(size_t);
void* allocate(SizeClass&);
void resetAllocator();
void addBlock(SizeClass&, MarkedBlock*);
void removeBlock(MarkedBlock*);
+ MarkedBlockSet& blocks() { return m_blocks; }
void canonicalizeCellLivenessData();
size_t waterMark();
- size_t highWaterMark();
size_t nurseryWaterMark();
- void setHighWaterMark(size_t);
- template<typename Functor> typename Functor::ReturnType forEachBlock(Functor&); // Safe to remove the current item while iterating.
+ typedef HashSet<MarkedBlock*>::iterator BlockIterator;
+
+ template<typename Functor> typename Functor::ReturnType forEachCell(Functor&);
+ template<typename Functor> typename Functor::ReturnType forEachCell();
+ template<typename Functor> typename Functor::ReturnType forEachBlock(Functor&);
template<typename Functor> typename Functor::ReturnType forEachBlock();
+
+ void shrink();
+ void freeBlocks(MarkedBlock* head);
private:
+ JS_EXPORT_PRIVATE void* allocateSlowCase(SizeClass&);
+ void* tryAllocateHelper(MarkedSpace::SizeClass&);
+ void* tryAllocate(MarkedSpace::SizeClass&);
+ MarkedBlock* allocateBlock(size_t, AllocationEffort);
+
// [ 32... 256 ]
static const size_t preciseStep = MarkedBlock::atomSize;
static const size_t preciseCutoff = 256;
@@ -93,8 +106,8 @@ private:
FixedArray<SizeClass, impreciseCount> m_impreciseSizeClasses;
size_t m_waterMark;
size_t m_nurseryWaterMark;
- size_t m_highWaterMark;
Heap* m_heap;
+ MarkedBlockSet m_blocks;
};
inline size_t MarkedSpace::waterMark()
@@ -102,19 +115,25 @@ inline size_t MarkedSpace::waterMark()
return m_waterMark;
}
-inline size_t MarkedSpace::highWaterMark()
+inline size_t MarkedSpace::nurseryWaterMark()
{
- return m_highWaterMark;
+ return m_nurseryWaterMark;
}
-inline size_t MarkedSpace::nurseryWaterMark()
+template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachCell(Functor& functor)
{
- return m_nurseryWaterMark;
+ canonicalizeCellLivenessData();
+
+ BlockIterator end = m_blocks.set().end();
+ for (BlockIterator it = m_blocks.set().begin(); it != end; ++it)
+ (*it)->forEachCell(functor);
+ return functor.returnValue();
}
-inline void MarkedSpace::setHighWaterMark(size_t highWaterMark)
+template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachCell()
{
- m_highWaterMark = highWaterMark;
+ Functor functor;
+ return forEachCell(functor);
}
inline MarkedSpace::SizeClass& MarkedSpace::sizeClassFor(size_t bytes)
@@ -125,25 +144,19 @@ inline MarkedSpace::SizeClass& MarkedSpace::sizeClassFor(size_t bytes)
return m_impreciseSizeClasses[(bytes - 1) / impreciseStep];
}
+inline void* MarkedSpace::allocate(size_t bytes)
+{
+ SizeClass& sizeClass = sizeClassFor(bytes);
+ return allocate(sizeClass);
+}
+
inline void* MarkedSpace::allocate(SizeClass& sizeClass)
{
+ // This is a light-weight fast path to cover the most common case.
MarkedBlock::FreeCell* firstFreeCell = sizeClass.firstFreeCell;
- if (!firstFreeCell) {
- for (MarkedBlock*& block = sizeClass.currentBlock; block; block = block->next()) {
- firstFreeCell = block->sweep(MarkedBlock::SweepToFreeList);
- if (firstFreeCell)
- break;
- m_nurseryWaterMark += block->capacity() - block->size();
- m_waterMark += block->capacity();
- block->didConsumeFreeList();
- }
-
- if (!firstFreeCell)
- return 0;
- }
-
- ASSERT(firstFreeCell);
-
+ if (UNLIKELY(!firstFreeCell))
+ return allocateSlowCase(sizeClass);
+
sizeClass.firstFreeCell = firstFreeCell->next;
return firstFreeCell;
}
@@ -152,19 +165,19 @@ template <typename Functor> inline typename Functor::ReturnType MarkedSpace::for
{
for (size_t i = 0; i < preciseCount; ++i) {
SizeClass& sizeClass = m_preciseSizeClasses[i];
- MarkedBlock* next;
- for (MarkedBlock* block = sizeClass.blockList.head(); block; block = next) {
+ HeapBlock* next;
+ for (HeapBlock* block = sizeClass.blockList.head(); block; block = next) {
next = block->next();
- functor(block);
+ functor(static_cast<MarkedBlock*>(block));
}
}
for (size_t i = 0; i < impreciseCount; ++i) {
SizeClass& sizeClass = m_impreciseSizeClasses[i];
- MarkedBlock* next;
- for (MarkedBlock* block = sizeClass.blockList.head(); block; block = next) {
+ HeapBlock* next;
+ for (HeapBlock* block = sizeClass.blockList.head(); block; block = next) {
next = block->next();
- functor(block);
+ functor(static_cast<MarkedBlock*>(block));
}
}
@@ -186,7 +199,7 @@ inline MarkedSpace::SizeClass::SizeClass()
inline void MarkedSpace::SizeClass::resetAllocator()
{
- currentBlock = blockList.head();
+ currentBlock = static_cast<MarkedBlock*>(blockList.head());
}
inline void MarkedSpace::SizeClass::zapFreeList()
diff --git a/Source/JavaScriptCore/heap/SlotVisitor.h b/Source/JavaScriptCore/heap/SlotVisitor.h
index 142d8ca49..e49a9a637 100644
--- a/Source/JavaScriptCore/heap/SlotVisitor.h
+++ b/Source/JavaScriptCore/heap/SlotVisitor.h
@@ -26,6 +26,7 @@
#ifndef SlotVisitor_h
#define SlotVisitor_h
+#include "BumpSpace.h"
#include "MarkStack.h"
namespace JSC {
@@ -59,8 +60,15 @@ public:
void harvestWeakReferences();
void finalizeUnconditionalFinalizers();
+
+ void startCopying();
+ void copy(void**, size_t);
+ void copyAndAppend(void**, size_t, JSValue*, unsigned);
+ void doneCopying();
private:
+ void* allocateNewSpace(void*, size_t);
+
void donateSlow();
void donateKnownParallel()
@@ -69,10 +77,13 @@ private:
return;
donateSlow();
}
+
+ BumpBlock* m_copyBlock;
};
inline SlotVisitor::SlotVisitor(MarkStackThreadSharedData& shared)
: MarkStack(shared)
+ , m_copyBlock(0)
{
}
diff --git a/Source/JavaScriptCore/heap/TinyBloomFilter.h b/Source/JavaScriptCore/heap/TinyBloomFilter.h
index 82b586309..a75ce8ce5 100644
--- a/Source/JavaScriptCore/heap/TinyBloomFilter.h
+++ b/Source/JavaScriptCore/heap/TinyBloomFilter.h
@@ -36,6 +36,7 @@ public:
void add(Bits);
bool ruleOut(Bits) const; // True for 0.
+ void reset();
private:
Bits m_bits;
@@ -62,6 +63,11 @@ inline bool TinyBloomFilter::ruleOut(Bits bits) const
return false;
}
+inline void TinyBloomFilter::reset()
+{
+ m_bits = 0;
+}
+
} // namespace JSC
#endif // TinyBloomFilter_h
diff --git a/Source/JavaScriptCore/heap/VTableSpectrum.h b/Source/JavaScriptCore/heap/VTableSpectrum.h
index 8a9737e9b..a50a04f47 100644
--- a/Source/JavaScriptCore/heap/VTableSpectrum.h
+++ b/Source/JavaScriptCore/heap/VTableSpectrum.h
@@ -39,7 +39,7 @@ public:
~VTableSpectrum();
void countVPtr(void*);
- void count(JSCell*);
+ JS_EXPORT_PRIVATE void count(JSCell*);
void dump(FILE* output, const char* comment);
};
diff --git a/Source/JavaScriptCore/heap/WriteBarrierSupport.h b/Source/JavaScriptCore/heap/WriteBarrierSupport.h
index 00b9bb97f..5d7d2f6fe 100644
--- a/Source/JavaScriptCore/heap/WriteBarrierSupport.h
+++ b/Source/JavaScriptCore/heap/WriteBarrierSupport.h
@@ -81,8 +81,8 @@ public:
}
#else
// These are necessary to work around not having conditional exports.
- static char usesWithBarrierFromCpp;
- static char usesWithoutBarrierFromCpp;
+ JS_EXPORTDATA static char usesWithBarrierFromCpp;
+ JS_EXPORTDATA static char usesWithoutBarrierFromCpp;
#endif // ENABLE(WRITE_BARRIER_PROFILING)
static void countWriteBarrier()
diff --git a/Source/JavaScriptCore/interpreter/AbstractPC.cpp b/Source/JavaScriptCore/interpreter/AbstractPC.cpp
new file mode 100644
index 000000000..863915bda
--- /dev/null
+++ b/Source/JavaScriptCore/interpreter/AbstractPC.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 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 "AbstractPC.h"
+
+#include "CallFrame.h"
+#include "JSGlobalData.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
+
+namespace JSC {
+
+AbstractPC::AbstractPC(JSGlobalData& globalData, ExecState* exec)
+{
+ UNUSED_PARAM(globalData);
+
+#if ENABLE(JIT)
+ if (globalData.canUseJIT()) {
+ m_pointer = exec->returnPC().value();
+ m_mode = JIT;
+ return;
+ }
+#endif
+
+#if ENABLE(INTERPRETER)
+ m_pointer = exec->returnVPC();
+ m_mode = Interpreter;
+#endif
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/interpreter/AbstractPC.h b/Source/JavaScriptCore/interpreter/AbstractPC.h
new file mode 100644
index 000000000..dffaaf343
--- /dev/null
+++ b/Source/JavaScriptCore/interpreter/AbstractPC.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2012 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 AbstractPC_h
+#define AbstractPC_h
+
+#include "MacroAssemblerCodeRef.h"
+#include <wtf/Platform.h>
+
+namespace JSC {
+
+class JSGlobalData;
+class ExecState;
+struct Instruction;
+
+class AbstractPC {
+public:
+ AbstractPC()
+ : m_pointer(0)
+ , m_mode(None)
+ {
+ }
+
+ AbstractPC(JSGlobalData&, ExecState*);
+
+#if ENABLE(JIT)
+ AbstractPC(ReturnAddressPtr ptr)
+ : m_pointer(ptr.value())
+ , m_mode(JIT)
+ {
+ }
+
+ bool hasJITReturnAddress() const { return m_mode == JIT; }
+ ReturnAddressPtr jitReturnAddress() const
+ {
+ ASSERT(hasJITReturnAddress());
+ return ReturnAddressPtr(m_pointer);
+ }
+#endif
+
+#if ENABLE(INTERPRETER)
+ AbstractPC(Instruction* vPC)
+ : m_pointer(vPC)
+ , m_mode(Interpreter)
+ {
+ }
+
+ bool hasInterpreterReturnAddress() const { return m_mode == Interpreter; }
+ Instruction* interpreterReturnAddress() const
+ {
+ ASSERT(hasInterpreterReturnAddress());
+ return static_cast<Instruction*>(m_pointer);
+ }
+#endif
+
+ bool isSet() const { return m_mode != None; }
+ bool operator!() const { return !isSet(); }
+
+private:
+ void* m_pointer;
+
+ enum Mode { None, JIT, Interpreter };
+ Mode m_mode;
+};
+
+} // namespace JSC
+
+#endif // AbstractPC_h
+
diff --git a/Source/JavaScriptCore/interpreter/CallFrame.cpp b/Source/JavaScriptCore/interpreter/CallFrame.cpp
index 6dba77898..3ef5bd26f 100644
--- a/Source/JavaScriptCore/interpreter/CallFrame.cpp
+++ b/Source/JavaScriptCore/interpreter/CallFrame.cpp
@@ -61,53 +61,66 @@ bool CallFrame::isInlineCallFrameSlow()
JSFunction* calleeAsFunction = asFunction(calleeAsFunctionCell);
return calleeAsFunction->executable() != codeBlock()->ownerExecutable();
}
-
-CallFrame* CallFrame::trueCallerFrame()
+
+CallFrame* CallFrame::trueCallFrame(AbstractPC pc)
{
- // this -> The callee; this is either an inlined callee in which case it already has
- // a pointer to the true caller. Otherwise it contains current PC in the machine
- // caller.
- //
- // machineCaller -> The caller according to the machine, which may be zero or
- // more frames above the true caller due to inlining.
- //
- // trueCaller -> The real caller.
-
// Am I an inline call frame? If so, we're done.
if (isInlineCallFrame())
- return callerFrame();
+ return this;
- // I am a machine call frame, so the question is: is my caller a machine call frame
- // that has inlines or a machine call frame that doesn't?
- CallFrame* machineCaller = callerFrame()->removeHostCallFrameFlag();
- if (!machineCaller)
- return 0;
- ASSERT(!machineCaller->isInlineCallFrame());
- if (!machineCaller->codeBlock())
- return machineCaller;
- if (!machineCaller->codeBlock()->hasCodeOrigins())
- return machineCaller; // No inlining, so machineCaller == trueCaller
+ // If I don't have a code block, then I'm not DFG code, so I'm the true call frame.
+ CodeBlock* machineCodeBlock = codeBlock();
+ if (!machineCodeBlock)
+ return this;
- // Figure out where the caller frame would have gone relative to the machine
- // caller, and rematerialize it. Do so for the entire inline stack.
+ // If the code block does not have any code origins, then there was no inlining, so
+ // I'm done.
+ if (!machineCodeBlock->hasCodeOrigins())
+ return this;
- CodeOrigin codeOrigin = machineCaller->codeBlock()->codeOriginForReturn(returnPC());
+ // At this point the PC must be due either to the DFG, or it must be unset.
+ ASSERT(pc.hasJITReturnAddress() || !pc);
+
+ // Try to determine the CodeOrigin. If we don't have a pc set then the only way
+ // that this makes sense is if the CodeOrigin index was set in the call frame.
+ // FIXME: Note that you will see "Not currently in inlined code" comments below.
+ // Currently, we do not record code origins for code that is not inlined, because
+ // the only thing that we use code origins for is determining the inline stack.
+ // But in the future, we'll want to use this same functionality (having a code
+ // origin mapping for any calls out of JIT code) to determine the PC at any point
+ // in the stack even if not in inlined code. When that happens, the code below
+ // will have to change the way it detects the presence of inlining: it will always
+ // get a code origin, but sometimes, that code origin will not have an inline call
+ // frame. In that case, this method should bail and return this.
+ CodeOrigin codeOrigin;
+ if (pc.isSet()) {
+ ReturnAddressPtr currentReturnPC = pc.jitReturnAddress();
+
+ if (!machineCodeBlock->codeOriginForReturn(currentReturnPC, codeOrigin))
+ return this; // Not currently in inlined code.
+ } else {
+ unsigned index = codeOriginIndexForDFGWithInlining();
+ if (index == UINT_MAX)
+ return this; // Not currently in inlined code.
+
+ codeOrigin = machineCodeBlock->codeOrigin(index);
+ }
for (InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame; inlineCallFrame;) {
InlineCallFrame* nextInlineCallFrame = inlineCallFrame->caller.inlineCallFrame;
- CallFrame* inlinedCaller = machineCaller + inlineCallFrame->stackOffset;
+ CallFrame* inlinedCaller = this + inlineCallFrame->stackOffset;
JSFunction* calleeAsFunction = inlineCallFrame->callee.get();
// Fill in the inlinedCaller
- inlinedCaller->setCodeBlock(machineCaller->codeBlock());
+ inlinedCaller->setCodeBlock(machineCodeBlock);
inlinedCaller->setScopeChain(calleeAsFunction->scope());
if (nextInlineCallFrame)
- inlinedCaller->setCallerFrame(machineCaller + nextInlineCallFrame->stackOffset);
+ inlinedCaller->setCallerFrame(this + nextInlineCallFrame->stackOffset);
else
- inlinedCaller->setCallerFrame(machineCaller);
+ inlinedCaller->setCallerFrame(this);
inlinedCaller->setInlineCallFrame(inlineCallFrame);
inlinedCaller->setArgumentCountIncludingThis(inlineCallFrame->arguments.size());
@@ -116,7 +129,34 @@ CallFrame* CallFrame::trueCallerFrame()
inlineCallFrame = nextInlineCallFrame;
}
- return machineCaller + codeOrigin.inlineCallFrame->stackOffset;
+ return this + codeOrigin.inlineCallFrame->stackOffset;
+}
+
+CallFrame* CallFrame::trueCallerFrame()
+{
+ // this -> The callee; this is either an inlined callee in which case it already has
+ // a pointer to the true caller. Otherwise it contains current PC in the machine
+ // caller.
+ //
+ // machineCaller -> The caller according to the machine, which may be zero or
+ // more frames above the true caller due to inlining.
+
+ // Am I an inline call frame? If so, we're done.
+ if (isInlineCallFrame())
+ return callerFrame();
+
+ // I am a machine call frame, so the question is: is my caller a machine call frame
+ // that has inlines or a machine call frame that doesn't?
+ CallFrame* machineCaller = callerFrame()->removeHostCallFrameFlag();
+ if (!machineCaller)
+ return 0;
+ ASSERT(!machineCaller->isInlineCallFrame());
+
+ // Figure out how we want to get the current code location.
+ if (hasHostCallFrameFlag() || returnAddressIsInCtiTrampoline(returnPC()))
+ return machineCaller->trueCallFrameFromVMCode();
+
+ return machineCaller->trueCallFrame(returnPC());
}
#endif
diff --git a/Source/JavaScriptCore/interpreter/CallFrame.h b/Source/JavaScriptCore/interpreter/CallFrame.h
index d5037b794..e0a291f8b 100644
--- a/Source/JavaScriptCore/interpreter/CallFrame.h
+++ b/Source/JavaScriptCore/interpreter/CallFrame.h
@@ -23,6 +23,7 @@
#ifndef CallFrame_h
#define CallFrame_h
+#include "AbstractPC.h"
#include "JSGlobalData.h"
#include "MacroAssemblerCodeRef.h"
#include "RegisterFile.h"
@@ -104,8 +105,10 @@ namespace JSC {
#if ENABLE(JIT)
ReturnAddressPtr returnPC() const { return ReturnAddressPtr(this[RegisterFile::ReturnPC].vPC()); }
#endif
+ AbstractPC abstractReturnPC(JSGlobalData& globalData) { return AbstractPC(globalData, this); }
#if ENABLE(DFG_JIT)
InlineCallFrame* inlineCallFrame() const { return this[RegisterFile::ReturnPC].asInlineCallFrame(); }
+ unsigned codeOriginIndexForDFGWithInlining() const { return this[RegisterFile::ArgumentCount].tag(); }
#else
// This will never be called if !ENABLE(DFG_JIT) since all calls should be guarded by
// isInlineCallFrame(). But to make it easier to write code without having a bunch of
@@ -185,14 +188,30 @@ namespace JSC {
void setInlineCallFrame(InlineCallFrame* inlineCallFrame) { static_cast<Register*>(this)[RegisterFile::ReturnPC] = inlineCallFrame; }
- // Call this to get the semantically correct JS CallFrame*. This resolves issues
- // surrounding inlining and the HostCallFrameFlag stuff.
+ // Call this to get the semantically correct JS CallFrame* for the
+ // currently executing function.
+ CallFrame* trueCallFrame(AbstractPC);
+
+ // Call this to get the semantically correct JS CallFrame* corresponding
+ // to the caller. This resolves issues surrounding inlining and the
+ // HostCallFrameFlag stuff.
CallFrame* trueCallerFrame();
#else
bool isInlineCallFrame() { return false; }
+ CallFrame* trueCallFrame(AbstractPC) { return this; }
CallFrame* trueCallerFrame() { return callerFrame()->removeHostCallFrameFlag(); }
#endif
+
+ // Call this to get the true call frame (accounted for inlining and any
+ // other optimizations), when you have entered into VM code through one
+ // of the "blessed" entrypoints (JITStubs or DFGOperations). This means
+ // that if you're pretty much anywhere in the VM you can safely call this;
+ // though if you were to magically get an ExecState* by, say, interrupting
+ // a thread that is running JS code and brutishly scraped the call frame
+ // register, calling this method would probably lead to horrible things
+ // happening.
+ CallFrame* trueCallFrameFromVMCode() { return trueCallFrame(AbstractPC()); }
private:
static const intptr_t HostCallFrameFlag = 1;
diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp
index 980bf8a1a..51843f2d2 100644
--- a/Source/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp
@@ -905,7 +905,7 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S
PutPropertySlot slot;
globalObject->methodTable()->put(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, slot);
} else
- globalObject->methodTable()->putWithAttributes(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, DontEnum | DontDelete);
+ globalObject->methodTable()->putDirectVirtual(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, DontEnum | DontDelete);
// var declarations return undefined
result = jsUndefined();
continue;
@@ -1324,7 +1324,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
JSObject* variableObject;
for (ScopeChainNode* node = scopeChain; ; node = node->next.get()) {
ASSERT(node);
- if (node->object->isVariableObject()) {
+ if (node->object->isVariableObject() && !node->object->isStaticScopeObject()) {
variableObject = static_cast<JSVariableObject*>(node->object.get());
break;
}
@@ -2579,7 +2579,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
if (propName.getUInt32(i))
callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, i));
else {
- Identifier property(callFrame, propName.toString(callFrame));
+ Identifier property(callFrame, propName.toString(callFrame)->value(callFrame));
CHECK_FOR_EXCEPTION();
callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, property));
}
@@ -3310,9 +3310,10 @@ skip_id_custom_self:
JSValue baseValue = callFrame->r(base).jsValue();
Identifier& ident = codeBlock->identifier(property);
PutPropertySlot slot(codeBlock->isStrictMode());
- if (direct)
- baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot);
- else
+ if (direct) {
+ ASSERT(baseValue.isObject());
+ asObject(baseValue)->putDirect(*globalData, ident, callFrame->r(value).jsValue(), slot);
+ } else
baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
CHECK_FOR_EXCEPTION();
@@ -3428,9 +3429,10 @@ skip_id_custom_self:
JSValue baseValue = callFrame->r(base).jsValue();
Identifier& ident = codeBlock->identifier(property);
PutPropertySlot slot(codeBlock->isStrictMode());
- if (direct)
- baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot);
- else
+ if (direct) {
+ ASSERT(baseValue.isObject());
+ asObject(baseValue)->putDirect(*globalData, ident, callFrame->r(value).jsValue(), slot);
+ } else
baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
CHECK_FOR_EXCEPTION();
@@ -3482,7 +3484,7 @@ skip_id_custom_self:
NEXT_INSTRUCTION();
}
{
- Identifier propertyName(callFrame, subscript.toString(callFrame));
+ Identifier propertyName(callFrame, subscript.toString(callFrame)->value(callFrame));
result = baseValue.get(callFrame, propertyName);
}
CHECK_FOR_EXCEPTION();
@@ -3557,7 +3559,7 @@ skip_id_custom_self:
else
result = baseValue.get(callFrame, i);
} else {
- Identifier property(callFrame, subscript.toString(callFrame));
+ Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
result = baseValue.get(callFrame, property);
}
@@ -3604,7 +3606,7 @@ skip_id_custom_self:
} else
baseValue.put(callFrame, i, callFrame->r(value).jsValue());
} else {
- Identifier property(callFrame, subscript.toString(callFrame));
+ Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
if (!globalData->exception) { // Don't put to an object if toString threw an exception.
PutPropertySlot slot(codeBlock->isStrictMode());
baseValue.put(callFrame, property, callFrame->r(value).jsValue(), slot);
@@ -3636,7 +3638,7 @@ skip_id_custom_self:
result = baseObj->methodTable()->deletePropertyByIndex(baseObj, callFrame, i);
else {
CHECK_FOR_EXCEPTION();
- Identifier property(callFrame, subscript.toString(callFrame));
+ Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
CHECK_FOR_EXCEPTION();
result = baseObj->methodTable()->deleteProperty(baseObj, callFrame, property);
}
@@ -4943,7 +4945,7 @@ skip_id_custom_self:
original constructor, using constant message as the
message string. The result is thrown.
*/
- UString message = callFrame->r(vPC[1].u.operand).jsValue().toString(callFrame);
+ UString message = callFrame->r(vPC[1].u.operand).jsValue().toString(callFrame)->value(callFrame);
exceptionValue = JSValue(createReferenceError(callFrame, message));
goto vm_throw;
}
@@ -4957,52 +4959,41 @@ skip_id_custom_self:
int result = vPC[1].u.operand;
return callFrame->r(result).jsValue();
}
- DEFINE_OPCODE(op_put_getter) {
- /* put_getter base(r) property(id) function(r)
+ DEFINE_OPCODE(op_put_getter_setter) {
+ /* put_getter_setter base(r) property(id) getter(r) setter(r)
- Sets register function on register base as the getter named
- by identifier property. Base and function are assumed to be
- objects as this op should only be used for getters defined
- in object literal form.
+ Puts accessor descriptor to register base as the named
+ identifier property. Base and function may be objects
+ or undefined, this op should only be used for accessors
+ defined in object literal form.
Unlike many opcodes, this one does not write any output to
the register file.
*/
int base = vPC[1].u.operand;
int property = vPC[2].u.operand;
- int function = vPC[3].u.operand;
+ int getterReg = vPC[3].u.operand;
+ int setterReg = vPC[4].u.operand;
ASSERT(callFrame->r(base).jsValue().isObject());
JSObject* baseObj = asObject(callFrame->r(base).jsValue());
Identifier& ident = codeBlock->identifier(property);
- ASSERT(callFrame->r(function).jsValue().isObject());
- baseObj->methodTable()->defineGetter(baseObj, callFrame, ident, asObject(callFrame->r(function).jsValue()), 0);
- vPC += OPCODE_LENGTH(op_put_getter);
- NEXT_INSTRUCTION();
- }
- DEFINE_OPCODE(op_put_setter) {
- /* put_setter base(r) property(id) function(r)
+ GetterSetter* accessor = GetterSetter::create(callFrame);
- Sets register function on register base as the setter named
- by identifier property. Base and function are assumed to be
- objects as this op should only be used for setters defined
- in object literal form.
+ JSValue getter = callFrame->r(getterReg).jsValue();
+ JSValue setter = callFrame->r(setterReg).jsValue();
+ ASSERT(getter.isObject() || getter.isUndefined());
+ ASSERT(setter.isObject() || setter.isUndefined());
+ ASSERT(getter.isObject() || setter.isObject());
- Unlike many opcodes, this one does not write any output to
- the register file.
- */
- int base = vPC[1].u.operand;
- int property = vPC[2].u.operand;
- int function = vPC[3].u.operand;
-
- ASSERT(callFrame->r(base).jsValue().isObject());
- JSObject* baseObj = asObject(callFrame->r(base).jsValue());
- Identifier& ident = codeBlock->identifier(property);
- ASSERT(callFrame->r(function).jsValue().isObject());
- baseObj->methodTable()->defineSetter(baseObj, callFrame, ident, asObject(callFrame->r(function).jsValue()), 0);
+ if (!getter.isUndefined())
+ accessor->setGetter(callFrame->globalData(), asObject(getter));
+ if (!setter.isUndefined())
+ accessor->setSetter(callFrame->globalData(), asObject(setter));
+ baseObj->putDirectAccessor(callFrame->globalData(), ident, accessor, Accessor);
- vPC += OPCODE_LENGTH(op_put_setter);
+ vPC += OPCODE_LENGTH(op_put_getter_setter);
NEXT_INSTRUCTION();
}
DEFINE_OPCODE(op_method_check) {
@@ -5106,9 +5097,9 @@ skip_id_custom_self:
#endif // ENABLE(INTERPRETER)
}
-JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* function) const
+JSValue Interpreter::retrieveArgumentsFromVMCode(CallFrame* callFrame, JSFunction* function) const
{
- CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
+ CallFrame* functionCallFrame = findFunctionCallFrameFromVMCode(callFrame, function);
if (!functionCallFrame)
return jsNull();
@@ -5130,9 +5121,9 @@ JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* functio
return JSValue(arguments);
}
-JSValue Interpreter::retrieveCaller(CallFrame* callFrame, JSFunction* function) const
+JSValue Interpreter::retrieveCallerFromVMCode(CallFrame* callFrame, JSFunction* function) const
{
- CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
+ CallFrame* functionCallFrame = findFunctionCallFrameFromVMCode(callFrame, function);
if (!functionCallFrame)
return jsNull();
@@ -5177,9 +5168,9 @@ void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intp
function = callerFrame->callee();
}
-CallFrame* Interpreter::findFunctionCallFrame(CallFrame* callFrame, JSFunction* function)
+CallFrame* Interpreter::findFunctionCallFrameFromVMCode(CallFrame* callFrame, JSFunction* function)
{
- for (CallFrame* candidate = callFrame; candidate; candidate = candidate->trueCallerFrame()) {
+ for (CallFrame* candidate = callFrame->trueCallFrameFromVMCode(); candidate; candidate = candidate->trueCallerFrame()) {
if (candidate->callee() == function)
return candidate;
}
diff --git a/Source/JavaScriptCore/interpreter/Interpreter.h b/Source/JavaScriptCore/interpreter/Interpreter.h
index 6dfd331f8..1943513ae 100644
--- a/Source/JavaScriptCore/interpreter/Interpreter.h
+++ b/Source/JavaScriptCore/interpreter/Interpreter.h
@@ -79,6 +79,16 @@ namespace JSC {
JSGlobalData& globalData;
CallFrame* oldCallFrame;
};
+
+ class NativeCallFrameTracer {
+ public:
+ ALWAYS_INLINE NativeCallFrameTracer(JSGlobalData* global, CallFrame* callFrame)
+ {
+ ASSERT(global);
+ ASSERT(callFrame);
+ global->topCallFrame = callFrame;
+ }
+ };
#if PLATFORM(IOS)
// We use a smaller reentrancy limit on iPhone because of the high amount of
@@ -131,8 +141,8 @@ namespace JSC {
JSValue execute(EvalExecutable*, CallFrame*, JSValue thisValue, ScopeChainNode*);
JSValue execute(EvalExecutable*, CallFrame*, JSValue thisValue, ScopeChainNode*, int globalRegisterOffset);
- JSValue retrieveArguments(CallFrame*, JSFunction*) const;
- JS_EXPORT_PRIVATE JSValue retrieveCaller(CallFrame*, JSFunction*) const;
+ JSValue retrieveArgumentsFromVMCode(CallFrame*, JSFunction*) const;
+ JS_EXPORT_PRIVATE JSValue retrieveCallerFromVMCode(CallFrame*, JSFunction*) const;
JS_EXPORT_PRIVATE void retrieveLastCaller(CallFrame*, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValue& function) const;
void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
@@ -172,7 +182,7 @@ namespace JSC {
static ALWAYS_INLINE CallFrame* slideRegisterWindowForCall(CodeBlock*, RegisterFile*, CallFrame*, size_t registerOffset, int argc);
- static CallFrame* findFunctionCallFrame(CallFrame*, JSFunction*);
+ static CallFrame* findFunctionCallFrameFromVMCode(CallFrame*, JSFunction*);
JSValue privateExecute(ExecutionFlag, RegisterFile*, CallFrame*);
diff --git a/Source/JavaScriptCore/jit/ExecutableAllocator.cpp b/Source/JavaScriptCore/jit/ExecutableAllocator.cpp
index 82c149d0e..75137279e 100644
--- a/Source/JavaScriptCore/jit/ExecutableAllocator.cpp
+++ b/Source/JavaScriptCore/jit/ExecutableAllocator.cpp
@@ -28,6 +28,7 @@
#include "ExecutableAllocator.h"
#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
+#include "CodeProfiling.h"
#include <wtf/MetaAllocator.h>
#include <wtf/PageReservation.h>
#include <wtf/VMTags.h>
@@ -93,6 +94,7 @@ void ExecutableAllocator::initializeAllocator()
{
ASSERT(!allocator);
allocator = new DemandExecutableAllocator();
+ CodeProfiling::notifyAllocator(allocator);
}
ExecutableAllocator::ExecutableAllocator(JSGlobalData&)
@@ -110,9 +112,9 @@ bool ExecutableAllocator::underMemoryPressure()
return false;
}
-PassRefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(JSGlobalData&, size_t sizeInBytes)
+PassRefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(JSGlobalData&, size_t sizeInBytes, void* ownerUID)
{
- RefPtr<ExecutableMemoryHandle> result = allocator->allocate(sizeInBytes);
+ RefPtr<ExecutableMemoryHandle> result = allocator->allocate(sizeInBytes, ownerUID);
if (!result)
CRASH();
return result.release();
diff --git a/Source/JavaScriptCore/jit/ExecutableAllocator.h b/Source/JavaScriptCore/jit/ExecutableAllocator.h
index 876bda62e..bc8b816c8 100644
--- a/Source/JavaScriptCore/jit/ExecutableAllocator.h
+++ b/Source/JavaScriptCore/jit/ExecutableAllocator.h
@@ -113,7 +113,7 @@ public:
static void dumpProfile() { }
#endif
- PassRefPtr<ExecutableMemoryHandle> allocate(JSGlobalData&, size_t sizeInBytes);
+ PassRefPtr<ExecutableMemoryHandle> allocate(JSGlobalData&, size_t sizeInBytes, void* ownerUID);
#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
static void makeWritable(void* start, size_t size)
@@ -130,7 +130,6 @@ public:
static void makeExecutable(void*, size_t) {}
#endif
-
#if CPU(X86) || CPU(X86_64)
static void cacheFlush(void*, size_t)
{
diff --git a/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp b/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp
index 3771c74a9..3fe631e3b 100644
--- a/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp
+++ b/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp
@@ -29,8 +29,8 @@
#if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
+#include "CodeProfiling.h"
#include <errno.h>
-
#include <sys/mman.h>
#include <unistd.h>
#include <wtf/MetaAllocator.h>
@@ -96,6 +96,7 @@ void ExecutableAllocator::initializeAllocator()
{
ASSERT(!allocator);
allocator = new FixedVMPoolExecutableAllocator();
+ CodeProfiling::notifyAllocator(allocator);
}
ExecutableAllocator::ExecutableAllocator(JSGlobalData&)
@@ -114,12 +115,12 @@ bool ExecutableAllocator::underMemoryPressure()
return statistics.bytesAllocated > statistics.bytesReserved / 2;
}
-PassRefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(JSGlobalData& globalData, size_t sizeInBytes)
+PassRefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(JSGlobalData& globalData, size_t sizeInBytes, void* ownerUID)
{
- RefPtr<ExecutableMemoryHandle> result = allocator->allocate(sizeInBytes);
+ RefPtr<ExecutableMemoryHandle> result = allocator->allocate(sizeInBytes, ownerUID);
if (!result) {
releaseExecutableMemory(globalData);
- result = allocator->allocate(sizeInBytes);
+ result = allocator->allocate(sizeInBytes, ownerUID);
if (!result)
CRASH();
}
diff --git a/Source/JavaScriptCore/jit/JIT.cpp b/Source/JavaScriptCore/jit/JIT.cpp
index 025b5b706..247495aaf 100644
--- a/Source/JavaScriptCore/jit/JIT.cpp
+++ b/Source/JavaScriptCore/jit/JIT.cpp
@@ -99,7 +99,7 @@ void JIT::emitOptimizationCheck(OptimizationCheckKind kind)
if (!shouldEmitProfiling())
return;
- Jump skipOptimize = branchAdd32(Signed, TrustedImm32(kind == LoopOptimizationCheck ? Options::executionCounterIncrementForLoop : Options::executionCounterIncrementForReturn), AbsoluteAddress(m_codeBlock->addressOfExecuteCounter()));
+ Jump skipOptimize = branchAdd32(Signed, TrustedImm32(kind == LoopOptimizationCheck ? Options::executionCounterIncrementForLoop : Options::executionCounterIncrementForReturn), AbsoluteAddress(m_codeBlock->addressOfJITExecuteCounter()));
JITStubCall stubCall(this, kind == LoopOptimizationCheck ? cti_optimize_from_loop : cti_optimize_from_ret);
if (kind == LoopOptimizationCheck)
stubCall.addArgument(Imm32(m_bytecodeOffset));
@@ -328,10 +328,9 @@ void JIT::privateCompileMainPass()
DEFINE_OP(op_put_by_id)
DEFINE_OP(op_put_by_index)
DEFINE_OP(op_put_by_val)
- DEFINE_OP(op_put_getter)
+ DEFINE_OP(op_put_getter_setter)
DEFINE_OP(op_put_global_var)
DEFINE_OP(op_put_scoped_var)
- DEFINE_OP(op_put_setter)
DEFINE_OP(op_resolve)
DEFINE_OP(op_resolve_base)
DEFINE_OP(op_ensure_property_exists)
@@ -614,7 +613,7 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck)
ASSERT(m_jmpTable.isEmpty());
- LinkBuffer patchBuffer(*m_globalData, this);
+ LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
// Translate vPC offsets into addresses in JIT generated code, for switch tables.
for (unsigned i = 0; i < m_switches.size(); ++i) {
diff --git a/Source/JavaScriptCore/jit/JIT.h b/Source/JavaScriptCore/jit/JIT.h
index 750b9d818..c357e8c39 100644
--- a/Source/JavaScriptCore/jit/JIT.h
+++ b/Source/JavaScriptCore/jit/JIT.h
@@ -333,14 +333,15 @@ namespace JSC {
template<typename T> void emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID storagePtr);
void emitAllocateJSFunction(FunctionExecutable*, RegisterID scopeChain, RegisterID result, RegisterID storagePtr);
- enum ValueProfilingSiteKind { FirstProfilingSite, SubsequentProfilingSite };
#if ENABLE(VALUE_PROFILER)
// This assumes that the value to profile is in regT0 and that regT3 is available for
// scratch.
void emitValueProfilingSite(ValueProfile*);
- void emitValueProfilingSite(ValueProfilingSiteKind);
+ void emitValueProfilingSite(unsigned bytecodeOffset);
+ void emitValueProfilingSite();
#else
- void emitValueProfilingSite(ValueProfilingSiteKind) { }
+ void emitValueProfilingSite(unsigned) { }
+ void emitValueProfilingSite() { }
#endif
#if USE(JSVALUE32_64)
@@ -856,10 +857,9 @@ namespace JSC {
void emit_op_put_by_id(Instruction*);
void emit_op_put_by_index(Instruction*);
void emit_op_put_by_val(Instruction*);
- void emit_op_put_getter(Instruction*);
+ void emit_op_put_getter_setter(Instruction*);
void emit_op_put_global_var(Instruction*);
void emit_op_put_scoped_var(Instruction*);
- void emit_op_put_setter(Instruction*);
void emit_op_resolve(Instruction*);
void emit_op_resolve_base(Instruction*);
void emit_op_ensure_property_exists(Instruction*);
diff --git a/Source/JavaScriptCore/jit/JITCall.cpp b/Source/JavaScriptCore/jit/JITCall.cpp
index 465f1add8..69dc9540e 100644
--- a/Source/JavaScriptCore/jit/JITCall.cpp
+++ b/Source/JavaScriptCore/jit/JITCall.cpp
@@ -50,8 +50,10 @@ namespace JSC {
void JIT::emit_op_call_put_result(Instruction* instruction)
{
int dst = instruction[1].u.operand;
- emitValueProfilingSite(FirstProfilingSite);
+ emitValueProfilingSite();
emitPutVirtualRegister(dst);
+ if (canBeOptimized())
+ killLastResultRegister(); // Make lastResultRegister tracking simpler in the DFG.
}
void JIT::compileLoadVarargs(Instruction* instruction)
diff --git a/Source/JavaScriptCore/jit/JITCall32_64.cpp b/Source/JavaScriptCore/jit/JITCall32_64.cpp
index 01c9db094..b84ad1a49 100644
--- a/Source/JavaScriptCore/jit/JITCall32_64.cpp
+++ b/Source/JavaScriptCore/jit/JITCall32_64.cpp
@@ -50,7 +50,7 @@ namespace JSC {
void JIT::emit_op_call_put_result(Instruction* instruction)
{
int dst = instruction[1].u.operand;
- emitValueProfilingSite(FirstProfilingSite);
+ emitValueProfilingSite();
emitStore(dst, regT1, regT0);
}
diff --git a/Source/JavaScriptCore/jit/JITDriver.h b/Source/JavaScriptCore/jit/JITDriver.h
new file mode 100644
index 000000000..7e010cdfe
--- /dev/null
+++ b/Source/JavaScriptCore/jit/JITDriver.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2012 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 JITDriver_h
+#define JITDriver_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(JIT)
+
+#include "BytecodeGenerator.h"
+#include "DFGDriver.h"
+#include "JIT.h"
+
+namespace JSC {
+
+template<typename CodeBlockType>
+inline bool jitCompileIfAppropriate(JSGlobalData& globalData, OwnPtr<CodeBlockType>& codeBlock, JITCode& jitCode, JITCode::JITType jitType)
+{
+ if (!globalData.canUseJIT())
+ return true;
+
+ bool dfgCompiled = false;
+ if (jitType == JITCode::DFGJIT)
+ dfgCompiled = DFG::tryCompile(globalData, codeBlock.get(), jitCode);
+ if (dfgCompiled) {
+ if (codeBlock->alternative())
+ codeBlock->alternative()->unlinkIncomingCalls();
+ } else {
+ if (codeBlock->alternative()) {
+ codeBlock = static_pointer_cast<CodeBlockType>(codeBlock->releaseAlternative());
+ return false;
+ }
+ jitCode = JIT::compile(&globalData, codeBlock.get());
+ }
+#if !ENABLE(OPCODE_SAMPLING)
+ if (!BytecodeGenerator::dumpsGeneratedCode())
+ codeBlock->handleBytecodeDiscardingOpportunity();
+#endif
+ codeBlock->setJITCode(jitCode, MacroAssemblerCodePtr());
+
+ return true;
+}
+
+inline bool jitCompileFunctionIfAppropriate(JSGlobalData& globalData, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType)
+{
+ if (!globalData.canUseJIT())
+ return true;
+
+ bool dfgCompiled = false;
+ if (jitType == JITCode::DFGJIT)
+ dfgCompiled = DFG::tryCompileFunction(globalData, codeBlock.get(), jitCode, jitCodeWithArityCheck);
+ if (dfgCompiled) {
+ if (codeBlock->alternative())
+ codeBlock->alternative()->unlinkIncomingCalls();
+ } else {
+ if (codeBlock->alternative()) {
+ codeBlock = static_pointer_cast<FunctionCodeBlock>(codeBlock->releaseAlternative());
+ symbolTable = codeBlock->sharedSymbolTable();
+ return false;
+ }
+ jitCode = JIT::compile(&globalData, codeBlock.get(), &jitCodeWithArityCheck);
+ }
+#if !ENABLE(OPCODE_SAMPLING)
+ if (!BytecodeGenerator::dumpsGeneratedCode())
+ codeBlock->handleBytecodeDiscardingOpportunity();
+#endif
+
+ codeBlock->setJITCode(jitCode, jitCodeWithArityCheck);
+
+ return true;
+}
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
+#endif // JITDriver_h
+
diff --git a/Source/JavaScriptCore/jit/JITInlineMethods.h b/Source/JavaScriptCore/jit/JITInlineMethods.h
index 5540ffab3..e617961b5 100644
--- a/Source/JavaScriptCore/jit/JITInlineMethods.h
+++ b/Source/JavaScriptCore/jit/JITInlineMethods.h
@@ -486,20 +486,16 @@ inline void JIT::emitValueProfilingSite(ValueProfile* valueProfile)
#endif
}
-inline void JIT::emitValueProfilingSite(ValueProfilingSiteKind siteKind)
+inline void JIT::emitValueProfilingSite(unsigned bytecodeOffset)
{
if (!shouldEmitProfiling())
return;
-
- ValueProfile* valueProfile;
- if (siteKind == FirstProfilingSite)
- valueProfile = m_codeBlock->addValueProfile(m_bytecodeOffset);
- else {
- ASSERT(siteKind == SubsequentProfilingSite);
- valueProfile = m_codeBlock->valueProfileForBytecodeOffset(m_bytecodeOffset);
- }
-
- emitValueProfilingSite(valueProfile);
+ emitValueProfilingSite(m_codeBlock->valueProfileForBytecodeOffset(bytecodeOffset));
+}
+
+inline void JIT::emitValueProfilingSite()
+{
+ emitValueProfilingSite(m_bytecodeOffset);
}
#endif
diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp
index f5be279a6..8a2077e47 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp
@@ -194,7 +194,7 @@ PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGl
Call string_failureCases3Call = makeTailRecursiveCall(string_failureCases3);
// All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
- LinkBuffer patchBuffer(*m_globalData, this);
+ LinkBuffer patchBuffer(*m_globalData, this, GLOBAL_THUNK_ID);
patchBuffer.link(string_failureCases1Call, FunctionPtr(cti_op_get_by_id_string_fail));
patchBuffer.link(string_failureCases2Call, FunctionPtr(cti_op_get_by_id_string_fail));
@@ -568,7 +568,7 @@ void JIT::emit_op_resolve(Instruction* currentInstruction)
{
JITStubCall stubCall(this, cti_op_resolve);
stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
- stubCall.callWithValueProfiling(currentInstruction[1].u.operand, FirstProfilingSite);
+ stubCall.callWithValueProfiling(currentInstruction[1].u.operand);
}
void JIT::emit_op_to_primitive(Instruction* currentInstruction)
@@ -599,7 +599,7 @@ void JIT::emit_op_resolve_base(Instruction* currentInstruction)
{
JITStubCall stubCall(this, currentInstruction[3].u.operand ? cti_op_resolve_base_strict_put : cti_op_resolve_base);
stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
- stubCall.callWithValueProfiling(currentInstruction[1].u.operand, FirstProfilingSite);
+ stubCall.callWithValueProfiling(currentInstruction[1].u.operand);
}
void JIT::emit_op_ensure_property_exists(Instruction* currentInstruction)
@@ -615,7 +615,7 @@ void JIT::emit_op_resolve_skip(Instruction* currentInstruction)
JITStubCall stubCall(this, cti_op_resolve_skip);
stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
- stubCall.callWithValueProfiling(currentInstruction[1].u.operand, FirstProfilingSite);
+ stubCall.callWithValueProfiling(currentInstruction[1].u.operand);
}
void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool)
@@ -636,7 +636,7 @@ void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool)
loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_propertyStorage)), regT0);
load32(Address(regT2, OBJECT_OFFSETOF(GlobalResolveInfo, offset)), regT1);
loadPtr(BaseIndex(regT0, regT1, ScalePtr), regT0);
- emitValueProfilingSite(FirstProfilingSite);
+ emitValueProfilingSite();
emitPutVirtualRegister(currentInstruction[1].u.operand);
}
@@ -652,7 +652,7 @@ void JIT::emitSlow_op_resolve_global(Instruction* currentInstruction, Vector<Slo
stubCall.addArgument(TrustedImmPtr(ident));
stubCall.addArgument(Imm32(currentIndex));
stubCall.addArgument(regT0);
- stubCall.callWithValueProfiling(dst, SubsequentProfilingSite);
+ stubCall.callWithValueProfiling(dst);
}
void JIT::emit_op_not(Instruction* currentInstruction)
@@ -773,7 +773,7 @@ void JIT::emit_op_resolve_with_base(Instruction* currentInstruction)
JITStubCall stubCall(this, cti_op_resolve_with_base);
stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
- stubCall.callWithValueProfiling(currentInstruction[2].u.operand, FirstProfilingSite);
+ stubCall.callWithValueProfiling(currentInstruction[2].u.operand);
}
void JIT::emit_op_resolve_with_this(Instruction* currentInstruction)
@@ -781,7 +781,7 @@ void JIT::emit_op_resolve_with_this(Instruction* currentInstruction)
JITStubCall stubCall(this, cti_op_resolve_with_this);
stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
- stubCall.callWithValueProfiling(currentInstruction[2].u.operand, FirstProfilingSite);
+ stubCall.callWithValueProfiling(currentInstruction[2].u.operand);
}
void JIT::emit_op_jtrue(Instruction* currentInstruction)
@@ -1563,7 +1563,7 @@ void JIT::emitSlow_op_resolve_global_dynamic(Instruction* currentInstruction, Ve
stubCall.addArgument(TrustedImmPtr(ident));
stubCall.addArgument(Imm32(currentIndex));
stubCall.addArgument(regT0);
- stubCall.callWithValueProfiling(dst, SubsequentProfilingSite); // The first profiling site is in emit_op_resolve_global
+ stubCall.callWithValueProfiling(dst);
}
void JIT::emit_op_new_regexp(Instruction* currentInstruction)
diff --git a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
index 9d1cbce8d..99594c3f1 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
@@ -193,7 +193,7 @@ PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGl
Call string_failureCases3Call = makeTailRecursiveCall(string_failureCases3);
// All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
- LinkBuffer patchBuffer(*m_globalData, this);
+ LinkBuffer patchBuffer(*m_globalData, this, GLOBAL_THUNK_ID);
patchBuffer.link(string_failureCases1Call, FunctionPtr(cti_op_get_by_id_string_fail));
patchBuffer.link(string_failureCases2Call, FunctionPtr(cti_op_get_by_id_string_fail));
@@ -492,7 +492,7 @@ JIT::CodeRef JIT::privateCompileCTINativeCall(JSGlobalData* globalData, NativeFu
ret();
// All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
- LinkBuffer patchBuffer(*m_globalData, this);
+ LinkBuffer patchBuffer(*m_globalData, this, GLOBAL_THUNK_ID);
patchBuffer.link(nativeCall, FunctionPtr(func));
return patchBuffer.finalizeCode();
@@ -660,7 +660,7 @@ void JIT::emit_op_resolve(Instruction* currentInstruction)
{
JITStubCall stubCall(this, cti_op_resolve);
stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
- stubCall.callWithValueProfiling(currentInstruction[1].u.operand, FirstProfilingSite);
+ stubCall.callWithValueProfiling(currentInstruction[1].u.operand);
}
void JIT::emit_op_to_primitive(Instruction* currentInstruction)
@@ -702,7 +702,7 @@ void JIT::emit_op_resolve_base(Instruction* currentInstruction)
{
JITStubCall stubCall(this, currentInstruction[3].u.operand ? cti_op_resolve_base_strict_put : cti_op_resolve_base);
stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
- stubCall.callWithValueProfiling(currentInstruction[1].u.operand, FirstProfilingSite);
+ stubCall.callWithValueProfiling(currentInstruction[1].u.operand);
}
void JIT::emit_op_ensure_property_exists(Instruction* currentInstruction)
@@ -718,7 +718,7 @@ void JIT::emit_op_resolve_skip(Instruction* currentInstruction)
JITStubCall stubCall(this, cti_op_resolve_skip);
stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
- stubCall.callWithValueProfiling(currentInstruction[1].u.operand, FirstProfilingSite);
+ stubCall.callWithValueProfiling(currentInstruction[1].u.operand);
}
void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool dynamic)
@@ -743,7 +743,7 @@ void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool dynamic)
load32(Address(regT3, OBJECT_OFFSETOF(GlobalResolveInfo, offset)), regT3);
load32(BaseIndex(regT2, regT3, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload
load32(BaseIndex(regT2, regT3, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); // tag
- emitValueProfilingSite(FirstProfilingSite);
+ emitValueProfilingSite();
emitStore(dst, regT1, regT0);
map(m_bytecodeOffset + (dynamic ? OPCODE_LENGTH(op_resolve_global_dynamic) : OPCODE_LENGTH(op_resolve_global)), dst, regT1, regT0);
}
@@ -759,7 +759,7 @@ void JIT::emitSlow_op_resolve_global(Instruction* currentInstruction, Vector<Slo
JITStubCall stubCall(this, cti_op_resolve_global);
stubCall.addArgument(TrustedImmPtr(ident));
stubCall.addArgument(Imm32(currentIndex));
- stubCall.callWithValueProfiling(dst, SubsequentProfilingSite);
+ stubCall.callWithValueProfiling(dst);
}
void JIT::emit_op_not(Instruction* currentInstruction)
@@ -1157,7 +1157,7 @@ void JIT::emit_op_resolve_with_base(Instruction* currentInstruction)
JITStubCall stubCall(this, cti_op_resolve_with_base);
stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
- stubCall.callWithValueProfiling(currentInstruction[2].u.operand, FirstProfilingSite);
+ stubCall.callWithValueProfiling(currentInstruction[2].u.operand);
}
void JIT::emit_op_resolve_with_this(Instruction* currentInstruction)
@@ -1165,7 +1165,7 @@ void JIT::emit_op_resolve_with_this(Instruction* currentInstruction)
JITStubCall stubCall(this, cti_op_resolve_with_this);
stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
- stubCall.callWithValueProfiling(currentInstruction[2].u.operand, FirstProfilingSite);
+ stubCall.callWithValueProfiling(currentInstruction[2].u.operand);
}
void JIT::emit_op_throw(Instruction* currentInstruction)
diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
index 48951e879..9fa29e2d9 100644
--- a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
+++ b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
@@ -86,7 +86,7 @@ JIT::CodeRef JIT::stringGetByValStubGenerator(JSGlobalData* globalData)
jit.move(TrustedImm32(0), regT0);
jit.ret();
- LinkBuffer patchBuffer(*globalData, &jit);
+ LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
return patchBuffer.finalizeCode();
}
@@ -116,7 +116,7 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction)
loadPtr(BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT0);
addSlowCase(branchTestPtr(Zero, regT0));
- emitValueProfilingSite(FirstProfilingSite);
+ emitValueProfilingSite();
emitPutVirtualRegister(dst);
}
@@ -147,7 +147,7 @@ void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCas
stubCall.addArgument(property, regT2);
stubCall.call(dst);
- emitValueProfilingSite(SubsequentProfilingSite);
+ emitValueProfilingSite();
}
void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID offset, RegisterID scratch)
@@ -261,21 +261,13 @@ void JIT::emit_op_put_by_index(Instruction* currentInstruction)
stubCall.call();
}
-void JIT::emit_op_put_getter(Instruction* currentInstruction)
+void JIT::emit_op_put_getter_setter(Instruction* currentInstruction)
{
- JITStubCall stubCall(this, cti_op_put_getter);
- stubCall.addArgument(currentInstruction[1].u.operand, regT2);
- stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
- stubCall.addArgument(currentInstruction[3].u.operand, regT2);
- stubCall.call();
-}
-
-void JIT::emit_op_put_setter(Instruction* currentInstruction)
-{
- JITStubCall stubCall(this, cti_op_put_setter);
+ JITStubCall stubCall(this, cti_op_put_getter_setter);
stubCall.addArgument(currentInstruction[1].u.operand, regT2);
stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
stubCall.addArgument(currentInstruction[3].u.operand, regT2);
+ stubCall.addArgument(currentInstruction[4].u.operand, regT2);
stubCall.call();
}
@@ -332,7 +324,7 @@ void JIT::emit_op_method_check(Instruction* currentInstruction)
compileGetByIdHotPath(baseVReg, ident);
match.link(this);
- emitValueProfilingSite(FirstProfilingSite);
+ emitValueProfilingSite(m_bytecodeOffset + OPCODE_LENGTH(op_method_check));
emitPutVirtualRegister(resultVReg);
// We've already generated the following get_by_id, so make sure it's skipped over.
@@ -347,7 +339,7 @@ void JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowC
Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
compileGetByIdSlowCase(resultVReg, baseVReg, ident, iter, true);
- emitValueProfilingSite(SubsequentProfilingSite);
+ emitValueProfilingSite(m_bytecodeOffset + OPCODE_LENGTH(op_method_check));
// We've already generated the following get_by_id, so make sure it's skipped over.
m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id);
@@ -361,7 +353,7 @@ void JIT::emit_op_get_by_id(Instruction* currentInstruction)
emitGetVirtualRegister(baseVReg, regT0);
compileGetByIdHotPath(baseVReg, ident);
- emitValueProfilingSite(FirstProfilingSite);
+ emitValueProfilingSite();
emitPutVirtualRegister(resultVReg);
}
@@ -405,7 +397,7 @@ void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCase
Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
compileGetByIdSlowCase(resultVReg, baseVReg, ident, iter, false);
- emitValueProfilingSite(SubsequentProfilingSite);
+ emitValueProfilingSite();
}
void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck)
@@ -548,7 +540,7 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
stubCall.skipArgument(); // ident
stubCall.skipArgument(); // value
stubCall.addArgument(TrustedImm32(oldStructure->propertyStorageCapacity()));
- stubCall.addArgument(TrustedImm32(newStructure->propertyStorageCapacity()));
+ stubCall.addArgument(TrustedImmPtr(newStructure));
stubCall.call(regT0);
emitGetJITStubArg(2, regT1);
@@ -570,7 +562,7 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
restoreArgumentReferenceForTrampoline();
Call failureCall = tailRecursiveCall();
- LinkBuffer patchBuffer(*m_globalData, this);
+ LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
patchBuffer.link(failureCall, FunctionPtr(direct ? cti_op_put_by_id_direct_fail : cti_op_put_by_id_fail));
@@ -629,7 +621,7 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
emitFastArithIntToImmNoCheck(regT2, regT0);
Jump success = jump();
- LinkBuffer patchBuffer(*m_globalData, this);
+ LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
// Use the patch information to link the failure cases back to the original slow case routine.
CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall);
@@ -686,7 +678,7 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
} else
compileGetDirectOffset(protoObject, regT0, cachedOffset);
Jump success = jump();
- LinkBuffer patchBuffer(*m_globalData, this);
+ LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
// Use the patch information to link the failure cases back to the original slow case routine.
CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall);
@@ -741,7 +733,7 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
}
Jump success = jump();
- LinkBuffer patchBuffer(*m_globalData, this);
+ LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
if (needsStubLink) {
for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
@@ -809,7 +801,7 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
Jump success = jump();
- LinkBuffer patchBuffer(*m_globalData, this);
+ LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
if (needsStubLink) {
for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
@@ -878,7 +870,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
}
Jump success = jump();
- LinkBuffer patchBuffer(*m_globalData, this);
+ LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
if (needsStubLink) {
for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
@@ -946,7 +938,7 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
compileGetDirectOffset(protoObject, regT0, cachedOffset);
Jump success = jump();
- LinkBuffer patchBuffer(*m_globalData, this);
+ LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
if (needsStubLink) {
for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
@@ -994,7 +986,7 @@ void JIT::emit_op_get_scoped_var(Instruction* currentInstruction)
loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT0);
loadPtr(Address(regT0, JSVariableObject::offsetOfRegisters()), regT0);
loadPtr(Address(regT0, currentInstruction[2].u.operand * sizeof(Register)), regT0);
- emitValueProfilingSite(FirstProfilingSite);
+ emitValueProfilingSite();
emitPutVirtualRegister(currentInstruction[1].u.operand);
}
@@ -1029,7 +1021,7 @@ void JIT::emit_op_get_global_var(Instruction* currentInstruction)
JSVariableObject* globalObject = m_codeBlock->globalObject();
loadPtr(&globalObject->m_registers, regT0);
loadPtr(Address(regT0, currentInstruction[2].u.operand * sizeof(Register)), regT0);
- emitValueProfilingSite(FirstProfilingSite);
+ emitValueProfilingSite();
emitPutVirtualRegister(currentInstruction[1].u.operand);
}
diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
index b73d7ab75..2c81a5ff6 100644
--- a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
+++ b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
@@ -62,29 +62,18 @@ void JIT::emit_op_put_by_index(Instruction* currentInstruction)
stubCall.call();
}
-void JIT::emit_op_put_getter(Instruction* currentInstruction)
+void JIT::emit_op_put_getter_setter(Instruction* currentInstruction)
{
unsigned base = currentInstruction[1].u.operand;
unsigned property = currentInstruction[2].u.operand;
- unsigned function = currentInstruction[3].u.operand;
+ unsigned getter = currentInstruction[3].u.operand;
+ unsigned setter = currentInstruction[4].u.operand;
- JITStubCall stubCall(this, cti_op_put_getter);
+ JITStubCall stubCall(this, cti_op_put_getter_setter);
stubCall.addArgument(base);
stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(property)));
- stubCall.addArgument(function);
- stubCall.call();
-}
-
-void JIT::emit_op_put_setter(Instruction* currentInstruction)
-{
- unsigned base = currentInstruction[1].u.operand;
- unsigned property = currentInstruction[2].u.operand;
- unsigned function = currentInstruction[3].u.operand;
-
- JITStubCall stubCall(this, cti_op_put_setter);
- stubCall.addArgument(base);
- stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(property)));
- stubCall.addArgument(function);
+ stubCall.addArgument(getter);
+ stubCall.addArgument(setter);
stubCall.call();
}
@@ -144,7 +133,7 @@ void JIT::emit_op_method_check(Instruction* currentInstruction)
compileGetByIdHotPath();
match.link(this);
- emitValueProfilingSite(FirstProfilingSite);
+ emitValueProfilingSite(m_bytecodeOffset + OPCODE_LENGTH(op_method_check));
emitStore(dst, regT1, regT0);
map(m_bytecodeOffset + OPCODE_LENGTH(op_method_check) + OPCODE_LENGTH(op_get_by_id), dst, regT1, regT0);
@@ -161,7 +150,7 @@ void JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowC
int ident = currentInstruction[3].u.operand;
compileGetByIdSlowCase(dst, base, &(m_codeBlock->identifier(ident)), iter, true);
- emitValueProfilingSite(SubsequentProfilingSite);
+ emitValueProfilingSite(m_bytecodeOffset + OPCODE_LENGTH(op_method_check));
// We've already generated the following get_by_id, so make sure it's skipped over.
m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id);
@@ -205,7 +194,7 @@ JIT::CodeRef JIT::stringGetByValStubGenerator(JSGlobalData* globalData)
jit.move(TrustedImm32(0), regT0);
jit.ret();
- LinkBuffer patchBuffer(*globalData, &jit);
+ LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
return patchBuffer.finalizeCode();
}
@@ -228,7 +217,7 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction)
load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload
addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag)));
- emitValueProfilingSite(FirstProfilingSite);
+ emitValueProfilingSite();
emitStore(dst, regT1, regT0);
map(m_bytecodeOffset + OPCODE_LENGTH(op_get_by_val), dst, regT1, regT0);
}
@@ -261,7 +250,7 @@ void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCas
stubCall.addArgument(property);
stubCall.call(dst);
- emitValueProfilingSite(SubsequentProfilingSite);
+ emitValueProfilingSite();
}
void JIT::emit_op_put_by_val(Instruction* currentInstruction)
@@ -325,7 +314,7 @@ void JIT::emit_op_get_by_id(Instruction* currentInstruction)
emitLoad(base, regT1, regT0);
emitJumpSlowCaseIfNotJSCell(base, regT1);
compileGetByIdHotPath();
- emitValueProfilingSite(FirstProfilingSite);
+ emitValueProfilingSite();
emitStore(dst, regT1, regT0);
map(m_bytecodeOffset + OPCODE_LENGTH(op_get_by_id), dst, regT1, regT0);
}
@@ -369,7 +358,7 @@ void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCase
int ident = currentInstruction[3].u.operand;
compileGetByIdSlowCase(dst, base, &(m_codeBlock->identifier(ident)), iter);
- emitValueProfilingSite(SubsequentProfilingSite);
+ emitValueProfilingSite();
}
void JIT::compileGetByIdSlowCase(int dst, int base, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck)
@@ -517,7 +506,7 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
stubCall.skipArgument(); // ident
stubCall.skipArgument(); // value
stubCall.addArgument(TrustedImm32(oldStructure->propertyStorageCapacity()));
- stubCall.addArgument(TrustedImm32(newStructure->propertyStorageCapacity()));
+ stubCall.addArgument(TrustedImmPtr(newStructure));
stubCall.call(regT0);
restoreReturnAddressBeforeReturn(regT3);
@@ -553,7 +542,7 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
restoreArgumentReferenceForTrampoline();
Call failureCall = tailRecursiveCall();
- LinkBuffer patchBuffer(*m_globalData, this);
+ LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
patchBuffer.link(failureCall, FunctionPtr(direct ? cti_op_put_by_id_direct_fail : cti_op_put_by_id_fail));
@@ -617,7 +606,7 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
move(TrustedImm32(JSValue::Int32Tag), regT1);
Jump success = jump();
- LinkBuffer patchBuffer(*m_globalData, this);
+ LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
// Use the patch information to link the failure cases back to the original slow case routine.
CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall);
@@ -676,7 +665,7 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
Jump success = jump();
- LinkBuffer patchBuffer(*m_globalData, this);
+ LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
// Use the patch information to link the failure cases back to the original slow case routine.
CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall);
@@ -735,7 +724,7 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
Jump success = jump();
- LinkBuffer patchBuffer(*m_globalData, this);
+ LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
if (needsStubLink) {
for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
if (iter->to)
@@ -802,7 +791,7 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
Jump success = jump();
- LinkBuffer patchBuffer(*m_globalData, this);
+ LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
if (needsStubLink) {
for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
if (iter->to)
@@ -872,7 +861,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
Jump success = jump();
- LinkBuffer patchBuffer(*m_globalData, this);
+ LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
if (needsStubLink) {
for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
if (iter->to)
@@ -939,7 +928,7 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
Jump success = jump();
- LinkBuffer patchBuffer(*m_globalData, this);
+ LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
if (needsStubLink) {
for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
if (iter->to)
@@ -1043,7 +1032,7 @@ void JIT::emit_op_get_scoped_var(Instruction* currentInstruction)
loadPtr(Address(regT2, JSVariableObject::offsetOfRegisters()), regT2);
emitLoad(index, regT1, regT0, regT2);
- emitValueProfilingSite(FirstProfilingSite);
+ emitValueProfilingSite();
emitStore(dst, regT1, regT0);
map(m_bytecodeOffset + OPCODE_LENGTH(op_get_scoped_var), dst, regT1, regT0);
}
@@ -1085,7 +1074,7 @@ void JIT::emit_op_get_global_var(Instruction* currentInstruction)
loadPtr(&globalObject->m_registers, regT2);
emitLoad(index, regT1, regT0, regT2);
- emitValueProfilingSite(FirstProfilingSite);
+ emitValueProfilingSite();
emitStore(dst, regT1, regT0);
map(m_bytecodeOffset + OPCODE_LENGTH(op_get_global_var), dst, regT1, regT0);
}
diff --git a/Source/JavaScriptCore/jit/JITStubCall.h b/Source/JavaScriptCore/jit/JITStubCall.h
index 18441c363..51401a77f 100644
--- a/Source/JavaScriptCore/jit/JITStubCall.h
+++ b/Source/JavaScriptCore/jit/JITStubCall.h
@@ -201,14 +201,14 @@ namespace JSC {
return call;
}
- JIT::Call callWithValueProfiling(unsigned dst, JIT::ValueProfilingSiteKind kind)
+ JIT::Call callWithValueProfiling(unsigned dst)
{
ASSERT(m_returnType == Value || m_returnType == Cell);
JIT::Call call = this->call();
ASSERT(JIT::returnValueRegister == JIT::regT0);
if (m_returnType == Cell)
m_jit->move(JIT::TrustedImm32(JSValue::CellTag), JIT::regT1);
- m_jit->emitValueProfilingSite(kind);
+ m_jit->emitValueProfilingSite();
if (m_returnType == Value)
m_jit->emitStore(dst, JIT::regT1, JIT::regT0);
else
@@ -224,12 +224,12 @@ namespace JSC {
return call;
}
- JIT::Call callWithValueProfiling(unsigned dst, JIT::ValueProfilingSiteKind kind)
+ JIT::Call callWithValueProfiling(unsigned dst)
{
ASSERT(m_returnType == VoidPtr || m_returnType == Cell);
JIT::Call call = this->call();
ASSERT(JIT::returnValueRegister == JIT::regT0);
- m_jit->emitValueProfilingSite(kind);
+ m_jit->emitValueProfilingSite();
m_jit->emitPutVirtualRegister(dst);
return call;
}
diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp
index 3c16efe01..386d0dfa1 100644
--- a/Source/JavaScriptCore/jit/JITStubs.cpp
+++ b/Source/JavaScriptCore/jit/JITStubs.cpp
@@ -37,6 +37,7 @@
#include "Arguments.h"
#include "CallFrame.h"
#include "CodeBlock.h"
+#include "CodeProfiling.h"
#include "DFGOSREntry.h"
#include "Debugger.h"
#include "ExceptionHelpers.h"
@@ -101,6 +102,9 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
"popl %esi" "\n"
"popl %ebp" "\n"
"ret" "\n"
+".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n"
+HIDE_SYMBOL(ctiTrampolineEnd) "\n"
+SYMBOL_STRING(ctiTrampolineEnd) ":" "\n"
);
asm (
@@ -158,6 +162,9 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
"popq %r12" "\n"
"popq %rbp" "\n"
"ret" "\n"
+".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n"
+HIDE_SYMBOL(ctiTrampolineEnd) "\n"
+SYMBOL_STRING(ctiTrampolineEnd) ":" "\n"
);
asm (
@@ -400,6 +407,9 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
"popq %r12" "\n"
"popq %rbp" "\n"
"ret" "\n"
+".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n"
+HIDE_SYMBOL(ctiTrampolineEnd) "\n"
+SYMBOL_STRING(ctiTrampolineEnd) ":" "\n"
);
asm (
@@ -560,6 +570,12 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
"ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
"add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
"bx lr" "\n"
+".align 2" "\n"
+".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n"
+HIDE_SYMBOL(ctiTrampolineEnd) "\n"
+".thumb" "\n"
+".thumb_func " THUMB_FUNC_PARAM(ctiTrampolineEnd) "\n"
+SYMBOL_STRING(ctiTrampolineEnd) ":" "\n"
);
asm (
@@ -953,7 +969,7 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co
JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, propertyName, slot, offset, returnAddress);
}
-#ifndef NDEBUG
+#if !defined(NDEBUG)
extern "C" {
@@ -971,7 +987,8 @@ struct StackHack {
: stackFrame(stackFrame)
, savedReturnAddress(*stackFrame.returnAddressSlot())
{
- *stackFrame.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode));
+ if (!CodeProfiling::enabled())
+ *stackFrame.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode));
}
ALWAYS_INLINE ~StackHack()
@@ -1303,10 +1320,8 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_add)
JSValue v2 = stackFrame.args[1].jsValue();
CallFrame* callFrame = stackFrame.callFrame;
- if (v1.isString()) {
- JSValue result = v2.isString()
- ? jsString(callFrame, asString(v1), asString(v2))
- : jsString(callFrame, asString(v1), v2.toPrimitiveString(callFrame));
+ if (v1.isString() && !v2.isObject()) {
+ JSValue result = jsString(callFrame, asString(v1), v2.toString(callFrame));
CHECK_FOR_EXCEPTION_AT_END();
return JSValue::encode(result);
}
@@ -1382,7 +1397,9 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_generic)
STUB_INIT_STACK_FRAME(stackFrame);
PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode());
- stackFrame.args[0].jsValue().putDirect(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ ASSERT(baseValue.isObject());
+ asObject(baseValue)->putDirect(stackFrame.callFrame->globalData(), stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
CHECK_FOR_EXCEPTION_AT_END();
}
@@ -1427,7 +1444,9 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_direct)
Identifier& ident = stackFrame.args[1].identifier();
PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
- stackFrame.args[0].jsValue().putDirect(callFrame, ident, stackFrame.args[2].jsValue(), slot);
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ ASSERT(baseValue.isObject());
+ asObject(baseValue)->putDirect(callFrame->globalData(), ident, stackFrame.args[2].jsValue(), slot);
CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
@@ -1460,7 +1479,9 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_fail)
Identifier& ident = stackFrame.args[1].identifier();
PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
- stackFrame.args[0].jsValue().putDirect(callFrame, ident, stackFrame.args[2].jsValue(), slot);
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ ASSERT(baseValue.isObject());
+ asObject(baseValue)->putDirect(callFrame->globalData(), ident, stackFrame.args[2].jsValue(), slot);
CHECK_FOR_EXCEPTION_AT_END();
}
@@ -1471,7 +1492,8 @@ DEFINE_STUB_FUNCTION(JSObject*, op_put_by_id_transition_realloc)
JSValue baseValue = stackFrame.args[0].jsValue();
int32_t oldSize = stackFrame.args[3].int32();
- int32_t newSize = stackFrame.args[4].int32();
+ Structure* newStructure = stackFrame.args[4].structure();
+ int32_t newSize = newStructure->propertyStorageCapacity();
ASSERT(baseValue.isObject());
JSObject* base = asObject(baseValue);
@@ -1909,7 +1931,7 @@ DEFINE_STUB_FUNCTION(void, optimize_from_loop)
unsigned bytecodeIndex = stackFrame.args[0].int32();
#if ENABLE(JIT_VERBOSE_OSR)
- printf("Entered optimize_from_loop with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock->executeCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
+ printf("Entered optimize_from_loop with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
#endif
if (codeBlock->hasOptimizedReplacement()) {
@@ -2007,7 +2029,7 @@ DEFINE_STUB_FUNCTION(void, optimize_from_ret)
CodeBlock* codeBlock = callFrame->codeBlock();
#if ENABLE(JIT_VERBOSE_OSR)
- printf("Entered optimize_from_ret with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock->executeCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
+ printf("Entered optimize_from_ret with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
#endif
if (codeBlock->hasOptimizedReplacement()) {
@@ -2455,7 +2477,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val)
return JSValue::encode(result);
}
- Identifier property(callFrame, subscript.toString(callFrame));
+ Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
JSValue result = baseValue.get(callFrame, property);
CHECK_FOR_EXCEPTION_AT_END();
return JSValue::encode(result);
@@ -2482,7 +2504,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_string)
ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
}
} else {
- Identifier property(callFrame, subscript.toString(callFrame));
+ Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
result = baseValue.get(callFrame, property);
}
@@ -2512,7 +2534,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_byte_array)
if (!isJSByteArray(baseValue))
ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
} else {
- Identifier property(callFrame, subscript.toString(callFrame));
+ Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
result = baseValue.get(callFrame, property);
}
@@ -2573,7 +2595,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_val)
} else
baseValue.put(callFrame, i, value);
} else {
- Identifier property(callFrame, subscript.toString(callFrame));
+ Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
baseValue.put(callFrame, property, value, slot);
@@ -2614,7 +2636,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_val_byte_array)
ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val));
baseValue.put(callFrame, i, value);
} else {
- Identifier property(callFrame, subscript.toString(callFrame));
+ Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
baseValue.put(callFrame, property, value, slot);
@@ -3380,7 +3402,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_in)
if (propName.getUInt32(i))
return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, i)));
- Identifier property(callFrame, propName.toString(callFrame));
+ Identifier property(callFrame, propName.toString(callFrame)->value(callFrame));
CHECK_FOR_EXCEPTION();
return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, property)));
}
@@ -3492,7 +3514,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_val)
result = baseObj->methodTable()->deletePropertyByIndex(baseObj, callFrame, i);
else {
CHECK_FOR_EXCEPTION();
- Identifier property(callFrame, subscript.toString(callFrame));
+ Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
CHECK_FOR_EXCEPTION();
result = baseObj->methodTable()->deleteProperty(baseObj, callFrame, property);
}
@@ -3504,7 +3526,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_val)
return JSValue::encode(jsBoolean(result));
}
-DEFINE_STUB_FUNCTION(void, op_put_getter)
+DEFINE_STUB_FUNCTION(void, op_put_getter_setter)
{
STUB_INIT_STACK_FRAME(stackFrame);
@@ -3512,20 +3534,20 @@ DEFINE_STUB_FUNCTION(void, op_put_getter)
ASSERT(stackFrame.args[0].jsValue().isObject());
JSObject* baseObj = asObject(stackFrame.args[0].jsValue());
- ASSERT(stackFrame.args[2].jsValue().isObject());
- baseObj->methodTable()->defineGetter(baseObj, callFrame, stackFrame.args[1].identifier(), asObject(stackFrame.args[2].jsValue()), 0);
-}
-DEFINE_STUB_FUNCTION(void, op_put_setter)
-{
- STUB_INIT_STACK_FRAME(stackFrame);
+ GetterSetter* accessor = GetterSetter::create(callFrame);
- CallFrame* callFrame = stackFrame.callFrame;
+ JSValue getter = stackFrame.args[2].jsValue();
+ JSValue setter = stackFrame.args[3].jsValue();
+ ASSERT(getter.isObject() || getter.isUndefined());
+ ASSERT(setter.isObject() || setter.isUndefined());
+ ASSERT(getter.isObject() || setter.isObject());
- ASSERT(stackFrame.args[0].jsValue().isObject());
- JSObject* baseObj = asObject(stackFrame.args[0].jsValue());
- ASSERT(stackFrame.args[2].jsValue().isObject());
- baseObj->methodTable()->defineSetter(baseObj, callFrame, stackFrame.args[1].identifier(), asObject(stackFrame.args[2].jsValue()), 0);
+ if (!getter.isUndefined())
+ accessor->setGetter(callFrame->globalData(), asObject(getter));
+ if (!setter.isUndefined())
+ accessor->setSetter(callFrame->globalData(), asObject(setter));
+ baseObj->putDirectAccessor(callFrame->globalData(), stackFrame.args[1].identifier(), accessor, Accessor);
}
DEFINE_STUB_FUNCTION(void, op_throw_reference_error)
@@ -3533,7 +3555,7 @@ DEFINE_STUB_FUNCTION(void, op_throw_reference_error)
STUB_INIT_STACK_FRAME(stackFrame);
CallFrame* callFrame = stackFrame.callFrame;
- UString message = stackFrame.args[0].jsValue().toString(callFrame);
+ UString message = stackFrame.args[0].jsValue().toString(callFrame)->value(callFrame);
stackFrame.globalData->exception = createReferenceError(callFrame, message);
VM_THROW_EXCEPTION_AT_END();
}
diff --git a/Source/JavaScriptCore/jit/JITStubs.h b/Source/JavaScriptCore/jit/JITStubs.h
index 241ace968..fe5f522e9 100644
--- a/Source/JavaScriptCore/jit/JITStubs.h
+++ b/Source/JavaScriptCore/jit/JITStubs.h
@@ -59,6 +59,7 @@ namespace JSC {
class PutPropertySlot;
class RegisterFile;
class RegExp;
+ class Structure;
template <typename T> class Weak;
@@ -78,6 +79,7 @@ namespace JSC {
JSPropertyNameIterator* propertyNameIterator() { return static_cast<JSPropertyNameIterator*>(asPointer); }
JSGlobalObject* globalObject() { return static_cast<JSGlobalObject*>(asPointer); }
JSString* jsString() { return static_cast<JSString*>(asPointer); }
+ Structure* structure() { return static_cast<Structure*>(asPointer); }
ReturnAddressPtr returnAddress() { return ReturnAddressPtr(asPointer); }
};
@@ -281,6 +283,15 @@ namespace JSC {
extern "C" void ctiVMThrowTrampoline();
extern "C" void ctiOpThrowNotCaught();
extern "C" EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*);
+#if ENABLE(DFG_JIT)
+ extern "C" void ctiTrampolineEnd();
+
+ inline bool returnAddressIsInCtiTrampoline(ReturnAddressPtr returnAddress)
+ {
+ return returnAddress.value() >= bitwise_cast<void*>(&ctiTrampoline)
+ && returnAddress.value() < bitwise_cast<void*>(&ctiTrampolineEnd);
+ }
+#endif
class JITThunks {
public:
@@ -423,8 +434,7 @@ extern "C" {
void JIT_STUB cti_op_put_by_index(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_put_by_val(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_put_by_val_byte_array(STUB_ARGS_DECLARATION);
- void JIT_STUB cti_op_put_getter(STUB_ARGS_DECLARATION);
- void JIT_STUB cti_op_put_setter(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_put_getter_setter(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_tear_off_activation(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_tear_off_arguments(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_throw_reference_error(STUB_ARGS_DECLARATION);
diff --git a/Source/JavaScriptCore/jit/SpecializedThunkJIT.h b/Source/JavaScriptCore/jit/SpecializedThunkJIT.h
index 1802216fa..74e94ea3c 100644
--- a/Source/JavaScriptCore/jit/SpecializedThunkJIT.h
+++ b/Source/JavaScriptCore/jit/SpecializedThunkJIT.h
@@ -134,7 +134,7 @@ namespace JSC {
MacroAssemblerCodeRef finalize(JSGlobalData& globalData, MacroAssemblerCodePtr fallback)
{
- LinkBuffer patchBuffer(globalData, this);
+ LinkBuffer patchBuffer(globalData, this, GLOBAL_THUNK_ID);
patchBuffer.link(m_failures, CodeLocationLabel(fallback));
for (unsigned i = 0; i < m_calls.size(); i++)
patchBuffer.link(m_calls[i].first, m_calls[i].second);
diff --git a/Source/JavaScriptCore/jit/ThunkGenerators.cpp b/Source/JavaScriptCore/jit/ThunkGenerators.cpp
index 0e54c8a8f..099796986 100644
--- a/Source/JavaScriptCore/jit/ThunkGenerators.cpp
+++ b/Source/JavaScriptCore/jit/ThunkGenerators.cpp
@@ -27,8 +27,9 @@
#include "ThunkGenerators.h"
#include "CodeBlock.h"
-#include <wtf/text/StringImpl.h>
+#include "InlineASM.h"
#include "SpecializedThunkJIT.h"
+#include <wtf/text/StringImpl.h>
#if ENABLE(JIT)
@@ -111,21 +112,6 @@ MacroAssemblerCodeRef sqrtThunkGenerator(JSGlobalData* globalData)
return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
}
-#if OS(DARWIN) || (OS(WINDOWS) && CPU(X86))
-#define SYMBOL_STRING(name) "_" #name
-#else
-#define SYMBOL_STRING(name) #name
-#endif
-
-#if (OS(LINUX) || OS(FREEBSD)) && CPU(X86_64)
-#define SYMBOL_STRING_RELOCATION(name) #name "@plt"
-#elif OS(DARWIN) || (CPU(X86_64) && COMPILER(MINGW) && !GCC_VERSION_AT_LEAST(4, 5, 0))
-#define SYMBOL_STRING_RELOCATION(name) "_" #name
-#elif CPU(X86) && COMPILER(MINGW)
-#define SYMBOL_STRING_RELOCATION(name) "@" #name "@4"
-#else
-#define SYMBOL_STRING_RELOCATION(name) #name
-#endif
#define UnaryDoubleOpWrapper(function) function##Wrapper
enum MathThunkCallingConvention { };
@@ -147,6 +133,7 @@ double jsRound(double d)
asm( \
".text\n" \
".globl " SYMBOL_STRING(function##Thunk) "\n" \
+ HIDE_SYMBOL(function##Thunk) "\n" \
SYMBOL_STRING(function##Thunk) ":" "\n" \
"call " SYMBOL_STRING_RELOCATION(function) "\n" \
"ret\n" \
@@ -161,6 +148,7 @@ double jsRound(double d)
asm( \
".text\n" \
".globl " SYMBOL_STRING(function##Thunk) "\n" \
+ HIDE_SYMBOL(function##Thunk) "\n" \
SYMBOL_STRING(function##Thunk) ":" "\n" \
"subl $8, %esp\n" \
"movsd %xmm0, (%esp) \n" \
diff --git a/Source/JavaScriptCore/jsc.cpp b/Source/JavaScriptCore/jsc.cpp
index ea32d8976..47ec8c608 100644
--- a/Source/JavaScriptCore/jsc.cpp
+++ b/Source/JavaScriptCore/jsc.cpp
@@ -238,7 +238,7 @@ EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
if (i)
putchar(' ');
- printf("%s", exec->argument(i).toString(exec).utf8().data());
+ printf("%s", exec->argument(i).toString(exec)->value(exec).utf8().data());
}
putchar('\n');
@@ -248,7 +248,7 @@ EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
{
- fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec).utf8().data());
+ fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec)->value(exec).utf8().data());
return JSValue::encode(jsUndefined());
}
@@ -277,7 +277,7 @@ EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
{
- UString fileName = exec->argument(0).toString(exec);
+ UString fileName = exec->argument(0).toString(exec)->value(exec);
Vector<char> script;
if (!fillBufferWithContentsOfFile(fileName, script))
return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
@@ -294,7 +294,7 @@ EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
{
- UString fileName = exec->argument(0).toString(exec);
+ UString fileName = exec->argument(0).toString(exec)->value(exec);
Vector<char> script;
if (!fillBufferWithContentsOfFile(fileName, script))
return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
@@ -310,7 +310,7 @@ EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
{
- UString fileName = exec->argument(0).toString(exec);
+ UString fileName = exec->argument(0).toString(exec)->value(exec);
Vector<char> script;
if (!fillBufferWithContentsOfFile(fileName, script))
return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
@@ -487,9 +487,9 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
success = success && !evaluationException;
if (dump) {
if (evaluationException)
- printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec()).utf8().data());
+ printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
else
- printf("End: %s\n", returnValue.toString(globalObject->globalExec()).utf8().data());
+ printf("End: %s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
}
globalData.stopSampling();
@@ -546,9 +546,9 @@ static void runInteractive(GlobalObject* globalObject)
JSValue returnValue = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), jscSource(line.data(), interpreterName), JSValue(), &evaluationException);
#endif
if (evaluationException)
- printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec()).utf8().data());
+ printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
else
- printf("%s\n", returnValue.toString(globalObject->globalExec()).utf8().data());
+ printf("%s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
globalObject->globalExec()->clearException();
}
diff --git a/Source/JavaScriptCore/parser/ASTBuilder.h b/Source/JavaScriptCore/parser/ASTBuilder.h
index 2e81c2546..b6ea004b5 100644
--- a/Source/JavaScriptCore/parser/ASTBuilder.h
+++ b/Source/JavaScriptCore/parser/ASTBuilder.h
@@ -249,6 +249,8 @@ public:
ExpressionNode* createAssignResolve(int lineNumber, const Identifier& ident, ExpressionNode* rhs, bool rhsHasAssignment, int start, int divot, int end)
{
+ if (rhs->isFuncExprNode())
+ static_cast<FuncExprNode*>(rhs)->body()->setInferredName(ident);
AssignResolveNode* node = new (m_globalData) AssignResolveNode(lineNumber, ident, rhs, rhsHasAssignment);
setExceptionLocation(node, start, divot, end);
return node;
@@ -271,6 +273,7 @@ public:
{
ASSERT(name);
body->setLoc(bodyStartLine, bodyEndLine);
+ body->setInferredName(*name);
return new (m_globalData) PropertyNode(m_globalData, *name, new (m_globalData) FuncExprNode(lineNumber, m_globalData->propertyNames->nullIdentifier, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), params), type);
}
@@ -280,7 +283,12 @@ public:
ArgumentListNode* createArgumentsList(int lineNumber, ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(lineNumber, arg); }
ArgumentListNode* createArgumentsList(int lineNumber, ArgumentListNode* args, ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(lineNumber, args, arg); }
- template <bool> PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, *propertyName, node, type); }
+ template <bool> PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type)
+ {
+ if (node->isFuncExprNode())
+ static_cast<FuncExprNode*>(node)->body()->setInferredName(*propertyName);
+ return new (m_globalData) PropertyNode(m_globalData, *propertyName, node, type);
+ }
template <bool> PropertyNode* createProperty(JSGlobalData*, double propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, propertyName, node, type); }
PropertyListNode* createPropertyList(int lineNumber, PropertyNode* property) { return new (m_globalData) PropertyListNode(lineNumber, property); }
PropertyListNode* createPropertyList(int lineNumber, PropertyNode* property, PropertyListNode* tail) { return new (m_globalData) PropertyListNode(lineNumber, property, tail); }
@@ -411,9 +419,9 @@ public:
return result;
}
- StatementNode* createTryStatement(int lineNumber, StatementNode* tryBlock, const Identifier* ident, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine)
+ StatementNode* createTryStatement(int lineNumber, StatementNode* tryBlock, const Identifier* ident, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine)
{
- TryNode* result = new (m_globalData) TryNode(lineNumber, tryBlock, *ident, catchHasEval, catchBlock, finallyBlock);
+ TryNode* result = new (m_globalData) TryNode(lineNumber, tryBlock, *ident, catchBlock, finallyBlock);
if (catchBlock)
usesCatch();
result->setLoc(startLine, endLine);
@@ -903,6 +911,8 @@ ExpressionNode* ASTBuilder::makeAssignNode(int lineNumber, ExpressionNode* loc,
if (loc->isResolveNode()) {
ResolveNode* resolve = static_cast<ResolveNode*>(loc);
if (op == OpEqual) {
+ if (expr->isFuncExprNode())
+ static_cast<FuncExprNode*>(expr)->body()->setInferredName(resolve->identifier());
AssignResolveNode* node = new (m_globalData) AssignResolveNode(lineNumber, resolve->identifier(), expr, exprHasAssignments);
setExceptionLocation(node, start, divot, end);
return node;
@@ -919,8 +929,11 @@ ExpressionNode* ASTBuilder::makeAssignNode(int lineNumber, ExpressionNode* loc,
}
ASSERT(loc->isDotAccessorNode());
DotAccessorNode* dot = static_cast<DotAccessorNode*>(loc);
- if (op == OpEqual)
+ if (op == OpEqual) {
+ if (expr->isFuncExprNode())
+ static_cast<FuncExprNode*>(expr)->body()->setInferredName(dot->identifier());
return new (m_globalData) AssignDotNode(lineNumber, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), dot->divot() - start, end - dot->divot());
+ }
ReadModifyDotNode* node = new (m_globalData) ReadModifyDotNode(lineNumber, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
node->setSubexpressionInfo(dot->divot(), dot->endOffset());
diff --git a/Source/JavaScriptCore/parser/Keywords.table b/Source/JavaScriptCore/parser/Keywords.table
index fab0e23cc..333b4762d 100644
--- a/Source/JavaScriptCore/parser/Keywords.table
+++ b/Source/JavaScriptCore/parser/Keywords.table
@@ -43,10 +43,12 @@ extends RESERVED
import RESERVED
super RESERVED
+# technically RESERVED_IF_STRICT in ES5, but may be reserved in ES6.
+let RESERVED
+
# reserved for future use in strict code
implements RESERVED_IF_STRICT
interface RESERVED_IF_STRICT
-let RESERVED_IF_STRICT
package RESERVED_IF_STRICT
private RESERVED_IF_STRICT
protected RESERVED_IF_STRICT
diff --git a/Source/JavaScriptCore/parser/NodeConstructors.h b/Source/JavaScriptCore/parser/NodeConstructors.h
index 6c069490d..eea3f575c 100644
--- a/Source/JavaScriptCore/parser/NodeConstructors.h
+++ b/Source/JavaScriptCore/parser/NodeConstructors.h
@@ -781,13 +781,12 @@ namespace JSC {
{
}
- inline TryNode::TryNode(int lineNumber, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock)
+ inline TryNode::TryNode(int lineNumber, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock)
: StatementNode(lineNumber)
, m_tryBlock(tryBlock)
, m_exceptionIdent(exceptionIdent)
, m_catchBlock(catchBlock)
, m_finallyBlock(finallyBlock)
- , m_catchHasEval(catchHasEval)
{
}
diff --git a/Source/JavaScriptCore/parser/Nodes.h b/Source/JavaScriptCore/parser/Nodes.h
index 23f2cde9c..278d17ef4 100644
--- a/Source/JavaScriptCore/parser/Nodes.h
+++ b/Source/JavaScriptCore/parser/Nodes.h
@@ -181,7 +181,7 @@ namespace JSC {
StatementNode(int);
public:
- void setLoc(int firstLine, int lastLine);
+ JS_EXPORT_PRIVATE void setLoc(int firstLine, int lastLine);
int firstLine() const { return lineNo(); }
int lastLine() const { return m_lastLine; }
@@ -1348,7 +1348,7 @@ namespace JSC {
class TryNode : public StatementNode {
public:
- TryNode(int, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock);
+ TryNode(int, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock);
private:
virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1357,7 +1357,6 @@ namespace JSC {
const Identifier& m_exceptionIdent;
StatementNode* m_catchBlock;
StatementNode* m_finallyBlock;
- bool m_catchHasEval;
};
class ParameterNode : public ParserArenaFreeable {
@@ -1494,6 +1493,8 @@ namespace JSC {
void finishParsing(PassRefPtr<FunctionParameters>, const Identifier&);
const Identifier& ident() { return m_ident; }
+ void setInferredName(const Identifier& inferredName) { m_inferredName = inferredName; }
+ const Identifier& inferredName() { return m_inferredName.isEmpty() ? m_ident : m_inferredName; }
static const bool scopeIsFunction = true;
@@ -1502,6 +1503,7 @@ namespace JSC {
FunctionBodyNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
Identifier m_ident;
+ Identifier m_inferredName;
RefPtr<FunctionParameters> m_parameters;
};
diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp
index 5c2f0383f..ce6519873 100644
--- a/Source/JavaScriptCore/parser/Parser.cpp
+++ b/Source/JavaScriptCore/parser/Parser.cpp
@@ -43,7 +43,7 @@ template <typename LexerType>
Parser<LexerType>::Parser(JSGlobalData* globalData, const SourceCode& source, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode)
: m_globalData(globalData)
, m_source(&source)
- , m_stack(globalData->stack())
+ , m_stack(wtfThreadData().stack())
, m_error(false)
, m_errorMessage("Parse error")
, m_allowsIn(true)
@@ -603,7 +603,6 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(
ASSERT(match(TRY));
TreeStatement tryBlock = 0;
const Identifier* ident = &m_globalData->propertyNames->nullIdentifier;
- bool catchHasEval = false;
TreeStatement catchBlock = 0;
TreeStatement finallyBlock = 0;
int firstLine = tokenLine();
@@ -626,10 +625,8 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(
catchScope->preventNewDecls();
consumeOrFail(CLOSEPAREN);
matchOrFail(OPENBRACE);
- int initialEvalCount = context.evalCount();
catchBlock = parseBlockStatement(context);
failIfFalseWithMessage(catchBlock, "'try' must have a catch or finally block");
- catchHasEval = initialEvalCount != context.evalCount();
failIfFalse(popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo));
}
@@ -640,7 +637,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(
failIfFalse(finallyBlock);
}
failIfFalse(catchBlock || finallyBlock);
- return context.createTryStatement(m_lexer->lastLineNumber(), tryBlock, ident, catchHasEval, catchBlock, finallyBlock, firstLine, lastLine);
+ return context.createTryStatement(m_lexer->lastLineNumber(), tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine);
}
template <typename LexerType>
@@ -1512,23 +1509,20 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres
}
case OPENPAREN: {
m_nonTrivialExpressionCount++;
+ int nonLHSCount = m_nonLHSCount;
if (newCount) {
newCount--;
- if (match(OPENPAREN)) {
- int exprEnd = lastTokenEnd();
- TreeArguments arguments = parseArguments(context);
- failIfFalse(arguments);
- base = context.createNewExpr(m_lexer->lastLineNumber(), base, arguments, start, exprEnd, lastTokenEnd());
- } else
- base = context.createNewExpr(m_lexer->lastLineNumber(), base, start, lastTokenEnd());
+ int exprEnd = lastTokenEnd();
+ TreeArguments arguments = parseArguments(context);
+ failIfFalse(arguments);
+ base = context.createNewExpr(m_lexer->lastLineNumber(), base, arguments, start, exprEnd, lastTokenEnd());
} else {
- int nonLHSCount = m_nonLHSCount;
int expressionEnd = lastTokenEnd();
TreeArguments arguments = parseArguments(context);
failIfFalse(arguments);
base = context.makeFunctionCallNode(m_lexer->lastLineNumber(), base, arguments, expressionStart, expressionEnd, lastTokenEnd());
- m_nonLHSCount = nonLHSCount;
}
+ m_nonLHSCount = nonLHSCount;
break;
}
case DOT: {
diff --git a/Source/JavaScriptCore/parser/Parser.h b/Source/JavaScriptCore/parser/Parser.h
index ef176f014..f3d96ff3e 100644
--- a/Source/JavaScriptCore/parser/Parser.h
+++ b/Source/JavaScriptCore/parser/Parser.h
@@ -559,7 +559,7 @@ private:
case CASE:
return "case";
case DEFAULT:
- return "defualt";
+ return "default";
case FOR:
return "for";
case NEW:
diff --git a/Source/JavaScriptCore/parser/ParserArena.h b/Source/JavaScriptCore/parser/ParserArena.h
index 35674b604..49f0ab6bf 100644
--- a/Source/JavaScriptCore/parser/ParserArena.h
+++ b/Source/JavaScriptCore/parser/ParserArena.h
@@ -159,7 +159,7 @@ namespace JSC {
void removeLast();
bool isEmpty() const;
- void reset();
+ JS_EXPORT_PRIVATE void reset();
IdentifierArena& identifierArena() { return *m_identifierArena; }
diff --git a/Source/JavaScriptCore/parser/SyntaxChecker.h b/Source/JavaScriptCore/parser/SyntaxChecker.h
index 270c82385..32cbf7d6c 100644
--- a/Source/JavaScriptCore/parser/SyntaxChecker.h
+++ b/Source/JavaScriptCore/parser/SyntaxChecker.h
@@ -193,7 +193,7 @@ public:
int createBreakStatement(int, const Identifier*, int, int, int, int) { return 1; }
int createContinueStatement(int, int, int, int, int) { return 1; }
int createContinueStatement(int, const Identifier*, int, int, int, int) { return 1; }
- int createTryStatement(int, int, const Identifier*, bool, int, int, int, int) { return 1; }
+ int createTryStatement(int, int, const Identifier*, int, int, int, int) { return 1; }
int createSwitchStatement(int, int, int, int, int, int, int) { return 1; }
int createWhileStatement(int, int, int, int, int) { return 1; }
int createWithStatement(int, int, int, int, int, int, int) { return 1; }
diff --git a/Source/JavaScriptCore/profiler/Profile.h b/Source/JavaScriptCore/profiler/Profile.h
index 6bf29f7a6..9455e3595 100644
--- a/Source/JavaScriptCore/profiler/Profile.h
+++ b/Source/JavaScriptCore/profiler/Profile.h
@@ -44,11 +44,11 @@ namespace JSC {
double totalTime() const { return m_head->totalTime(); }
unsigned int uid() const { return m_uid; }
- void forEach(void (ProfileNode::*)());
+ JS_EXPORT_PRIVATE void forEach(void (ProfileNode::*)());
- void focus(const ProfileNode*);
- void exclude(const ProfileNode*);
- void restoreAll();
+ JS_EXPORT_PRIVATE void focus(const ProfileNode*);
+ JS_EXPORT_PRIVATE void exclude(const ProfileNode*);
+ JS_EXPORT_PRIVATE void restoreAll();
#ifndef NDEBUG
void debugPrintData() const;
diff --git a/Source/JavaScriptCore/profiler/Profiler.cpp b/Source/JavaScriptCore/profiler/Profiler.cpp
index 0a4b547d4..0ecd5b2c9 100644
--- a/Source/JavaScriptCore/profiler/Profiler.cpp
+++ b/Source/JavaScriptCore/profiler/Profiler.cpp
@@ -48,7 +48,7 @@ static const char* GlobalCodeExecution = "(program)";
static const char* AnonymousFunction = "(anonymous function)";
static unsigned ProfilesUID = 0;
-static CallIdentifier createCallIdentifierFromFunctionImp(ExecState*, JSFunction*);
+static CallIdentifier createCallIdentifierFromFunctionImp(ExecState*, JSObject*, const UString& defaultSourceURL, int defaultLineNumber);
Profiler* Profiler::s_sharedProfiler = 0;
Profiler* Profiler::s_sharedEnabledProfilerReference = 0;
@@ -163,23 +163,18 @@ CallIdentifier Profiler::createCallIdentifier(ExecState* exec, JSValue functionV
return CallIdentifier(GlobalCodeExecution, defaultSourceURL, defaultLineNumber);
if (!functionValue.isObject())
return CallIdentifier("(unknown)", defaultSourceURL, defaultLineNumber);
- if (asObject(functionValue)->inherits(&JSFunction::s_info)) {
- JSFunction* function = asFunction(functionValue);
- if (!function->executable()->isHostFunction())
- return createCallIdentifierFromFunctionImp(exec, function);
- }
- if (asObject(functionValue)->inherits(&JSFunction::s_info))
- return CallIdentifier(static_cast<JSFunction*>(asObject(functionValue))->name(exec), defaultSourceURL, defaultLineNumber);
- if (asObject(functionValue)->inherits(&InternalFunction::s_info))
- return CallIdentifier(static_cast<InternalFunction*>(asObject(functionValue))->name(exec), defaultSourceURL, defaultLineNumber);
+ if (asObject(functionValue)->inherits(&JSFunction::s_info) || asObject(functionValue)->inherits(&InternalFunction::s_info))
+ return createCallIdentifierFromFunctionImp(exec, asObject(functionValue), defaultSourceURL, defaultLineNumber);
return CallIdentifier(makeUString("(", asObject(functionValue)->methodTable()->className(asObject(functionValue)), " object)"), defaultSourceURL, defaultLineNumber);
}
-CallIdentifier createCallIdentifierFromFunctionImp(ExecState* exec, JSFunction* function)
+CallIdentifier createCallIdentifierFromFunctionImp(ExecState* exec, JSObject* function, const UString& defaultSourceURL, int defaultLineNumber)
{
- ASSERT(!function->isHostFunction());
- const UString& name = function->calculatedDisplayName(exec);
- return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, function->jsExecutable()->sourceURL(), function->jsExecutable()->lineNo());
+ const UString& name = getCalculatedDisplayName(exec, function);
+ JSFunction* jsFunction = jsDynamicCast<JSFunction*>(function);
+ if (jsFunction && !jsFunction->isHostFunction())
+ return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, jsFunction->jsExecutable()->sourceURL(), jsFunction->jsExecutable()->lineNo());
+ return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, defaultSourceURL, defaultLineNumber);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/ArgList.h b/Source/JavaScriptCore/runtime/ArgList.h
index ac5a4f271..1512a0fa1 100644
--- a/Source/JavaScriptCore/runtime/ArgList.h
+++ b/Source/JavaScriptCore/runtime/ArgList.h
@@ -102,7 +102,7 @@ namespace JSC {
static void markLists(HeapRootVisitor&, ListSet&);
private:
- void slowAppend(JSValue);
+ JS_EXPORT_PRIVATE void slowAppend(JSValue);
EncodedJSValue& slotFor(int item) const
{
@@ -171,7 +171,7 @@ namespace JSC {
bool isEmpty() const { return !m_argCount; }
size_t size() const { return m_argCount; }
- void getSlice(int startIndex, ArgList& result) const;
+ JS_EXPORT_PRIVATE void getSlice(int startIndex, ArgList& result) const;
private:
JSValue* m_args;
diff --git a/Source/JavaScriptCore/runtime/Arguments.cpp b/Source/JavaScriptCore/runtime/Arguments.cpp
index fc136eb7e..6a675ab84 100644
--- a/Source/JavaScriptCore/runtime/Arguments.cpp
+++ b/Source/JavaScriptCore/runtime/Arguments.cpp
@@ -109,7 +109,7 @@ void Arguments::createStrictModeCallerIfNecessary(ExecState* exec)
d->overrodeCaller = true;
PropertyDescriptor descriptor;
- descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(exec), DontEnum | DontDelete | Getter | Setter);
+ descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(exec), DontEnum | DontDelete | Accessor);
methodTable()->defineOwnProperty(this, exec, exec->propertyNames().caller, descriptor, false);
}
@@ -120,7 +120,7 @@ void Arguments::createStrictModeCalleeIfNecessary(ExecState* exec)
d->overrodeCallee = true;
PropertyDescriptor descriptor;
- descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(exec), DontEnum | DontDelete | Getter | Setter);
+ descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(exec), DontEnum | DontDelete | Accessor);
methodTable()->defineOwnProperty(this, exec, exec->propertyNames().callee, descriptor, false);
}
diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
index dcf7a2fae..cb9b12a59 100644
--- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
@@ -197,7 +197,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
if (element.isUndefinedOrNull())
continue;
- UString str = element.toString(exec);
+ UString str = element.toString(exec)->value(exec);
strBuffer[k] = str.impl();
totalSize += str.length();
allStrings8Bit = allStrings8Bit && str.is8Bit();
@@ -272,9 +272,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec)
CallData callData;
CallType callType = getCallData(conversionFunction, callData);
if (callType != CallTypeNone)
- str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec);
+ str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec)->value(exec);
else
- str = element.toString(exec);
+ str = element.toString(exec)->value(exec);
strBuffer.append(str);
}
}
@@ -297,7 +297,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
UString separator;
if (!exec->argument(0).isUndefined())
- separator = exec->argument(0).toString(exec);
+ separator = exec->argument(0).toString(exec)->value(exec);
unsigned k = 0;
if (isJSArray(thisObj)) {
@@ -308,7 +308,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
goto skipFirstLoop;
JSValue element = array->getIndex(k);
if (!element.isUndefinedOrNull())
- strBuffer.append(element.toString(exec));
+ strBuffer.append(element.toString(exec)->value(exec));
k++;
}
@@ -319,7 +319,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
strBuffer.append(',');
JSValue element = array->getIndex(k);
if (!element.isUndefinedOrNull())
- strBuffer.append(element.toString(exec));
+ strBuffer.append(element.toString(exec)->value(exec));
}
} else {
for (; k < length; k++) {
@@ -328,7 +328,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
strBuffer.append(separator);
JSValue element = array->getIndex(k);
if (!element.isUndefinedOrNull())
- strBuffer.append(element.toString(exec));
+ strBuffer.append(element.toString(exec)->value(exec));
}
}
}
@@ -343,7 +343,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
JSValue element = thisObj->get(exec, k);
if (!element.isUndefinedOrNull())
- strBuffer.append(element.toString(exec));
+ strBuffer.append(element.toString(exec)->value(exec));
}
return JSValue::encode(strBuffer.build(exec));
@@ -429,7 +429,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec)
thisObj->methodTable()->putByIndex(thisObj, exec, length + n, exec->argument(n));
else {
PutPropertySlot slot;
- Identifier propertyName(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toString(exec));
+ Identifier propertyName(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toString(exec)->value(exec));
thisObj->methodTable()->put(thisObj, exec, propertyName, exec->argument(n), slot);
}
}
@@ -571,7 +571,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec)
l.append(minObj);
compareResult = call(exec, function, callType, callData, jsUndefined(), l).toNumber(exec);
} else
- compareResult = (jObj.toString(exec) < minObj.toString(exec)) ? -1 : 1;
+ compareResult = (jObj.toString(exec)->value(exec) < minObj.toString(exec)->value(exec)) ? -1 : 1;
if (compareResult < 0) {
themin = j;
diff --git a/Source/JavaScriptCore/runtime/CallData.h b/Source/JavaScriptCore/runtime/CallData.h
index b138f5484..15a6a0a48 100644
--- a/Source/JavaScriptCore/runtime/CallData.h
+++ b/Source/JavaScriptCore/runtime/CallData.h
@@ -57,7 +57,7 @@ namespace JSC {
} js;
};
- JSValue call(ExecState*, JSValue functionObject, CallType, const CallData&, JSValue thisValue, const ArgList&);
+ JS_EXPORT_PRIVATE JSValue call(ExecState*, JSValue functionObject, CallType, const CallData&, JSValue thisValue, const ArgList&);
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/ClassInfo.h b/Source/JavaScriptCore/runtime/ClassInfo.h
index 9fff64e67..3d556d88c 100644
--- a/Source/JavaScriptCore/runtime/ClassInfo.h
+++ b/Source/JavaScriptCore/runtime/ClassInfo.h
@@ -88,7 +88,7 @@ namespace JSC {
HasInstanceFunctionPtr hasInstance;
typedef void (*PutWithAttributesFunctionPtr)(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
- PutWithAttributesFunctionPtr putWithAttributes;
+ PutWithAttributesFunctionPtr putDirectVirtual;
typedef bool (*DefineOwnPropertyFunctionPtr)(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&, bool);
DefineOwnPropertyFunctionPtr defineOwnProperty;
@@ -135,7 +135,7 @@ struct MemberCheck##member { \
&ClassName::getPropertyNames, \
&ClassName::className, \
&ClassName::hasInstance, \
- &ClassName::putWithAttributes, \
+ &ClassName::putDirectVirtual, \
&ClassName::defineOwnProperty, \
&ClassName::getOwnPropertyDescriptor, \
}, \
diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.h b/Source/JavaScriptCore/runtime/CommonSlowPaths.h
index ab4de7da8..86c4bd5c2 100644
--- a/Source/JavaScriptCore/runtime/CommonSlowPaths.h
+++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.h
@@ -76,7 +76,7 @@ inline bool opIn(ExecState* exec, JSValue propName, JSValue baseVal)
if (propName.getUInt32(i))
return baseObj->hasProperty(exec, i);
- Identifier property(exec, propName.toString(exec));
+ Identifier property(exec, propName.toString(exec)->value(exec));
if (exec->globalData().exception)
return false;
return baseObj->hasProperty(exec, property);
diff --git a/Source/JavaScriptCore/runtime/Completion.cpp b/Source/JavaScriptCore/runtime/Completion.cpp
index c3d9e6947..98a66589a 100644
--- a/Source/JavaScriptCore/runtime/Completion.cpp
+++ b/Source/JavaScriptCore/runtime/Completion.cpp
@@ -24,6 +24,7 @@
#include "Completion.h"
#include "CallFrame.h"
+#include "CodeProfiling.h"
#include "JSGlobalObject.h"
#include "JSLock.h"
#include "Interpreter.h"
@@ -55,6 +56,8 @@ JSValue evaluate(ExecState* exec, ScopeChainNode* scopeChain, const SourceCode&
JSLock lock(exec);
ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable());
+ CodeProfiling profile(source);
+
ProgramExecutable* program = ProgramExecutable::create(exec, source);
if (!program) {
if (returnedException)
diff --git a/Source/JavaScriptCore/runtime/Completion.h b/Source/JavaScriptCore/runtime/Completion.h
index c3dbdfc58..3d3b86fe4 100644
--- a/Source/JavaScriptCore/runtime/Completion.h
+++ b/Source/JavaScriptCore/runtime/Completion.h
@@ -31,8 +31,8 @@ namespace JSC {
class ScopeChainNode;
class SourceCode;
- bool checkSyntax(ExecState*, const SourceCode&, JSValue* exception = 0);
- JSValue evaluate(ExecState*, ScopeChainNode*, const SourceCode&, JSValue thisValue = JSValue(), JSValue* exception = 0);
+ JS_EXPORT_PRIVATE bool checkSyntax(ExecState*, const SourceCode&, JSValue* exception = 0);
+ JS_EXPORT_PRIVATE JSValue evaluate(ExecState*, ScopeChainNode*, const SourceCode&, JSValue thisValue = JSValue(), JSValue* exception = 0);
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/ConstructData.h b/Source/JavaScriptCore/runtime/ConstructData.h
index cc8f46977..d7a3c73d3 100644
--- a/Source/JavaScriptCore/runtime/ConstructData.h
+++ b/Source/JavaScriptCore/runtime/ConstructData.h
@@ -56,7 +56,7 @@ namespace JSC {
} js;
};
- JSObject* construct(ExecState*, JSValue constructor, ConstructType, const ConstructData&, const ArgList&);
+ JS_EXPORT_PRIVATE JSObject* construct(ExecState*, JSValue constructor, ConstructType, const ConstructData&, const ArgList&);
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/DateConstructor.cpp b/Source/JavaScriptCore/runtime/DateConstructor.cpp
index 79c5181eb..365172294 100644
--- a/Source/JavaScriptCore/runtime/DateConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/DateConstructor.cpp
@@ -185,7 +185,7 @@ CallType DateConstructor::getCallData(JSCell*, CallData& callData)
static EncodedJSValue JSC_HOST_CALL dateParse(ExecState* exec)
{
- return JSValue::encode(jsNumber(parseDate(exec, exec->argument(0).toString(exec))));
+ return JSValue::encode(jsNumber(parseDate(exec, exec->argument(0).toString(exec)->value(exec))));
}
static EncodedJSValue JSC_HOST_CALL dateNow(ExecState*)
diff --git a/Source/JavaScriptCore/runtime/DateInstance.h b/Source/JavaScriptCore/runtime/DateInstance.h
index 3edfb0970..7c976a514 100644
--- a/Source/JavaScriptCore/runtime/DateInstance.h
+++ b/Source/JavaScriptCore/runtime/DateInstance.h
@@ -31,9 +31,9 @@ namespace JSC {
class DateInstance : public JSWrapperObject {
protected:
- DateInstance(ExecState*, Structure*);
+ JS_EXPORT_PRIVATE DateInstance(ExecState*, Structure*);
void finishCreation(JSGlobalData&);
- void finishCreation(JSGlobalData&, double);
+ JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, double);
static void destroy(JSCell*);
diff --git a/Source/JavaScriptCore/runtime/DatePrototype.cpp b/Source/JavaScriptCore/runtime/DatePrototype.cpp
index 96dea01db..922fb0a86 100644
--- a/Source/JavaScriptCore/runtime/DatePrototype.cpp
+++ b/Source/JavaScriptCore/runtime/DatePrototype.cpp
@@ -60,8 +60,10 @@
#include <sys/timeb.h>
#endif
-#if PLATFORM(MAC) || PLATFORM(IOS)
+#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(WX) || (PLATFORM(QT) && OS(DARWIN))
#include <CoreFoundation/CoreFoundation.h>
+#elif USE(ICU_UNICODE)
+#include <unicode/udat.h>
#endif
#if OS(WINCE) && !PLATFORM(QT)
@@ -128,7 +130,7 @@ namespace JSC {
enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime };
-#if PLATFORM(MAC) || PLATFORM(IOS)
+#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(WX) || (PLATFORM(QT) && OS(DARWIN))
// FIXME: Since this is superior to the strftime-based version, why limit this to PLATFORM(MAC)?
// Instead we should consider using this whenever USE(CF) is true.
@@ -154,13 +156,13 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMil
bool useCustomFormat = false;
UString customFormatString;
- UString arg0String = exec->argument(0).toString(exec);
+ UString arg0String = exec->argument(0).toString(exec)->value(exec);
if (arg0String == "custom" && !exec->argument(1).isUndefined()) {
useCustomFormat = true;
- customFormatString = exec->argument(1).toString(exec);
+ customFormatString = exec->argument(1).toString(exec)->value(exec);
} else if (format == LocaleDateAndTime && !exec->argument(1).isUndefined()) {
dateStyle = styleFromArgString(arg0String, dateStyle);
- timeStyle = styleFromArgString(exec->argument(1).toString(exec), timeStyle);
+ timeStyle = styleFromArgString(exec->argument(1).toString(exec)->value(exec), timeStyle);
} else if (format != LocaleTime && !exec->argument(0).isUndefined())
dateStyle = styleFromArgString(arg0String, dateStyle);
else if (format != LocaleDate && !exec->argument(0).isUndefined())
@@ -195,7 +197,29 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMil
return jsNontrivialString(exec, UString(buffer, length));
}
-#else // !PLATFORM(MAC) && !PLATFORM(IOS)
+#elif USE(ICU_UNICODE) && !UCONFIG_NO_FORMATTING
+
+static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, double timeInMilliseconds, LocaleDateTimeFormat format)
+{
+ UDateFormatStyle timeStyle = (format != LocaleDate ? UDAT_LONG : UDAT_NONE);
+ UDateFormatStyle dateStyle = (format != LocaleTime ? UDAT_LONG : UDAT_NONE);
+
+ UErrorCode status = U_ZERO_ERROR;
+ UDateFormat* df = udat_open(timeStyle, dateStyle, 0, 0, -1, 0, 0, &status);
+ if (!df)
+ return jsEmptyString(exec);
+
+ UChar buffer[128];
+ int32_t length;
+ length = udat_format(df, timeInMilliseconds, buffer, 128, 0, &status);
+ udat_close(df);
+ if (status != U_ZERO_ERROR)
+ return jsEmptyString(exec);
+
+ return jsNontrivialString(exec, UString(buffer, length));
+}
+
+#else
static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, LocaleDateTimeFormat format)
{
diff --git a/Source/JavaScriptCore/runtime/Error.cpp b/Source/JavaScriptCore/runtime/Error.cpp
index 24f5da4f2..0947e3c20 100644
--- a/Source/JavaScriptCore/runtime/Error.cpp
+++ b/Source/JavaScriptCore/runtime/Error.cpp
@@ -37,7 +37,6 @@
namespace JSC {
static const char* linePropertyName = "line";
-static const char* sourceIdPropertyName = "sourceId";
static const char* sourceURLPropertyName = "sourceURL";
JSObject* createError(JSGlobalObject* globalObject, const UString& message)
@@ -119,15 +118,12 @@ JSObject* createURIError(ExecState* exec, const UString& message)
JSObject* addErrorInfo(JSGlobalData* globalData, JSObject* error, int line, const SourceCode& source)
{
- intptr_t sourceID = source.provider()->asID();
const UString& sourceURL = source.provider()->url();
if (line != -1)
- error->putWithAttributes(globalData, Identifier(globalData, linePropertyName), jsNumber(line), ReadOnly | DontDelete);
- if (sourceID != -1)
- error->putWithAttributes(globalData, Identifier(globalData, sourceIdPropertyName), jsNumber((double)sourceID), ReadOnly | DontDelete);
+ error->putDirect(*globalData, Identifier(globalData, linePropertyName), jsNumber(line), ReadOnly | DontDelete);
if (!sourceURL.isNull())
- error->putWithAttributes(globalData, Identifier(globalData, sourceURLPropertyName), jsString(globalData, sourceURL), ReadOnly | DontDelete);
+ error->putDirect(*globalData, Identifier(globalData, sourceURLPropertyName), jsString(globalData, sourceURL), ReadOnly | DontDelete);
return error;
}
@@ -140,7 +136,6 @@ JSObject* addErrorInfo(ExecState* exec, JSObject* error, int line, const SourceC
bool hasErrorInfo(ExecState* exec, JSObject* error)
{
return error->hasProperty(exec, Identifier(exec, linePropertyName))
- || error->hasProperty(exec, Identifier(exec, sourceIdPropertyName))
|| error->hasProperty(exec, Identifier(exec, sourceURLPropertyName));
}
diff --git a/Source/JavaScriptCore/runtime/Error.h b/Source/JavaScriptCore/runtime/Error.h
index b807d4ab4..88b540a35 100644
--- a/Source/JavaScriptCore/runtime/Error.h
+++ b/Source/JavaScriptCore/runtime/Error.h
@@ -46,12 +46,12 @@ namespace JSC {
JSObject* createTypeError(JSGlobalObject*, const UString&);
JSObject* createURIError(JSGlobalObject*, const UString&);
// ExecState wrappers.
- JSObject* createError(ExecState*, const UString&);
+ JS_EXPORT_PRIVATE JSObject* createError(ExecState*, const UString&);
JSObject* createEvalError(ExecState*, const UString&);
- JSObject* createRangeError(ExecState*, const UString&);
- JSObject* createReferenceError(ExecState*, const UString&);
- JSObject* createSyntaxError(ExecState*, const UString&);
- JSObject* createTypeError(ExecState*, const UString&);
+ JS_EXPORT_PRIVATE JSObject* createRangeError(ExecState*, const UString&);
+ JS_EXPORT_PRIVATE JSObject* createReferenceError(ExecState*, const UString&);
+ JS_EXPORT_PRIVATE JSObject* createSyntaxError(ExecState*, const UString&);
+ JS_EXPORT_PRIVATE JSObject* createTypeError(ExecState*, const UString&);
JSObject* createURIError(ExecState*, const UString&);
// Methods to add
@@ -61,12 +61,12 @@ namespace JSC {
JSObject* addErrorInfo(ExecState*, JSObject* error, int line, const SourceCode&);
// Methods to throw Errors.
- JSValue throwError(ExecState*, JSValue);
- JSObject* throwError(ExecState*, JSObject*);
+ JS_EXPORT_PRIVATE JSValue throwError(ExecState*, JSValue);
+ JS_EXPORT_PRIVATE JSObject* throwError(ExecState*, JSObject*);
// Convenience wrappers, create an throw an exception with a default message.
- JSObject* throwTypeError(ExecState*);
- JSObject* throwSyntaxError(ExecState*);
+ JS_EXPORT_PRIVATE JSObject* throwTypeError(ExecState*);
+ JS_EXPORT_PRIVATE JSObject* throwSyntaxError(ExecState*);
// Convenience wrappers, wrap result as an EncodedJSValue.
inline EncodedJSValue throwVMError(ExecState* exec, JSValue error) { return JSValue::encode(throwError(exec, error)); }
diff --git a/Source/JavaScriptCore/runtime/ErrorInstance.h b/Source/JavaScriptCore/runtime/ErrorInstance.h
index 888bfe856..d6fa32f99 100644
--- a/Source/JavaScriptCore/runtime/ErrorInstance.h
+++ b/Source/JavaScriptCore/runtime/ErrorInstance.h
@@ -42,14 +42,10 @@ namespace JSC {
instance->finishCreation(globalData, message);
return instance;
}
+
static ErrorInstance* create(ExecState* exec, Structure* structure, JSValue message)
{
- if (message.isUndefined()) {
- ErrorInstance* instance = new (NotNull, allocateCell<ErrorInstance>(*exec->heap())) ErrorInstance(exec->globalData(), structure);
- instance->finishCreation(exec->globalData(), UString());
- return instance;
- }
- return create(exec->globalData(), structure, message.toString(exec));
+ return create(exec->globalData(), structure, message.isUndefined() ? UString() : message.toString(exec)->value(exec));
}
bool appendSourceToMessage() { return m_appendSourceToMessage; }
diff --git a/Source/JavaScriptCore/runtime/ErrorPrototype.cpp b/Source/JavaScriptCore/runtime/ErrorPrototype.cpp
index e1a395c0e..7af294782 100644
--- a/Source/JavaScriptCore/runtime/ErrorPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/ErrorPrototype.cpp
@@ -101,7 +101,7 @@ EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec)
if (name.isUndefined())
nameString = "Error";
else {
- nameString = name.toString(exec);
+ nameString = name.toString(exec)->value(exec);
if (exec->hadException())
return JSValue::encode(jsUndefined());
}
@@ -118,7 +118,7 @@ EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec)
if (message.isUndefined())
messageString = "";
else {
- messageString = message.toString(exec);
+ messageString = message.toString(exec)->value(exec);
if (exec->hadException())
return JSValue::encode(jsUndefined());
}
diff --git a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
index 05e971f7f..ce63ae9af 100644
--- a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
+++ b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
@@ -113,7 +113,7 @@ JSObject* createUndefinedVariableError(ExecState* exec, const Identifier& ident)
JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value)
{
- UString errorMessage = makeUString("'", value.toString(exec), "' is not a valid argument for '", op, "'");
+ UString errorMessage = makeUString("'", value.toString(exec)->value(exec), "' is not a valid argument for '", op, "'");
JSObject* exception = createTypeError(exec, errorMessage);
ASSERT(exception->isErrorInstance());
static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
@@ -122,7 +122,7 @@ JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value
JSObject* createNotAConstructorError(ExecState* exec, JSValue value)
{
- UString errorMessage = makeUString("'", value.toString(exec), "' is not a constructor");
+ UString errorMessage = makeUString("'", value.toString(exec)->value(exec), "' is not a constructor");
JSObject* exception = createTypeError(exec, errorMessage);
ASSERT(exception->isErrorInstance());
static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
@@ -131,7 +131,7 @@ JSObject* createNotAConstructorError(ExecState* exec, JSValue value)
JSObject* createNotAFunctionError(ExecState* exec, JSValue value)
{
- UString errorMessage = makeUString("'", value.toString(exec), "' is not a function");
+ UString errorMessage = makeUString("'", value.toString(exec)->value(exec), "' is not a function");
JSObject* exception = createTypeError(exec, errorMessage);
ASSERT(exception->isErrorInstance());
static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
@@ -140,7 +140,7 @@ JSObject* createNotAFunctionError(ExecState* exec, JSValue value)
JSObject* createNotAnObjectError(ExecState* exec, JSValue value)
{
- UString errorMessage = makeUString("'", value.toString(exec), "' is not an object");
+ UString errorMessage = makeUString("'", value.toString(exec)->value(exec), "' is not an object");
JSObject* exception = createTypeError(exec, errorMessage);
ASSERT(exception->isErrorInstance());
static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
diff --git a/Source/JavaScriptCore/runtime/ExceptionHelpers.h b/Source/JavaScriptCore/runtime/ExceptionHelpers.h
index f71d1a308..7bffd294b 100644
--- a/Source/JavaScriptCore/runtime/ExceptionHelpers.h
+++ b/Source/JavaScriptCore/runtime/ExceptionHelpers.h
@@ -33,15 +33,15 @@
namespace JSC {
-JSObject* createInterruptedExecutionException(JSGlobalData*);
+JS_EXPORT_PRIVATE JSObject* createInterruptedExecutionException(JSGlobalData*);
bool isInterruptedExecutionException(JSObject*);
bool isInterruptedExecutionException(JSValue);
JSObject* createTerminatedExecutionException(JSGlobalData*);
bool isTerminatedExecutionException(JSObject*);
-bool isTerminatedExecutionException(JSValue);
+JS_EXPORT_PRIVATE bool isTerminatedExecutionException(JSValue);
-JSObject* createStackOverflowError(ExecState*);
+JS_EXPORT_PRIVATE JSObject* createStackOverflowError(ExecState*);
JSObject* createStackOverflowError(JSGlobalObject*);
JSObject* createOutOfMemoryError(JSGlobalObject*);
JSObject* createUndefinedVariableError(ExecState*, const Identifier&);
@@ -79,7 +79,7 @@ public:
return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
}
- static JS_EXPORTDATA const ClassInfo s_info;
+ static const ClassInfo s_info;
};
class TerminatedExecutionError : public JSNonFinalObject {
diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp
index a364e84da..c67c54cd2 100644
--- a/Source/JavaScriptCore/runtime/Executable.cpp
+++ b/Source/JavaScriptCore/runtime/Executable.cpp
@@ -30,6 +30,7 @@
#include "CodeBlock.h"
#include "DFGDriver.h"
#include "JIT.h"
+#include "JITDriver.h"
#include "Parser.h"
#include "UStringBuilder.h"
#include "Vector.h"
@@ -130,22 +131,24 @@ void ProgramExecutable::destroy(JSCell* cell)
const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
-FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext)
+FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext)
: ScriptExecutable(globalData.functionExecutableStructure.get(), globalData, source, inStrictContext)
, m_numCapturedVariables(0)
, m_forceUsesArguments(forceUsesArguments)
, m_parameters(parameters)
, m_name(name)
+ , m_inferredName(inferredName)
, m_symbolTable(0)
{
}
-FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext)
+FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext)
: ScriptExecutable(exec->globalData().functionExecutableStructure.get(), exec, source, inStrictContext)
, m_numCapturedVariables(0)
, m_forceUsesArguments(forceUsesArguments)
, m_parameters(parameters)
, m_name(name)
+ , m_inferredName(inferredName)
, m_symbolTable(0)
{
}
@@ -209,27 +212,8 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope
}
#if ENABLE(JIT)
- if (exec->globalData().canUseJIT()) {
- bool dfgCompiled = false;
- if (jitType == JITCode::DFGJIT)
- dfgCompiled = DFG::tryCompile(exec, m_evalCodeBlock.get(), m_jitCodeForCall);
- if (dfgCompiled)
- ASSERT(!m_evalCodeBlock->alternative() || !m_evalCodeBlock->alternative()->hasIncomingCalls());
- else {
- if (m_evalCodeBlock->alternative()) {
- // There is already an alternative piece of code compiled with a different
- // JIT, so we can silently fail.
- m_evalCodeBlock = static_pointer_cast<EvalCodeBlock>(m_evalCodeBlock->releaseAlternative());
- return 0;
- }
- m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_evalCodeBlock.get());
- }
-#if !ENABLE(OPCODE_SAMPLING)
- if (!BytecodeGenerator::dumpsGeneratedCode())
- m_evalCodeBlock->handleBytecodeDiscardingOpportunity();
-#endif
- m_evalCodeBlock->setJITCode(m_jitCodeForCall, MacroAssemblerCodePtr());
- }
+ if (!jitCompileIfAppropriate(*globalData, m_evalCodeBlock, m_jitCodeForCall, jitType))
+ return 0;
#endif
#if ENABLE(JIT)
@@ -354,26 +338,8 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc
}
#if ENABLE(JIT)
- if (exec->globalData().canUseJIT()) {
- bool dfgCompiled = false;
- if (jitType == JITCode::DFGJIT)
- dfgCompiled = DFG::tryCompile(exec, m_programCodeBlock.get(), m_jitCodeForCall);
- if (dfgCompiled) {
- if (m_programCodeBlock->alternative())
- m_programCodeBlock->alternative()->unlinkIncomingCalls();
- } else {
- if (m_programCodeBlock->alternative()) {
- m_programCodeBlock = static_pointer_cast<ProgramCodeBlock>(m_programCodeBlock->releaseAlternative());
- return 0;
- }
- m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_programCodeBlock.get());
- }
-#if !ENABLE(OPCODE_SAMPLING)
- if (!BytecodeGenerator::dumpsGeneratedCode())
- m_programCodeBlock->handleBytecodeDiscardingOpportunity();
-#endif
- m_programCodeBlock->setJITCode(m_jitCodeForCall, MacroAssemblerCodePtr());
- }
+ if (!jitCompileIfAppropriate(*globalData, m_programCodeBlock, m_jitCodeForCall, jitType))
+ return 0;
#endif
#if ENABLE(JIT)
@@ -540,29 +506,8 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain
m_symbolTable = m_codeBlockForCall->sharedSymbolTable();
#if ENABLE(JIT)
- JSGlobalData* globalData = scopeChainNode->globalData;
- if (globalData->canUseJIT()) {
- bool dfgCompiled = false;
- if (jitType == JITCode::DFGJIT)
- dfgCompiled = DFG::tryCompileFunction(exec, m_codeBlockForCall.get(), m_jitCodeForCall, m_jitCodeForCallWithArityCheck);
- if (dfgCompiled) {
- if (m_codeBlockForCall->alternative())
- m_codeBlockForCall->alternative()->unlinkIncomingCalls();
- } else {
- if (m_codeBlockForCall->alternative()) {
- m_codeBlockForCall = static_pointer_cast<FunctionCodeBlock>(m_codeBlockForCall->releaseAlternative());
- m_symbolTable = m_codeBlockForCall->sharedSymbolTable();
- return 0;
- }
- m_jitCodeForCall = JIT::compile(globalData, m_codeBlockForCall.get(), &m_jitCodeForCallWithArityCheck);
- }
-#if !ENABLE(OPCODE_SAMPLING)
- if (!BytecodeGenerator::dumpsGeneratedCode())
- m_codeBlockForCall->handleBytecodeDiscardingOpportunity();
-#endif
-
- m_codeBlockForCall->setJITCode(m_jitCodeForCall, m_jitCodeForCallWithArityCheck);
- }
+ if (!jitCompileFunctionIfAppropriate(exec->globalData(), m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, jitType))
+ return 0;
#endif
#if ENABLE(JIT)
@@ -603,29 +548,8 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, Scope
m_symbolTable = m_codeBlockForConstruct->sharedSymbolTable();
#if ENABLE(JIT)
- JSGlobalData* globalData = scopeChainNode->globalData;
- if (globalData->canUseJIT()) {
- bool dfgCompiled = false;
- if (jitType == JITCode::DFGJIT)
- dfgCompiled = DFG::tryCompileFunction(exec, m_codeBlockForConstruct.get(), m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck);
- if (dfgCompiled) {
- if (m_codeBlockForConstruct->alternative())
- m_codeBlockForConstruct->alternative()->unlinkIncomingCalls();
- } else {
- if (m_codeBlockForConstruct->alternative()) {
- m_codeBlockForConstruct = static_pointer_cast<FunctionCodeBlock>(m_codeBlockForConstruct->releaseAlternative());
- m_symbolTable = m_codeBlockForConstruct->sharedSymbolTable();
- return 0;
- }
- m_jitCodeForConstruct = JIT::compile(globalData, m_codeBlockForConstruct.get(), &m_jitCodeForConstructWithArityCheck);
- }
-#if !ENABLE(OPCODE_SAMPLING)
- if (!BytecodeGenerator::dumpsGeneratedCode())
- m_codeBlockForConstruct->handleBytecodeDiscardingOpportunity();
-#endif
-
- m_codeBlockForConstruct->setJITCode(m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck);
- }
+ if (!jitCompileFunctionIfAppropriate(exec->globalData(), m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, jitType))
+ return 0;
#endif
#if ENABLE(JIT)
@@ -738,7 +662,7 @@ FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& functio
FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
ASSERT(body);
- return FunctionExecutable::create(exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
+ return FunctionExecutable::create(exec->globalData(), functionName, functionName, body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
}
UString FunctionExecutable::paramString() const
diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h
index cc44d61a7..6800b5a82 100644
--- a/Source/JavaScriptCore/runtime/Executable.h
+++ b/Source/JavaScriptCore/runtime/Executable.h
@@ -87,7 +87,7 @@ namespace JSC {
static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); }
- static const ClassInfo s_info;
+ static JS_EXPORTDATA const ClassInfo s_info;
protected:
static const unsigned StructureFlags = 0;
@@ -456,17 +456,17 @@ namespace JSC {
public:
typedef ScriptExecutable Base;
- static FunctionExecutable* create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
+ static FunctionExecutable* create(ExecState* exec, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
{
- FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(*exec->heap())) FunctionExecutable(exec, name, source, forceUsesArguments, parameters, isInStrictContext);
+ FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(*exec->heap())) FunctionExecutable(exec, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext);
executable->finishCreation(exec->globalData(), name, firstLine, lastLine);
exec->globalData().heap.addFinalizer(executable, &finalize);
return executable;
}
- static FunctionExecutable* create(JSGlobalData& globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
+ static FunctionExecutable* create(JSGlobalData& globalData, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
{
- FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, isInStrictContext);
+ FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext);
executable->finishCreation(globalData, name, firstLine, lastLine);
globalData.heap.addFinalizer(executable, &finalize);
return executable;
@@ -608,6 +608,7 @@ namespace JSC {
}
const Identifier& name() { return m_name; }
+ const Identifier& inferredName() { return m_inferredName; }
JSString* nameValue() const { return m_nameValue.get(); }
size_t parameterCount() const { return m_parameters->size(); } // Excluding 'this'!
unsigned capturedVariableCount() const { return m_numCapturedVariables; }
@@ -639,8 +640,8 @@ namespace JSC {
}
private:
- FunctionExecutable(JSGlobalData&, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool);
- FunctionExecutable(ExecState*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool);
+ FunctionExecutable(JSGlobalData&, const Identifier& name, const Identifier& inferredName, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool);
+ FunctionExecutable(ExecState*, const Identifier& name, const Identifier& inferredName, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool);
JSObject* compileForCallInternal(ExecState*, ScopeChainNode*, JITCode::JITType);
JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*, JITCode::JITType);
@@ -661,6 +662,7 @@ namespace JSC {
OwnPtr<FunctionCodeBlock> m_codeBlockForCall;
OwnPtr<FunctionCodeBlock> m_codeBlockForConstruct;
Identifier m_name;
+ Identifier m_inferredName;
WriteBarrier<JSString> m_nameValue;
SharedSymbolTable* m_symbolTable;
};
diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
index e08e58c83..956b2161d 100644
--- a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
@@ -96,17 +96,17 @@ JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState* exec, JSGlobalObj
if (args.isEmpty())
program = "(function() { \n})";
else if (args.size() == 1)
- program = makeUString("(function() { ", args.at(0).toString(exec), "\n})");
+ program = makeUString("(function() { ", args.at(0).toString(exec)->value(exec), "\n})");
else {
UStringBuilder builder;
builder.append("(function(");
- builder.append(args.at(0).toString(exec));
+ builder.append(args.at(0).toString(exec)->value(exec));
for (size_t i = 1; i < args.size() - 1; i++) {
builder.append(",");
- builder.append(args.at(i).toString(exec));
+ builder.append(args.at(i).toString(exec)->value(exec));
}
builder.append(") { ");
- builder.append(args.at(args.size() - 1).toString(exec));
+ builder.append(args.at(args.size() - 1).toString(exec)->value(exec));
builder.append("\n})");
program = builder.toUString();
}
diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.h b/Source/JavaScriptCore/runtime/FunctionConstructor.h
index 7141916cf..31986b70a 100644
--- a/Source/JavaScriptCore/runtime/FunctionConstructor.h
+++ b/Source/JavaScriptCore/runtime/FunctionConstructor.h
@@ -59,7 +59,7 @@ namespace JSC {
JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&, const Identifier& functionName, const UString& sourceURL, const WTF::TextPosition&);
JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&);
- JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState*, JSGlobalObject*, const ArgList&, const Identifier&, const UString&, const WTF::TextPosition&);
+ JS_EXPORT_PRIVATE JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState*, JSGlobalObject*, const ArgList&, const Identifier&, const UString&, const WTF::TextPosition&);
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
index 049b7b914..266ddc241 100644
--- a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
@@ -207,7 +207,7 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncBind(ExecState* exec)
length = targetLength - numBoundArgs;
}
- Identifier name(exec, target.get(exec, exec->propertyNames().name).toString(exec));
+ Identifier name(exec, target.get(exec, exec->propertyNames().name).toString(exec)->value(exec));
return JSValue::encode(JSBoundFunction::create(exec, globalObject, targetObject, exec->argument(0), boundArgs, length, name));
}
diff --git a/Source/JavaScriptCore/runtime/GetterSetter.h b/Source/JavaScriptCore/runtime/GetterSetter.h
index 293bf6434..b8caf0198 100644
--- a/Source/JavaScriptCore/runtime/GetterSetter.h
+++ b/Source/JavaScriptCore/runtime/GetterSetter.h
@@ -56,9 +56,9 @@ namespace JSC {
static void visitChildren(JSCell*, SlotVisitor&);
JSObject* getter() const { return m_getter.get(); }
- void setGetter(JSGlobalData& globalData, JSObject* getter) { m_getter.set(globalData, this, getter); }
+ void setGetter(JSGlobalData& globalData, JSObject* getter) { m_getter.setMayBeNull(globalData, this, getter); }
JSObject* setter() const { return m_setter.get(); }
- void setSetter(JSGlobalData& globalData, JSObject* setter) { m_setter.set(globalData, this, setter); }
+ void setSetter(JSGlobalData& globalData, JSObject* setter) { m_setter.setMayBeNull(globalData, this, setter); }
static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
{
return Structure::create(globalData, globalObject, prototype, TypeInfo(GetterSetterType, OverridesVisitChildren), &s_info);
diff --git a/Source/JavaScriptCore/runtime/Identifier.h b/Source/JavaScriptCore/runtime/Identifier.h
index 2cc88b256..947c95b33 100644
--- a/Source/JavaScriptCore/runtime/Identifier.h
+++ b/Source/JavaScriptCore/runtime/Identifier.h
@@ -56,14 +56,14 @@ namespace JSC {
static Identifier createLCharFromUChar(JSGlobalData* globalData, const UChar* s, int length) { return Identifier(globalData, add8(globalData, s, length)); }
- static Identifier from(ExecState* exec, unsigned y);
- static Identifier from(ExecState* exec, int y);
+ JS_EXPORT_PRIVATE static Identifier from(ExecState* exec, unsigned y);
+ JS_EXPORT_PRIVATE static Identifier from(ExecState* exec, int y);
static Identifier from(ExecState* exec, double y);
static Identifier from(JSGlobalData*, unsigned y);
static Identifier from(JSGlobalData*, int y);
static Identifier from(JSGlobalData*, double y);
- static uint32_t toUInt32(const UString&, bool& ok);
+ JS_EXPORT_PRIVATE static uint32_t toUInt32(const UString&, bool& ok);
uint32_t toUInt32(bool& ok) const { return toUInt32(m_string, ok); }
unsigned toArrayIndex(bool& ok) const;
@@ -84,7 +84,7 @@ namespace JSC {
static bool equal(const StringImpl*, const UChar*, unsigned length);
static bool equal(const StringImpl* a, const StringImpl* b) { return ::equal(a, b); }
- static PassRefPtr<StringImpl> add(ExecState*, const char*); // Only to be used with string literals.
+ JS_EXPORT_PRIVATE static PassRefPtr<StringImpl> add(ExecState*, const char*); // Only to be used with string literals.
static PassRefPtr<StringImpl> add(JSGlobalData*, const char*); // Only to be used with string literals.
private:
@@ -119,11 +119,11 @@ namespace JSC {
return addSlowCase(globalData, r);
}
- static PassRefPtr<StringImpl> addSlowCase(ExecState*, StringImpl* r);
- static PassRefPtr<StringImpl> addSlowCase(JSGlobalData*, StringImpl* r);
+ JS_EXPORT_PRIVATE static PassRefPtr<StringImpl> addSlowCase(ExecState*, StringImpl* r);
+ JS_EXPORT_PRIVATE static PassRefPtr<StringImpl> addSlowCase(JSGlobalData*, StringImpl* r);
- static void checkCurrentIdentifierTable(ExecState*);
- static void checkCurrentIdentifierTable(JSGlobalData*);
+ JS_EXPORT_PRIVATE static void checkCurrentIdentifierTable(ExecState*);
+ JS_EXPORT_PRIVATE static void checkCurrentIdentifierTable(JSGlobalData*);
};
template <> ALWAYS_INLINE bool Identifier::canUseSingleCharacterString(LChar)
diff --git a/Source/JavaScriptCore/runtime/InitializeThreading.h b/Source/JavaScriptCore/runtime/InitializeThreading.h
index 1a93ccb9b..91301a0d8 100644
--- a/Source/JavaScriptCore/runtime/InitializeThreading.h
+++ b/Source/JavaScriptCore/runtime/InitializeThreading.h
@@ -33,7 +33,7 @@ namespace JSC {
// This function must be called from the main thread. It is safe to call it repeatedly.
// Darwin is an exception to this rule: it is OK to call this function from any thread, even reentrantly.
- void initializeThreading();
+ JS_EXPORT_PRIVATE void initializeThreading();
}
diff --git a/Source/JavaScriptCore/runtime/InternalFunction.h b/Source/JavaScriptCore/runtime/InternalFunction.h
index a038b7ae1..532bd0c8d 100644
--- a/Source/JavaScriptCore/runtime/InternalFunction.h
+++ b/Source/JavaScriptCore/runtime/InternalFunction.h
@@ -37,7 +37,7 @@ namespace JSC {
static JS_EXPORTDATA const ClassInfo s_info;
- const UString& name(ExecState*);
+ JS_EXPORT_PRIVATE const UString& name(ExecState*);
const UString displayName(ExecState*);
const UString calculatedDisplayName(ExecState*);
@@ -49,9 +49,9 @@ namespace JSC {
protected:
static const unsigned StructureFlags = ImplementsHasInstance | JSObject::StructureFlags;
- InternalFunction(JSGlobalObject*, Structure*);
+ JS_EXPORT_PRIVATE InternalFunction(JSGlobalObject*, Structure*);
- void finishCreation(JSGlobalData&, const Identifier& name);
+ JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, const Identifier& name);
static CallType getCallData(JSCell*, CallData&);
};
diff --git a/Source/JavaScriptCore/runtime/JSActivation.cpp b/Source/JavaScriptCore/runtime/JSActivation.cpp
index 83d1ee493..3e05738eb 100644
--- a/Source/JavaScriptCore/runtime/JSActivation.cpp
+++ b/Source/JavaScriptCore/runtime/JSActivation.cpp
@@ -45,7 +45,7 @@ JSActivation::JSActivation(CallFrame* callFrame, FunctionExecutable* functionExe
: Base(callFrame->globalData(), callFrame->globalData().activationStructure.get(), functionExecutable->symbolTable(), callFrame->registers())
, m_numCapturedArgs(max(callFrame->argumentCount(), functionExecutable->parameterCount()))
, m_numCapturedVars(functionExecutable->capturedVariableCount())
- , m_requiresDynamicChecks(functionExecutable->usesEval())
+ , m_requiresDynamicChecks(functionExecutable->usesEval() && !functionExecutable->isStrictMode())
, m_argumentsRegister(functionExecutable->generatedBytecode().argumentsRegister())
{
}
@@ -184,11 +184,11 @@ void JSActivation::put(JSCell* cell, ExecState* exec, const Identifier& property
// properties are non-standard extensions that other implementations do not
// expose in the activation object.
ASSERT(!thisObject->hasGetterSetterProperties());
- thisObject->putDirect(exec->globalData(), propertyName, value, 0, true, slot);
+ thisObject->putOwnDataProperty(exec->globalData(), propertyName, value, slot);
}
// FIXME: Make this function honor ReadOnly (const) and DontEnum
-void JSActivation::putWithAttributes(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
+void JSActivation::putDirectVirtual(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
{
JSActivation* thisObject = jsCast<JSActivation*>(object);
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
@@ -200,7 +200,7 @@ void JSActivation::putWithAttributes(JSObject* object, ExecState* exec, const Id
// properties are non-standard extensions that other implementations do not
// expose in the activation object.
ASSERT(!thisObject->hasGetterSetterProperties());
- JSObject::putWithAttributes(thisObject, exec, propertyName, value, attributes);
+ JSObject::putDirectVirtual(thisObject, exec, propertyName, value, attributes);
}
bool JSActivation::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
diff --git a/Source/JavaScriptCore/runtime/JSActivation.h b/Source/JavaScriptCore/runtime/JSActivation.h
index 2ce053e05..c18492344 100644
--- a/Source/JavaScriptCore/runtime/JSActivation.h
+++ b/Source/JavaScriptCore/runtime/JSActivation.h
@@ -64,7 +64,7 @@ namespace JSC {
static void put(JSCell*, ExecState*, const Identifier&, JSValue, PutPropertySlot&);
- static void putWithAttributes(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes);
+ static void putDirectVirtual(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes);
static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
static JSObject* toThisObject(JSCell*, ExecState*);
diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp
index b3210083d..c84fb5b10 100644
--- a/Source/JavaScriptCore/runtime/JSArray.cpp
+++ b/Source/JavaScriptCore/runtime/JSArray.cpp
@@ -24,6 +24,8 @@
#include "JSArray.h"
#include "ArrayPrototype.h"
+#include "BumpSpace.h"
+#include "BumpSpaceInlineMethods.h"
#include "CachedCall.h"
#include "Error.h"
#include "Executable.h"
@@ -130,7 +132,10 @@ inline void JSArray::checkConsistency(ConsistencyCheckType)
JSArray::JSArray(JSGlobalData& globalData, Structure* structure)
: JSNonFinalObject(globalData, structure)
+ , m_indexBias(0)
, m_storage(0)
+ , m_sparseValueMap(0)
+ , m_subclassData(0)
{
}
@@ -142,13 +147,14 @@ void JSArray::finishCreation(JSGlobalData& globalData, unsigned initialLength)
unsigned initialVectorLength = BASE_VECTOR_LEN;
unsigned initialStorageSize = storageSize(initialVectorLength);
- m_storage = static_cast<ArrayStorage*>(fastMalloc(initialStorageSize));
+ void* newStorage = 0;
+ if (!globalData.heap.tryAllocateStorage(initialStorageSize, &newStorage))
+ CRASH();
+
+ m_storage = static_cast<ArrayStorage*>(newStorage);
m_storage->m_allocBase = m_storage;
m_storage->m_length = initialLength;
- m_indexBias = 0;
m_vectorLength = initialVectorLength;
- m_storage->m_sparseValueMap = 0;
- m_storage->subclassData = 0;
m_storage->m_numValuesInVector = 0;
#if CHECK_ARRAY_CONSISTENCY
m_storage->m_inCompactInitialization = false;
@@ -159,8 +165,6 @@ void JSArray::finishCreation(JSGlobalData& globalData, unsigned initialLength)
vector[i].clear();
checkConsistency();
-
- Heap::heap(this)->reportExtraMemoryCost(initialStorageSize);
}
JSArray* JSArray::tryFinishCreationUninitialized(JSGlobalData& globalData, unsigned initialLength)
@@ -175,14 +179,16 @@ JSArray* JSArray::tryFinishCreationUninitialized(JSGlobalData& globalData, unsig
unsigned initialVectorLength = max(initialLength, BASE_VECTOR_LEN);
unsigned initialStorageSize = storageSize(initialVectorLength);
- m_storage = static_cast<ArrayStorage*>(fastMalloc(initialStorageSize));
+ void* newStorage = 0;
+ if (!globalData.heap.tryAllocateStorage(initialStorageSize, &newStorage))
+ CRASH();
+
+ m_storage = static_cast<ArrayStorage*>(newStorage);
m_storage->m_allocBase = m_storage;
m_storage->m_length = 0;
- m_indexBias = 0;
m_vectorLength = initialVectorLength;
- m_storage->m_sparseValueMap = 0;
- m_storage->subclassData = 0;
m_storage->m_numValuesInVector = initialLength;
+
#if CHECK_ARRAY_CONSISTENCY
m_storage->m_inCompactInitialization = true;
#endif
@@ -191,26 +197,15 @@ JSArray* JSArray::tryFinishCreationUninitialized(JSGlobalData& globalData, unsig
for (size_t i = initialLength; i < initialVectorLength; ++i)
vector[i].clear();
- Heap::heap(this)->reportExtraMemoryCost(initialStorageSize);
return this;
}
-JSArray::~JSArray()
-{
- ASSERT(jsCast<JSArray*>(this));
-
- // If we are unable to allocate memory for m_storage then this may be null.
- if (!m_storage)
- return;
-
- checkConsistency(DestructorConsistencyCheck);
- delete m_storage->m_sparseValueMap;
- fastFree(m_storage->m_allocBase);
-}
-
-void JSArray::destroy(JSCell* cell)
+// This function can be called multiple times on the same object.
+void JSArray::finalize(JSCell* cell)
{
- jsCast<JSArray*>(cell)->JSArray::~JSArray();
+ JSArray* thisObject = jsCast<JSArray*>(cell);
+ thisObject->checkConsistency(DestructorConsistencyCheck);
+ thisObject->deallocateSparseMap();
}
inline std::pair<SparseArrayValueMap::iterator, bool> SparseArrayValueMap::add(JSArray* array, unsigned i)
@@ -229,7 +224,7 @@ inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i
{
SparseArrayEntry& entry = add(array, i).first->second;
- if (!(entry.attributes & (Getter | Setter))) {
+ if (!(entry.attributes & Accessor)) {
if (entry.attributes & ReadOnly) {
// FIXME: should throw if being called from strict mode.
// throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
@@ -310,13 +305,27 @@ inline void SparseArrayValueMap::visitChildren(SlotVisitor& visitor)
visitor.append(&it->second);
}
-void JSArray::enterSparseMode(JSGlobalData& globalData)
+void JSArray::allocateSparseMap(JSGlobalData& globalData)
+{
+ m_sparseValueMap = new SparseArrayValueMap;
+ globalData.heap.addFinalizer(this, finalize);
+}
+
+void JSArray::deallocateSparseMap()
+{
+ delete m_sparseValueMap;
+ m_sparseValueMap = 0;
+}
+
+void JSArray::enterDictionaryMode(JSGlobalData& globalData)
{
ArrayStorage* storage = m_storage;
- SparseArrayValueMap* map = storage->m_sparseValueMap;
+ SparseArrayValueMap* map = m_sparseValueMap;
- if (!map)
- map = storage->m_sparseValueMap = new SparseArrayValueMap;
+ if (!map) {
+ allocateSparseMap(globalData);
+ map = m_sparseValueMap;
+ }
if (map->sparseMode())
return;
@@ -332,10 +341,13 @@ void JSArray::enterSparseMode(JSGlobalData& globalData)
map->add(this, i).first->second.set(globalData, this, value);
}
- ArrayStorage* newStorage = static_cast<ArrayStorage*>(fastMalloc(storageSize(0)));
+ void* newRawStorage = 0;
+ if (!globalData.heap.tryAllocateStorage(storageSize(0), &newRawStorage))
+ CRASH();
+
+ ArrayStorage* newStorage = static_cast<ArrayStorage*>(newRawStorage);
memcpy(newStorage, m_storage, storageSize(0));
newStorage->m_allocBase = newStorage;
- fastFree(m_storage);
m_storage = newStorage;
m_indexBias = 0;
m_vectorLength = 0;
@@ -348,25 +360,21 @@ void JSArray::putDescriptor(ExecState* exec, SparseArrayEntry* entryInMap, Prope
entryInMap->set(exec->globalData(), this, descriptor.value());
else if (oldDescriptor.isAccessorDescriptor())
entryInMap->set(exec->globalData(), this, jsUndefined());
- entryInMap->attributes = descriptor.attributesOverridingCurrent(oldDescriptor) & ~(Getter | Setter);
+ entryInMap->attributes = descriptor.attributesOverridingCurrent(oldDescriptor) & ~Accessor;
return;
}
if (descriptor.isAccessorDescriptor()) {
JSObject* getter = 0;
- if (descriptor.getter() && descriptor.getter().isObject())
- getter = asObject(descriptor.getter());
- if (!getter && oldDescriptor.isAccessorDescriptor()) {
- if (oldDescriptor.getter() && oldDescriptor.getter().isObject())
- getter = asObject(oldDescriptor.getter());
- }
+ if (descriptor.getterPresent())
+ getter = descriptor.getterObject();
+ else if (oldDescriptor.isAccessorDescriptor())
+ getter = oldDescriptor.getterObject();
JSObject* setter = 0;
- if (descriptor.setter() && descriptor.setter().isObject())
- setter = asObject(descriptor.setter());
- if (!setter && oldDescriptor.isAccessorDescriptor()) {
- if (oldDescriptor.setter() && oldDescriptor.setter().isObject())
- setter = asObject(oldDescriptor.setter());
- }
+ if (descriptor.setterPresent())
+ setter = descriptor.setterObject();
+ else if (oldDescriptor.isAccessorDescriptor())
+ setter = oldDescriptor.setterObject();
GetterSetter* accessor = GetterSetter::create(exec);
if (getter)
@@ -406,10 +414,10 @@ bool JSArray::defineOwnNumericProperty(ExecState* exec, unsigned index, Property
return true;
}
- enterSparseMode(exec->globalData());
+ enterDictionaryMode(exec->globalData());
}
- SparseArrayValueMap* map = m_storage->m_sparseValueMap;
+ SparseArrayValueMap* map = m_sparseValueMap;
ASSERT(map);
// 1. Let current be the result of calling the [[GetOwnProperty]] internal method of O with property name P.
@@ -491,6 +499,7 @@ bool JSArray::defineOwnNumericProperty(ExecState* exec, unsigned index, Property
}
// 10.b. else, the [[Configurable]] field of current is true, so any change is acceptable.
} else {
+ ASSERT(current.isAccessorDescriptor() && current.getterPresent() && current.setterPresent());
// 11. Else, IsAccessorDescriptor(current) and IsAccessorDescriptor(Desc) are both true so, if the [[Configurable]] field of current is false, then
if (!current.configurable()) {
// 11.i. Reject, if the [[Set]] field of Desc is present and SameValue(Desc.[[Set]], current.[[Set]]) is false.
@@ -515,9 +524,9 @@ void JSArray::setLengthWritable(ExecState* exec, bool writable)
if (!isLengthWritable() || writable)
return;
- enterSparseMode(exec->globalData());
+ enterDictionaryMode(exec->globalData());
- SparseArrayValueMap* map = m_storage->m_sparseValueMap;
+ SparseArrayValueMap* map = m_sparseValueMap;
ASSERT(map);
map->setLengthIsReadOnly();
}
@@ -531,10 +540,10 @@ bool JSArray::defineOwnProperty(JSObject* object, ExecState* exec, const Identif
if (propertyName == exec->propertyNames().length) {
// All paths through length definition call the default [[DefineOwnProperty]], hence:
// from ES5.1 8.12.9 7.a.
- if (descriptor.configurable())
+ if (descriptor.configurablePresent() && descriptor.configurable())
return reject(exec, throwException, "Attempting to change configurable attribute of unconfigurable property.");
// from ES5.1 8.12.9 7.b.
- if (descriptor.enumerable())
+ if (descriptor.enumerablePresent() && descriptor.enumerable())
return reject(exec, throwException, "Attempting to change enumerable attribute of unconfigurable property.");
// a. If the [[Value]] field of Desc is absent, then
@@ -542,11 +551,12 @@ bool JSArray::defineOwnProperty(JSObject* object, ExecState* exec, const Identif
if (descriptor.isAccessorDescriptor())
return reject(exec, throwException, "Attempting to change access mechanism for an unconfigurable property.");
// from ES5.1 8.12.9 10.a.
- if (!array->isLengthWritable() && descriptor.writable())
+ if (!array->isLengthWritable() && descriptor.writablePresent() && descriptor.writable())
return reject(exec, throwException, "Attempting to change writable attribute of unconfigurable property.");
// This descriptor is either just making length read-only, or changing nothing!
if (!descriptor.value()) {
- array->setLengthWritable(exec, descriptor.writable());
+ if (descriptor.writablePresent())
+ array->setLengthWritable(exec, descriptor.writable());
return true;
}
@@ -561,7 +571,8 @@ bool JSArray::defineOwnProperty(JSObject* object, ExecState* exec, const Identif
// Based on SameValue check in 8.12.9, this is always okay.
if (newLen == array->length()) {
- array->setLengthWritable(exec, descriptor.writable());
+ if (descriptor.writablePresent())
+ array->setLengthWritable(exec, descriptor.writable());
return true;
}
@@ -588,13 +599,17 @@ bool JSArray::defineOwnProperty(JSObject* object, ExecState* exec, const Identif
// 2. If newWritable is false, set newLenDesc.[[Writable] to false.
// 3. Call the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", newLenDesc, and false as arguments.
// 4. Reject.
- array->setLengthWritable(exec, descriptor.writable());
+ if (descriptor.writablePresent())
+ array->setLengthWritable(exec, descriptor.writable());
return false;
}
// m. If newWritable is false, then
- // i. Call the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", Property Descriptor{[[Writable]]: false}, and false as arguments. This call will always return true.
- array->setLengthWritable(exec, descriptor.writable());
+ // i. Call the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length",
+ // Property Descriptor{[[Writable]]: false}, and false as arguments. This call will always
+ // return true.
+ if (descriptor.writablePresent())
+ array->setLengthWritable(exec, descriptor.writable());
// n. Return true.
return true;
}
@@ -623,7 +638,7 @@ bool JSArray::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned
{
JSArray* thisObject = jsCast<JSArray*>(cell);
ArrayStorage* storage = thisObject->m_storage;
-
+
if (i >= storage->m_length) {
if (i > MAX_ARRAY_INDEX)
return thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, Identifier::from(exec, i), slot);
@@ -636,7 +651,7 @@ bool JSArray::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned
slot.setValue(value);
return true;
}
- } else if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ } else if (SparseArrayValueMap* map = thisObject->m_sparseValueMap) {
SparseArrayValueMap::iterator it = map->find(i);
if (it != map->notFound()) {
it->second.get(slot);
@@ -684,7 +699,7 @@ bool JSArray::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const
descriptor.setDescriptor(value.get(), 0);
return true;
}
- } else if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ } else if (SparseArrayValueMap* map = thisObject->m_sparseValueMap) {
SparseArrayValueMap::iterator it = map->find(i);
if (it != map->notFound()) {
it->second.get(descriptor);
@@ -765,7 +780,7 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne
ASSERT(i <= MAX_ARRAY_INDEX);
ArrayStorage* storage = m_storage;
- SparseArrayValueMap* map = storage->m_sparseValueMap;
+ SparseArrayValueMap* map = m_sparseValueMap;
// First, handle cases where we don't currently have a sparse map.
if (LIKELY(!map)) {
@@ -774,7 +789,7 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne
storage->m_length = i + 1;
// Check that it is sensible to still be using a vector, and then try to grow the vector.
- if (LIKELY((isDenseEnoughForVector(i, storage->m_numValuesInVector)) && increaseVectorLength(i + 1))) {
+ if (LIKELY((isDenseEnoughForVector(i, storage->m_numValuesInVector)) && increaseVectorLength(globalData, i + 1))) {
// success! - reread m_storage since it has likely been reallocated, and store to the vector.
storage = m_storage;
storage->m_vector[i].set(globalData, this, value);
@@ -782,8 +797,8 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne
return;
}
// We don't want to, or can't use a vector to hold this property - allocate a sparse map & add the value.
- map = new SparseArrayValueMap;
- storage->m_sparseValueMap = map;
+ allocateSparseMap(exec->globalData());
+ map = m_sparseValueMap;
map->put(exec, this, i, value);
return;
}
@@ -803,7 +818,7 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne
// We are currently using a map - check whether we still want to be doing so.
// We will continue to use a sparse map if SparseMode is set, a vector would be too sparse, or if allocation fails.
unsigned numValuesInArray = storage->m_numValuesInVector + map->size();
- if (map->sparseMode() || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(length)) {
+ if (map->sparseMode() || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(exec->globalData(), length)) {
map->put(exec, this, i, value);
return;
}
@@ -817,8 +832,7 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne
SparseArrayValueMap::const_iterator end = map->end();
for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it)
vector[it->first].set(globalData, this, it->second.getNonSparseMode());
- delete map;
- storage->m_sparseValueMap = 0;
+ deallocateSparseMap();
// Store the new property into the vector.
WriteBarrier<Unknown>& valueSlot = vector[i];
@@ -857,7 +871,7 @@ bool JSArray::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i)
valueSlot.clear();
--storage->m_numValuesInVector;
}
- } else if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ } else if (SparseArrayValueMap* map = thisObject->m_sparseValueMap) {
SparseArrayValueMap::iterator it = map->find(i);
if (it != map->notFound()) {
if (it->second.attributes & DontDelete)
@@ -892,7 +906,7 @@ void JSArray::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNam
propertyNames.add(Identifier::from(exec, i));
}
- if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ if (SparseArrayValueMap* map = thisObject->m_sparseValueMap) {
Vector<unsigned> keys;
keys.reserveCapacity(map->size());
@@ -940,7 +954,7 @@ ALWAYS_INLINE unsigned JSArray::getNewVectorLength(unsigned desiredLength)
return min(increasedLength, MAX_STORAGE_VECTOR_LENGTH);
}
-bool JSArray::increaseVectorLength(unsigned newLength)
+bool JSArray::increaseVectorLength(JSGlobalData& globalData, unsigned newLength)
{
// This function leaves the array in an internally inconsistent state, because it does not move any values from sparse value map
// to the vector. Callers have to account for that, because they can do it more efficiently.
@@ -952,15 +966,16 @@ bool JSArray::increaseVectorLength(unsigned newLength)
unsigned vectorLength = m_vectorLength;
ASSERT(newLength > vectorLength);
unsigned newVectorLength = getNewVectorLength(newLength);
- void* baseStorage = storage->m_allocBase;
// Fast case - there is no precapacity. In these cases a realloc makes sense.
if (LIKELY(!m_indexBias)) {
- if (!tryFastRealloc(baseStorage, storageSize(newVectorLength)).getValue(baseStorage))
+ void* newStorage = storage->m_allocBase;
+ if (!globalData.heap.tryReallocateStorage(&newStorage, storageSize(vectorLength), storageSize(newVectorLength)))
return false;
- storage = m_storage = reinterpret_cast_ptr<ArrayStorage*>(baseStorage);
- m_storage->m_allocBase = baseStorage;
+ storage = m_storage = reinterpret_cast_ptr<ArrayStorage*>(static_cast<char*>(newStorage));
+ m_storage->m_allocBase = newStorage;
+ ASSERT(m_storage->m_allocBase);
WriteBarrier<Unknown>* vector = storage->m_vector;
for (unsigned i = vectorLength; i < newVectorLength; ++i)
@@ -968,7 +983,6 @@ bool JSArray::increaseVectorLength(unsigned newLength)
m_vectorLength = newVectorLength;
- Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
return true;
}
@@ -976,15 +990,11 @@ bool JSArray::increaseVectorLength(unsigned newLength)
unsigned newIndexBias = min(m_indexBias >> 1, MAX_STORAGE_VECTOR_LENGTH - newVectorLength);
// Calculate new stoarge capcity, allowing room for the pre-capacity.
unsigned newStorageCapacity = newVectorLength + newIndexBias;
- void* newAllocBase;
- if (!tryFastMalloc(storageSize(newStorageCapacity)).getValue(newAllocBase))
+ void* newAllocBase = 0;
+ if (!globalData.heap.tryAllocateStorage(storageSize(newStorageCapacity), &newAllocBase))
return false;
// The sum of m_vectorLength and m_indexBias will never exceed MAX_STORAGE_VECTOR_LENGTH.
ASSERT(m_vectorLength <= MAX_STORAGE_VECTOR_LENGTH && (MAX_STORAGE_VECTOR_LENGTH - m_vectorLength) >= m_indexBias);
- unsigned currentCapacity = m_vectorLength + m_indexBias;
- // Currently there is no way to report to the heap that the extra capacity is shrinking!
- if (newStorageCapacity > currentCapacity)
- Heap::heap(this)->reportExtraMemoryCost((newStorageCapacity - currentCapacity) * sizeof(WriteBarrier<Unknown>));
m_vectorLength = newVectorLength;
m_indexBias = newIndexBias;
@@ -996,14 +1006,13 @@ bool JSArray::increaseVectorLength(unsigned newLength)
m_storage->m_vector[i].clear();
// Free the old allocation, update m_allocBase.
- fastFree(m_storage->m_allocBase);
m_storage->m_allocBase = newAllocBase;
return true;
}
// This method makes room in the vector, but leaves the new space uncleared.
-bool JSArray::unshiftCountSlowCase(unsigned count)
+bool JSArray::unshiftCountSlowCase(JSGlobalData& globalData, unsigned count)
{
// If not, we should have handled this on the fast path.
ASSERT(count > m_indexBias);
@@ -1034,19 +1043,16 @@ bool JSArray::unshiftCountSlowCase(unsigned count)
// Step 2:
// We're either going to choose to allocate a new ArrayStorage, or we're going to reuse the existing on.
- void* newAllocBase;
+ void* newAllocBase = 0;
unsigned newStorageCapacity;
// If the current storage array is sufficiently large (but not too large!) then just keep using it.
if (currentCapacity > desiredCapacity && isDenseEnoughForVector(currentCapacity, requiredVectorLength)) {
newAllocBase = storage->m_allocBase;
newStorageCapacity = currentCapacity;
} else {
- if (!tryFastMalloc(storageSize(desiredCapacity)).getValue(newAllocBase))
+ if (!globalData.heap.tryAllocateStorage(storageSize(desiredCapacity), &newAllocBase))
return false;
newStorageCapacity = desiredCapacity;
- // Currently there is no way to report to the heap that the extra capacity is shrinking!
- if (desiredCapacity > currentCapacity)
- Heap::heap(this)->reportExtraMemoryCost((desiredCapacity - currentCapacity) * sizeof(WriteBarrier<Unknown>));
}
// Step 3:
@@ -1079,7 +1085,6 @@ bool JSArray::unshiftCountSlowCase(unsigned count)
// Are we copying into a new allocation?
if (newAllocBase != m_storage->m_allocBase) {
// Free the old allocation, update m_allocBase.
- fastFree(m_storage->m_allocBase);
m_storage->m_allocBase = newAllocBase;
// We need to clear any entries in the vector beyond length. We only need to
@@ -1101,9 +1106,9 @@ bool JSArray::setLength(ExecState* exec, unsigned newLength, bool throwException
unsigned length = storage->m_length;
// If the length is read only then we enter sparse mode, so should enter the following 'if'.
- ASSERT(isLengthWritable() || storage->m_sparseValueMap);
+ ASSERT(isLengthWritable() || m_sparseValueMap);
- if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ if (SparseArrayValueMap* map = m_sparseValueMap) {
// Fail if the length is not writable.
if (map->lengthIsReadOnly())
return reject(exec, throwException, StrictModeReadonlyPropertyWriteError);
@@ -1138,10 +1143,8 @@ bool JSArray::setLength(ExecState* exec, unsigned newLength, bool throwException
} else {
for (unsigned i = 0; i < keys.size(); ++i)
map->remove(keys[i]);
- if (map->isEmpty()) {
- delete map;
- storage->m_sparseValueMap = 0;
- }
+ if (map->isEmpty())
+ deallocateSparseMap();
}
}
}
@@ -1190,7 +1193,7 @@ JSValue JSArray::pop(ExecState* exec)
result = jsUndefined();
} else {
result = jsUndefined();
- if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ if (SparseArrayValueMap* map = m_sparseValueMap) {
SparseArrayValueMap::iterator it = map->find(length);
if (it != map->notFound()) {
unsigned attributes = it->second.attributes;
@@ -1206,10 +1209,8 @@ JSValue JSArray::pop(ExecState* exec)
}
map->remove(it);
- if (map->isEmpty() && !map->sparseMode()) {
- delete map;
- storage->m_sparseValueMap = 0;
- }
+ if (map->isEmpty() && !map->sparseMode())
+ deallocateSparseMap();
}
}
}
@@ -1331,7 +1332,7 @@ void JSArray::unshiftCount(ExecState* exec, unsigned count)
memmove(newBaseStorage, storage, storageSize(0));
m_storage = reinterpret_cast_ptr<ArrayStorage*>(newBaseStorage);
m_vectorLength += count;
- } else if (!unshiftCountSlowCase(count)) {
+ } else if (!unshiftCountSlowCase(exec->globalData(), count)) {
throwOutOfMemoryError(exec);
return;
}
@@ -1349,13 +1350,21 @@ void JSArray::visitChildren(JSCell* cell, SlotVisitor& visitor)
ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
JSNonFinalObject::visitChildren(thisObject, visitor);
-
- ArrayStorage* storage = thisObject->m_storage;
- unsigned usedVectorLength = std::min(storage->m_length, thisObject->m_vectorLength);
- visitor.appendValues(storage->m_vector, usedVectorLength);
+ if (thisObject->m_storage) {
+ ArrayStorage* storage = thisObject->m_storage;
+ void* baseStorage = storage->m_allocBase;
+
+ visitor.copyAndAppend(reinterpret_cast<void**>(&baseStorage), storageSize(thisObject->m_vectorLength + thisObject->m_indexBias), storage->m_vector->slot(), thisObject->m_vectorLength);
+
+ if (baseStorage != thisObject->m_storage->m_allocBase) {
+ thisObject->m_storage = reinterpret_cast<ArrayStorage*>(static_cast<char*>(baseStorage) + sizeof(JSValue) * thisObject->m_indexBias);
+ thisObject->m_storage->m_allocBase = baseStorage;
+ ASSERT(thisObject->m_storage->m_allocBase);
+ }
+ }
- if (SparseArrayValueMap* map = storage->m_sparseValueMap)
+ if (SparseArrayValueMap* map = thisObject->m_sparseValueMap)
map->visitChildren(visitor);
}
@@ -1379,8 +1388,8 @@ void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType cal
ArrayStorage* storage = m_storage;
- unsigned lengthNotIncludingUndefined = compactForSorting();
- if (storage->m_sparseValueMap) {
+ unsigned lengthNotIncludingUndefined = compactForSorting(exec->globalData());
+ if (m_sparseValueMap) {
throwOutOfMemoryError(exec);
return;
}
@@ -1412,10 +1421,8 @@ void JSArray::sort(ExecState* exec)
{
ASSERT(!inSparseMode());
- ArrayStorage* storage = m_storage;
-
- unsigned lengthNotIncludingUndefined = compactForSorting();
- if (storage->m_sparseValueMap) {
+ unsigned lengthNotIncludingUndefined = compactForSorting(exec->globalData());
+ if (m_sparseValueMap) {
throwOutOfMemoryError(exec);
return;
}
@@ -1437,7 +1444,7 @@ void JSArray::sort(ExecState* exec)
Heap::heap(this)->pushTempSortVector(&values);
for (size_t i = 0; i < lengthNotIncludingUndefined; i++) {
- JSValue value = storage->m_vector[i].get();
+ JSValue value = m_storage->m_vector[i].get();
ASSERT(!value.isUndefined());
values[i].first = value;
}
@@ -1446,7 +1453,7 @@ void JSArray::sort(ExecState* exec)
// a toString call raises an exception.
for (size_t i = 0; i < lengthNotIncludingUndefined; i++)
- values[i].second = values[i].first.toString(exec);
+ values[i].second = values[i].first.toString(exec)->value(exec);
if (exec->hadException()) {
Heap::heap(this)->popTempSortVector(&values);
@@ -1467,13 +1474,13 @@ void JSArray::sort(ExecState* exec)
// If the toString function changed the length of the array or vector storage,
// increase the length to handle the orignal number of actual values.
if (m_vectorLength < lengthNotIncludingUndefined)
- increaseVectorLength(lengthNotIncludingUndefined);
- if (storage->m_length < lengthNotIncludingUndefined)
- storage->m_length = lengthNotIncludingUndefined;
+ increaseVectorLength(exec->globalData(), lengthNotIncludingUndefined);
+ if (m_storage->m_length < lengthNotIncludingUndefined)
+ m_storage->m_length = lengthNotIncludingUndefined;
JSGlobalData& globalData = exec->globalData();
for (size_t i = 0; i < lengthNotIncludingUndefined; i++)
- storage->m_vector[i].set(globalData, this, values[i].first);
+ m_storage->m_vector[i].set(globalData, this, values[i].first);
Heap::heap(this)->popTempSortVector(&values);
@@ -1563,18 +1570,16 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
checkConsistency();
- ArrayStorage* storage = m_storage;
-
// FIXME: This ignores exceptions raised in the compare function or in toNumber.
// The maximum tree depth is compiled in - but the caller is clearly up to no good
// if a larger array is passed.
- ASSERT(storage->m_length <= static_cast<unsigned>(std::numeric_limits<int>::max()));
- if (storage->m_length > static_cast<unsigned>(std::numeric_limits<int>::max()))
+ ASSERT(m_storage->m_length <= static_cast<unsigned>(std::numeric_limits<int>::max()));
+ if (m_storage->m_length > static_cast<unsigned>(std::numeric_limits<int>::max()))
return;
- unsigned usedVectorLength = min(storage->m_length, m_vectorLength);
- unsigned nodeCount = usedVectorLength + (storage->m_sparseValueMap ? storage->m_sparseValueMap->size() : 0);
+ unsigned usedVectorLength = min(m_storage->m_length, m_vectorLength);
+ unsigned nodeCount = usedVectorLength + (m_sparseValueMap ? m_sparseValueMap->size() : 0);
if (!nodeCount)
return;
@@ -1602,14 +1607,14 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
// Iterate over the array, ignoring missing values, counting undefined ones, and inserting all other ones into the tree.
for (; numDefined < usedVectorLength; ++numDefined) {
- JSValue v = storage->m_vector[numDefined].get();
+ JSValue v = m_storage->m_vector[numDefined].get();
if (!v || v.isUndefined())
break;
tree.abstractor().m_nodes[numDefined].value = v;
tree.insert(numDefined);
}
for (unsigned i = numDefined; i < usedVectorLength; ++i) {
- JSValue v = storage->m_vector[i].get();
+ JSValue v = m_storage->m_vector[i].get();
if (v) {
if (v.isUndefined())
++numUndefined;
@@ -1623,17 +1628,15 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
unsigned newUsedVectorLength = numDefined + numUndefined;
- if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ if (SparseArrayValueMap* map = m_sparseValueMap) {
newUsedVectorLength += map->size();
if (newUsedVectorLength > m_vectorLength) {
// Check that it is possible to allocate an array large enough to hold all the entries.
- if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength)) {
+ if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(exec->globalData(), newUsedVectorLength)) {
throwOutOfMemoryError(exec);
return;
}
}
-
- storage = m_storage;
SparseArrayValueMap::const_iterator end = map->end();
for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) {
@@ -1642,8 +1645,7 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
++numDefined;
}
- delete map;
- storage->m_sparseValueMap = 0;
+ deallocateSparseMap();
}
ASSERT(tree.abstractor().m_nodes.size() >= numDefined);
@@ -1656,19 +1658,19 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
iter.start_iter_least(tree);
JSGlobalData& globalData = exec->globalData();
for (unsigned i = 0; i < numDefined; ++i) {
- storage->m_vector[i].set(globalData, this, tree.abstractor().m_nodes[*iter].value);
+ m_storage->m_vector[i].set(globalData, this, tree.abstractor().m_nodes[*iter].value);
++iter;
}
// Put undefined values back in.
for (unsigned i = numDefined; i < newUsedVectorLength; ++i)
- storage->m_vector[i].setUndefined();
+ m_storage->m_vector[i].setUndefined();
// Ensure that unused values in the vector are zeroed out.
for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
- storage->m_vector[i].clear();
+ m_storage->m_vector[i].clear();
- storage->m_numValuesInVector = newUsedVectorLength;
+ m_storage->m_numValuesInVector = newUsedVectorLength;
checkConsistency(SortConsistencyCheck);
}
@@ -1709,7 +1711,7 @@ void JSArray::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t le
callFrame->setArgument(i, get(exec, i));
}
-unsigned JSArray::compactForSorting()
+unsigned JSArray::compactForSorting(JSGlobalData& globalData)
{
ASSERT(!inSparseMode());
@@ -1740,12 +1742,12 @@ unsigned JSArray::compactForSorting()
unsigned newUsedVectorLength = numDefined + numUndefined;
- if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ if (SparseArrayValueMap* map = m_sparseValueMap) {
newUsedVectorLength += map->size();
if (newUsedVectorLength > m_vectorLength) {
// Check that it is possible to allocate an array large enough to hold all the entries - if not,
// exception is thrown by caller.
- if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength))
+ if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(globalData, newUsedVectorLength))
return 0;
storage = m_storage;
@@ -1755,8 +1757,7 @@ unsigned JSArray::compactForSorting()
for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it)
storage->m_vector[numDefined++].setWithoutWriteBarrier(it->second.getNonSparseMode());
- delete map;
- storage->m_sparseValueMap = 0;
+ deallocateSparseMap();
}
for (unsigned i = numDefined; i < newUsedVectorLength; ++i)
@@ -1773,12 +1774,12 @@ unsigned JSArray::compactForSorting()
void* JSArray::subclassData() const
{
- return m_storage->subclassData;
+ return m_subclassData;
}
void JSArray::setSubclassData(void* d)
{
- m_storage->subclassData = d;
+ m_subclassData = d;
}
#if CHECK_ARRAY_CONSISTENCY
@@ -1791,7 +1792,7 @@ void JSArray::checkConsistency(ConsistencyCheckType type)
ASSERT(storage);
if (type == SortConsistencyCheck)
- ASSERT(!storage->m_sparseValueMap);
+ ASSERT(!m_sparseValueMap);
unsigned numValuesInVector = 0;
for (unsigned i = 0; i < m_vectorLength; ++i) {
@@ -1808,9 +1809,9 @@ void JSArray::checkConsistency(ConsistencyCheckType type)
ASSERT(numValuesInVector == storage->m_numValuesInVector);
ASSERT(numValuesInVector <= storage->m_length);
- if (storage->m_sparseValueMap) {
- SparseArrayValueMap::iterator end = storage->m_sparseValueMap->end();
- for (SparseArrayValueMap::iterator it = storage->m_sparseValueMap->begin(); it != end; ++it) {
+ if (m_sparseValueMap) {
+ SparseArrayValueMap::iterator end = m_sparseValueMap->end();
+ for (SparseArrayValueMap::iterator it = m_sparseValueMap->begin(); it != end; ++it) {
unsigned index = it->first;
ASSERT(index < storage->m_length);
ASSERT(index >= storage->m_vectorLength);
diff --git a/Source/JavaScriptCore/runtime/JSArray.h b/Source/JavaScriptCore/runtime/JSArray.h
index 871cfc882..a3354c602 100644
--- a/Source/JavaScriptCore/runtime/JSArray.h
+++ b/Source/JavaScriptCore/runtime/JSArray.h
@@ -114,8 +114,6 @@ namespace JSC {
struct ArrayStorage {
unsigned m_length; // The "length" property on the array
unsigned m_numValuesInVector;
- SparseArrayValueMap* m_sparseValueMap;
- void* subclassData; // A JSArray subclass can use this to fill the vector lazily.
void* m_allocBase; // Pointer to base address returned by malloc(). Keeping this pointer does eliminate false positives from the leak detector.
#if CHECK_ARRAY_CONSISTENCY
bool m_inCompactInitialization;
@@ -127,16 +125,15 @@ namespace JSC {
friend class Walker;
protected:
- explicit JSArray(JSGlobalData&, Structure*);
+ JS_EXPORT_PRIVATE explicit JSArray(JSGlobalData&, Structure*);
- void finishCreation(JSGlobalData&, unsigned initialLength = 0);
- JSArray* tryFinishCreationUninitialized(JSGlobalData&, unsigned initialLength);
+ JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, unsigned initialLength = 0);
+ JS_EXPORT_PRIVATE JSArray* tryFinishCreationUninitialized(JSGlobalData&, unsigned initialLength);
public:
typedef JSNonFinalObject Base;
- ~JSArray();
- static void destroy(JSCell*);
+ static void finalize(JSCell*);
static JSArray* create(JSGlobalData& globalData, Structure* structure, unsigned initialLength = 0)
{
@@ -156,10 +153,10 @@ namespace JSC {
return array->tryFinishCreationUninitialized(globalData, initialLength);
}
- static bool defineOwnProperty(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&, bool throwException);
+ JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&, bool throwException);
static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
- static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
+ JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue);
@@ -232,7 +229,7 @@ namespace JSC {
bool inSparseMode()
{
- SparseArrayValueMap* map = m_storage->m_sparseValueMap;
+ SparseArrayValueMap* map = m_sparseValueMap;
return map && map->sparseMode();
}
@@ -254,7 +251,7 @@ namespace JSC {
return OBJECT_OFFSETOF(JSArray, m_vectorLength);
}
- static void visitChildren(JSCell*, SlotVisitor&);
+ JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
protected:
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
@@ -264,29 +261,31 @@ namespace JSC {
static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
- void* subclassData() const;
- void setSubclassData(void*);
+ JS_EXPORT_PRIVATE void* subclassData() const;
+ JS_EXPORT_PRIVATE void setSubclassData(void*);
private:
bool isLengthWritable()
{
- SparseArrayValueMap* map = m_storage->m_sparseValueMap;
+ SparseArrayValueMap* map = m_sparseValueMap;
return !map || !map->lengthIsReadOnly();
}
void setLengthWritable(ExecState*, bool writable);
void putDescriptor(ExecState*, SparseArrayEntry*, PropertyDescriptor&, PropertyDescriptor& old);
bool defineOwnNumericProperty(ExecState*, unsigned, PropertyDescriptor&, bool throwException);
- void enterSparseMode(JSGlobalData&);
+ void enterDictionaryMode(JSGlobalData&);
+ void allocateSparseMap(JSGlobalData&);
+ void deallocateSparseMap();
bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&);
void putByIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue);
unsigned getNewVectorLength(unsigned desiredLength);
- bool increaseVectorLength(unsigned newLength);
- bool unshiftCountSlowCase(unsigned count);
+ bool increaseVectorLength(JSGlobalData&, unsigned newLength);
+ bool unshiftCountSlowCase(JSGlobalData&, unsigned count);
- unsigned compactForSorting();
+ unsigned compactForSorting(JSGlobalData&);
enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck };
void checkConsistency(ConsistencyCheckType = NormalConsistencyCheck);
@@ -294,6 +293,10 @@ namespace JSC {
unsigned m_vectorLength; // The valid length of m_vector
unsigned m_indexBias; // The number of JSValue sized blocks before ArrayStorage.
ArrayStorage *m_storage;
+
+ // FIXME: Maybe SparseArrayValueMap should be put into its own JSCell?
+ SparseArrayValueMap* m_sparseValueMap;
+ void* m_subclassData; // A JSArray subclass can use this to fill the vector lazily.
};
JSArray* asArray(JSValue);
diff --git a/Source/JavaScriptCore/runtime/JSBoundFunction.cpp b/Source/JavaScriptCore/runtime/JSBoundFunction.cpp
index 549b6034f..88260ea27 100644
--- a/Source/JavaScriptCore/runtime/JSBoundFunction.cpp
+++ b/Source/JavaScriptCore/runtime/JSBoundFunction.cpp
@@ -111,8 +111,8 @@ void JSBoundFunction::finishCreation(ExecState* exec, NativeExecutable* executab
Base::finishCreation(exec, executable, length, name);
ASSERT(inherits(&s_info));
- initializeGetterSetterProperty(exec, exec->propertyNames().arguments, globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter);
- initializeGetterSetterProperty(exec, exec->propertyNames().caller, globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter);
+ initializeGetterSetterProperty(exec, exec->propertyNames().arguments, globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
+ initializeGetterSetterProperty(exec, exec->propertyNames().caller, globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
}
void JSBoundFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
diff --git a/Source/JavaScriptCore/runtime/JSBoundFunction.h b/Source/JavaScriptCore/runtime/JSBoundFunction.h
index c60d7db01..e54d45883 100644
--- a/Source/JavaScriptCore/runtime/JSBoundFunction.h
+++ b/Source/JavaScriptCore/runtime/JSBoundFunction.h
@@ -51,7 +51,7 @@ public:
return Structure::create(globalData, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), &s_info);
}
- static JS_EXPORTDATA const ClassInfo s_info;
+ static const ClassInfo s_info;
protected:
const static unsigned StructureFlags = OverridesHasInstance | OverridesVisitChildren | Base::StructureFlags;
diff --git a/Source/JavaScriptCore/runtime/JSByteArray.h b/Source/JavaScriptCore/runtime/JSByteArray.h
index 754774d3e..d1f4ad630 100644
--- a/Source/JavaScriptCore/runtime/JSByteArray.h
+++ b/Source/JavaScriptCore/runtime/JSByteArray.h
@@ -76,7 +76,7 @@ namespace JSC {
}
private:
- JSByteArray(ExecState*, Structure*, ByteArray* storage);
+ JS_EXPORT_PRIVATE JSByteArray(ExecState*, Structure*, ByteArray* storage);
public:
static JSByteArray* create(ExecState* exec, Structure* structure, ByteArray* storage)
@@ -86,15 +86,15 @@ namespace JSC {
return array;
}
- static Structure* createStructure(JSGlobalData&, JSGlobalObject*, JSValue prototype, const JSC::ClassInfo* = &s_info);
+ JS_EXPORT_PRIVATE static Structure* createStructure(JSGlobalData&, JSGlobalObject*, JSValue prototype, const JSC::ClassInfo* = &s_info);
- static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);
- static bool getOwnPropertySlotByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);
- static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
- static void put(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);
- static void putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue);
+ JS_EXPORT_PRIVATE static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);
+ JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);
+ JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
+ JS_EXPORT_PRIVATE static void put(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);
+ JS_EXPORT_PRIVATE static void putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue);
- static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, EnumerationMode);
+ JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, EnumerationMode);
static JS_EXPORTDATA const ClassInfo s_info;
@@ -103,7 +103,7 @@ namespace JSC {
WTF::ByteArray* storage() const { return m_storage.get(); }
~JSByteArray();
- static void destroy(JSCell*);
+ JS_EXPORT_PRIVATE static void destroy(JSCell*);
static size_t offsetOfStorage() { return OBJECT_OFFSETOF(JSByteArray, m_storage); }
diff --git a/Source/JavaScriptCore/runtime/JSCell.cpp b/Source/JavaScriptCore/runtime/JSCell.cpp
index 065fd13ea..9dcd6364b 100644
--- a/Source/JavaScriptCore/runtime/JSCell.cpp
+++ b/Source/JavaScriptCore/runtime/JSCell.cpp
@@ -145,13 +145,6 @@ double JSCell::toNumber(ExecState* exec) const
return static_cast<const JSObject*>(this)->toNumber(exec);
}
-UString JSCell::toString(ExecState* exec) const
-{
- if (isString())
- return static_cast<const JSString*>(this)->toString(exec);
- return static_cast<const JSObject*>(this)->toString(exec);
-}
-
JSObject* JSCell::toObject(ExecState* exec, JSGlobalObject* globalObject) const
{
if (isString())
@@ -203,7 +196,7 @@ bool JSCell::hasInstance(JSObject*, ExecState*, JSValue, JSValue)
return false;
}
-void JSCell::putWithAttributes(JSObject*, ExecState*, const Identifier&, JSValue, unsigned)
+void JSCell::putDirectVirtual(JSObject*, ExecState*, const Identifier&, JSValue, unsigned)
{
ASSERT_NOT_REACHED();
}
diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h
index 47e336a86..a36bb7d58 100644
--- a/Source/JavaScriptCore/runtime/JSCell.h
+++ b/Source/JavaScriptCore/runtime/JSCell.h
@@ -51,6 +51,7 @@ namespace JSC {
TypedArrayInt16,
TypedArrayInt32,
TypedArrayUint8,
+ TypedArrayUint8Clamped,
TypedArrayUint16,
TypedArrayUint32,
TypedArrayFloat32,
@@ -67,7 +68,7 @@ namespace JSC {
protected:
JSCell(JSGlobalData&, Structure*);
- static void destroy(JSCell*);
+ JS_EXPORT_PRIVATE static void destroy(JSCell*);
public:
// Querying the type.
@@ -82,21 +83,20 @@ namespace JSC {
void clearStructure() { m_structure.clear(); }
// Extracting the value.
- bool getString(ExecState* exec, UString&) const;
- UString getString(ExecState* exec) const; // null string if not a string
- JSObject* getObject(); // NULL if not an object
+ JS_EXPORT_PRIVATE bool getString(ExecState* exec, UString&) const;
+ JS_EXPORT_PRIVATE UString getString(ExecState* exec) const; // null string if not a string
+ JS_EXPORT_PRIVATE JSObject* getObject(); // NULL if not an object
const JSObject* getObject() const; // NULL if not an object
- static CallType getCallData(JSCell*, CallData&);
- static ConstructType getConstructData(JSCell*, ConstructData&);
+ JS_EXPORT_PRIVATE static CallType getCallData(JSCell*, CallData&);
+ JS_EXPORT_PRIVATE static ConstructType getConstructData(JSCell*, ConstructData&);
// Basic conversions.
- JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ JS_EXPORT_PRIVATE JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
bool toBoolean(ExecState*) const;
- double toNumber(ExecState*) const;
- UString toString(ExecState*) const;
- JSObject* toObject(ExecState*, JSGlobalObject*) const;
+ JS_EXPORT_PRIVATE double toNumber(ExecState*) const;
+ JS_EXPORT_PRIVATE JSObject* toObject(ExecState*, JSGlobalObject*) const;
static void visitChildren(JSCell*, SlotVisitor&);
@@ -159,7 +159,7 @@ namespace JSC {
static NO_RETURN_DUE_TO_ASSERT void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
static UString className(const JSObject*);
static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty);
- static NO_RETURN_DUE_TO_ASSERT void putWithAttributes(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
+ static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
diff --git a/Source/JavaScriptCore/runtime/JSFunction.cpp b/Source/JavaScriptCore/runtime/JSFunction.cpp
index 65470a53f..15718a176 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.cpp
+++ b/Source/JavaScriptCore/runtime/JSFunction.cpp
@@ -136,7 +136,11 @@ const UString JSFunction::calculatedDisplayName(ExecState* exec)
if (!explicitName.isEmpty())
return explicitName;
- return name(exec);
+ const UString actualName = name(exec);
+ if (!actualName.isEmpty() || isHostFunction())
+ return actualName;
+
+ return jsExecutable()->inferredName().ustring();
}
const SourceCode* JSFunction::sourceCode() const
@@ -175,14 +179,14 @@ JSValue JSFunction::argumentsGetter(ExecState* exec, JSValue slotBase, const Ide
{
JSFunction* thisObj = asFunction(slotBase);
ASSERT(!thisObj->isHostFunction());
- return exec->interpreter()->retrieveArguments(exec, thisObj);
+ return exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObj);
}
JSValue JSFunction::callerGetter(ExecState* exec, JSValue slotBase, const Identifier&)
{
JSFunction* thisObj = asFunction(slotBase);
ASSERT(!thisObj->isHostFunction());
- return exec->interpreter()->retrieveCaller(exec, thisObj);
+ return exec->interpreter()->retrieveCallerFromVMCode(exec, thisObj);
}
JSValue JSFunction::lengthGetter(ExecState*, JSValue slotBase, const Identifier&)
@@ -204,8 +208,7 @@ bool JSFunction::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identif
if (!location) {
JSObject* prototype = constructEmptyObject(exec, thisObject->globalObject()->emptyObjectStructure());
prototype->putDirect(exec->globalData(), exec->propertyNames().constructor, thisObject, DontEnum);
- PutPropertySlot slot;
- thisObject->putDirect(exec->globalData(), exec->propertyNames().prototype, prototype, DontDelete | DontEnum, false, slot);
+ thisObject->putDirect(exec->globalData(), exec->propertyNames().prototype, prototype, DontDelete | DontEnum);
location = thisObject->getDirectLocation(exec->globalData(), exec->propertyNames().prototype);
}
@@ -216,7 +219,7 @@ bool JSFunction::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identif
if (thisObject->jsExecutable()->isStrictMode()) {
bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
if (!result) {
- thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter);
+ thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
ASSERT(result);
}
@@ -235,7 +238,7 @@ bool JSFunction::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identif
if (thisObject->jsExecutable()->isStrictMode()) {
bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
if (!result) {
- thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter);
+ thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
ASSERT(result);
}
@@ -264,13 +267,13 @@ bool JSFunction::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, con
if (thisObject->jsExecutable()->isStrictMode()) {
bool result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
if (!result) {
- thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter);
+ thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
ASSERT(result);
}
return result;
}
- descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, thisObject), ReadOnly | DontEnum | DontDelete);
+ descriptor.setDescriptor(exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObject), ReadOnly | DontEnum | DontDelete);
return true;
}
@@ -283,13 +286,13 @@ bool JSFunction::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, con
if (thisObject->jsExecutable()->isStrictMode()) {
bool result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
if (!result) {
- thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter);
+ thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
ASSERT(result);
}
return result;
}
- descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, thisObject), ReadOnly | DontEnum | DontDelete);
+ descriptor.setDescriptor(exec->interpreter()->retrieveCallerFromVMCode(exec, thisObject), ReadOnly | DontEnum | DontDelete);
return true;
}
@@ -358,5 +361,15 @@ ConstructType JSFunction::getConstructData(JSCell* cell, ConstructData& construc
constructData.js.scopeChain = thisObject->scope();
return ConstructTypeJS;
}
+
+
+UString getCalculatedDisplayName(CallFrame* callFrame, JSObject* object)
+{
+ if (JSFunction* function = jsDynamicCast<JSFunction*>(object))
+ return function->calculatedDisplayName(callFrame);
+ if (InternalFunction* function = jsDynamicCast<InternalFunction*>(object))
+ return function->calculatedDisplayName(callFrame);
+ return UString();
+}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSFunction.h b/Source/JavaScriptCore/runtime/JSFunction.h
index 5118f8b10..a12b079d7 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.h
+++ b/Source/JavaScriptCore/runtime/JSFunction.h
@@ -40,8 +40,10 @@ namespace JSC {
class JITCompiler;
}
- EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*);
+ JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*);
+ JS_EXPORT_PRIVATE UString getCalculatedDisplayName(CallFrame*, JSObject*);
+
class JSFunction : public JSNonFinalObject {
friend class JIT;
friend class DFG::SpeculativeJIT;
@@ -51,7 +53,7 @@ namespace JSC {
public:
typedef JSNonFinalObject Base;
- static JSFunction* create(ExecState*, JSGlobalObject*, int length, const Identifier& name, NativeFunction nativeFunction, NativeFunction nativeConstructor = callHostFunctionAsConstructor);
+ JS_EXPORT_PRIVATE static JSFunction* create(ExecState*, JSGlobalObject*, int length, const Identifier& name, NativeFunction nativeFunction, NativeFunction nativeConstructor = callHostFunctionAsConstructor);
static JSFunction* create(ExecState*, JSGlobalObject*, int length, const Identifier& name, NativeExecutable* nativeExecutable);
static JSFunction* create(ExecState* exec, FunctionExecutable* executable, ScopeChainNode* scopeChain)
@@ -64,8 +66,8 @@ namespace JSC {
static void destroy(JSCell*);
- const UString& name(ExecState*);
- const UString displayName(ExecState*);
+ JS_EXPORT_PRIVATE const UString& name(ExecState*);
+ JS_EXPORT_PRIVATE const UString displayName(ExecState*);
const UString calculatedDisplayName(ExecState*);
ScopeChainNode* scope()
@@ -94,7 +96,7 @@ namespace JSC {
inline bool isHostFunction() const;
FunctionExecutable* jsExecutable() const;
- const SourceCode* sourceCode() const;
+ JS_EXPORT_PRIVATE const SourceCode* sourceCode() const;
static JS_EXPORTDATA const ClassInfo s_info;
@@ -123,7 +125,7 @@ namespace JSC {
protected:
const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
- JSFunction(ExecState*, JSGlobalObject*, Structure*);
+ JS_EXPORT_PRIVATE JSFunction(ExecState*, JSGlobalObject*, Structure*);
JSFunction(ExecState*, FunctionExecutable*, ScopeChainNode*);
void finishCreation(ExecState*, NativeExecutable*, int length, const Identifier& name);
@@ -140,7 +142,7 @@ namespace JSC {
static void visitChildren(JSCell*, SlotVisitor&);
private:
- bool isHostFunctionNonInline() const;
+ JS_EXPORT_PRIVATE bool isHostFunctionNonInline() const;
static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&);
static JSValue callerGetter(ExecState*, JSValue, const Identifier&);
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
index dab3f24ba..bbe520a1e 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -101,7 +101,7 @@ extern const HashTable globalObjectTable;
extern const HashTable mathTable;
extern const HashTable numberConstructorTable;
extern const HashTable numberPrototypeTable;
-extern const HashTable objectConstructorTable;
+JS_EXPORTDATA extern const HashTable objectConstructorTable;
extern const HashTable objectPrototypeTable;
extern const HashTable regExpTable;
extern const HashTable regExpConstructorTable;
@@ -162,8 +162,6 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
#endif
{
interpreter = new Interpreter;
- if (globalDataType == Default)
- m_stack = wtfThreadData().stack();
// Need to be careful to keep everything consistent here
IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable);
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h
index a6ad8a747..92817f2a2 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.h
@@ -134,18 +134,18 @@ namespace JSC {
enum GlobalDataType { Default, APIContextGroup, APIShared };
struct ClientData {
- virtual ~ClientData() = 0;
+ JS_EXPORT_PRIVATE virtual ~ClientData() = 0;
};
bool isSharedInstance() { return globalDataType == APIShared; }
bool usingAPI() { return globalDataType != Default; }
static bool sharedInstanceExists();
- static JSGlobalData& sharedInstance();
+ JS_EXPORT_PRIVATE static JSGlobalData& sharedInstance();
- static PassRefPtr<JSGlobalData> create(ThreadStackType, HeapSize = SmallHeap);
- static PassRefPtr<JSGlobalData> createLeaked(ThreadStackType, HeapSize = SmallHeap);
+ JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> create(ThreadStackType, HeapSize = SmallHeap);
+ JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> createLeaked(ThreadStackType, HeapSize = SmallHeap);
static PassRefPtr<JSGlobalData> createContextGroup(ThreadStackType, HeapSize = SmallHeap);
- ~JSGlobalData();
+ JS_EXPORT_PRIVATE ~JSGlobalData();
void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); }
@@ -223,13 +223,6 @@ namespace JSC {
bool canUseJIT() { return m_canUseJIT; }
#endif
- const StackBounds& stack()
- {
- return (globalDataType == Default)
- ? m_stack
- : wtfThreadData().stack();
- }
-
OwnPtr<ParserArena> parserArena;
OwnPtr<Keywords> keywords;
Interpreter* interpreter;
@@ -308,21 +301,21 @@ namespace JSC {
CachedTranscendentalFunction<sin> cachedSin;
- void resetDateCache();
+ JS_EXPORT_PRIVATE void resetDateCache();
- void startSampling();
- void stopSampling();
- void dumpSampleData(ExecState* exec);
+ JS_EXPORT_PRIVATE void startSampling();
+ JS_EXPORT_PRIVATE void stopSampling();
+ JS_EXPORT_PRIVATE void dumpSampleData(ExecState* exec);
void recompileAllJSFunctions();
RegExpCache* regExpCache() { return m_regExpCache; }
#if ENABLE(REGEXP_TRACING)
void addRegExpToTrace(PassRefPtr<RegExp> regExp);
#endif
- void dumpRegExpTrace();
- void clearBuiltinStructures();
+ JS_EXPORT_PRIVATE void dumpRegExpTrace();
+ JS_EXPORT_PRIVATE void clearBuiltinStructures();
bool isCollectorBusy() { return heap.isBusy(); }
- void releaseExecutableMemory();
+ JS_EXPORT_PRIVATE void releaseExecutableMemory();
#if ENABLE(GC_VALIDATION)
bool isInitializingObject() const;
@@ -345,6 +338,7 @@ namespace JSC {
registerTypedArrayFunction(int16, Int16);
registerTypedArrayFunction(int32, Int32);
registerTypedArrayFunction(uint8, Uint8);
+ registerTypedArrayFunction(uint8Clamped, Uint8Clamped);
registerTypedArrayFunction(uint16, Uint16);
registerTypedArrayFunction(uint32, Uint32);
registerTypedArrayFunction(float32, Float32);
@@ -358,7 +352,6 @@ namespace JSC {
#if ENABLE(JIT) && ENABLE(INTERPRETER)
bool m_canUseJIT;
#endif
- StackBounds m_stack;
#if ENABLE(GC_VALIDATION)
bool m_isInitializingObject;
#endif
@@ -366,6 +359,7 @@ namespace JSC {
TypedArrayDescriptor m_int16ArrayDescriptor;
TypedArrayDescriptor m_int32ArrayDescriptor;
TypedArrayDescriptor m_uint8ArrayDescriptor;
+ TypedArrayDescriptor m_uint8ClampedArrayDescriptor;
TypedArrayDescriptor m_uint16ArrayDescriptor;
TypedArrayDescriptor m_uint32ArrayDescriptor;
TypedArrayDescriptor m_float32ArrayDescriptor;
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
index 5ad53c222..f28139d27 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -153,7 +153,7 @@ void JSGlobalObject::put(JSCell* cell, ExecState* exec, const Identifier& proper
JSVariableObject::put(thisObject, exec, propertyName, value, slot);
}
-void JSGlobalObject::putWithAttributes(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
+void JSGlobalObject::putDirectVirtual(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
{
JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object);
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
@@ -167,7 +167,7 @@ void JSGlobalObject::putWithAttributes(JSObject* object, ExecState* exec, const
if (!valueBefore) {
JSValue valueAfter = thisObject->getDirect(exec->globalData(), propertyName);
if (valueAfter)
- JSObject::putWithAttributes(thisObject, exec, propertyName, valueAfter, attributes);
+ JSObject::putDirectVirtual(thisObject, exec, propertyName, valueAfter, attributes);
}
}
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h
index 1caa8b187..70368307d 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h
@@ -192,20 +192,20 @@ namespace JSC {
}
public:
- ~JSGlobalObject();
- static void destroy(JSCell*);
+ JS_EXPORT_PRIVATE ~JSGlobalObject();
+ JS_EXPORT_PRIVATE static void destroy(JSCell*);
- static void visitChildren(JSCell*, SlotVisitor&);
+ JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
- static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
- static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
+ JS_EXPORT_PRIVATE static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+ JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
bool hasOwnPropertyForWrite(ExecState*, const Identifier&);
- static void put(JSCell*, ExecState*, const Identifier&, JSValue, PutPropertySlot&);
+ JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, const Identifier&, JSValue, PutPropertySlot&);
- static void putWithAttributes(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
+ JS_EXPORT_PRIVATE static void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
- static void defineGetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes);
- static void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes);
+ JS_EXPORT_PRIVATE static void defineGetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes);
+ JS_EXPORT_PRIVATE static void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes);
// We use this in the code generator as we perform symbol table
// lookups prior to initializing the properties
@@ -283,7 +283,7 @@ namespace JSC {
ScopeChainNode* globalScopeChain() { return m_globalScopeChain.get(); }
- ExecState* globalExec();
+ JS_EXPORT_PRIVATE ExecState* globalExec();
static bool shouldInterruptScript(const JSGlobalObject*) { return true; }
@@ -332,17 +332,17 @@ namespace JSC {
JSValue value;
unsigned attributes;
};
- void addStaticGlobals(GlobalPropertyInfo*, int count);
+ JS_EXPORT_PRIVATE void addStaticGlobals(GlobalPropertyInfo*, int count);
private:
// FIXME: Fold reset into init.
- void init(JSObject* thisValue);
+ JS_EXPORT_PRIVATE void init(JSObject* thisValue);
void reset(JSValue prototype);
void createThrowTypeError(ExecState*);
void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count);
- static void clearRareData(JSCell*);
+ JS_EXPORT_PRIVATE static void clearRareData(JSCell*);
};
JSGlobalObject* asGlobalObject(JSValue);
@@ -488,7 +488,7 @@ namespace JSC {
class DynamicGlobalObjectScope {
WTF_MAKE_NONCOPYABLE(DynamicGlobalObjectScope);
public:
- DynamicGlobalObjectScope(JSGlobalData&, JSGlobalObject*);
+ JS_EXPORT_PRIVATE DynamicGlobalObjectScope(JSGlobalData&, JSGlobalObject*);
~DynamicGlobalObjectScope()
{
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
index bf6b31ef1..b82ab62ab 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
@@ -51,8 +51,7 @@ namespace JSC {
static JSValue encode(ExecState* exec, const char* doNotEscape)
{
- UString str = exec->argument(0).toString(exec);
- CString cstr = str.utf8(true);
+ CString cstr = exec->argument(0).toString(exec)->value(exec).utf8(true);
if (!cstr.data())
return throwError(exec, createURIError(exec, "String contained an illegal UTF-16 sequence."));
@@ -143,7 +142,7 @@ static JSValue decode(ExecState* exec, const CharType* characters, int length, c
static JSValue decode(ExecState* exec, const char* doNotUnescape, bool strict)
{
JSStringBuilder builder;
- UString str = exec->argument(0).toString(exec);
+ UString str = exec->argument(0).toString(exec)->value(exec);
if (str.is8Bit())
return decode(exec, str.characters8(), str.length(), doNotUnescape, strict);
@@ -513,7 +512,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec)
if (!x.isString())
return JSValue::encode(x);
- UString s = x.toString(exec);
+ UString s = x.toString(exec)->value(exec);
if (s.is8Bit()) {
LiteralParser<LChar> preparser(exec, s.characters8(), s.length(), NonStrictJSON);
@@ -556,7 +555,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec)
}
// If ToString throws, we shouldn't call ToInt32.
- UString s = value.toString(exec);
+ UString s = value.toString(exec)->value(exec);
if (exec->hadException())
return JSValue::encode(jsUndefined());
@@ -565,7 +564,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec)
EncodedJSValue JSC_HOST_CALL globalFuncParseFloat(ExecState* exec)
{
- return JSValue::encode(jsNumber(parseFloat(exec->argument(0).toString(exec))));
+ return JSValue::encode(jsNumber(parseFloat(exec->argument(0).toString(exec)->value(exec))));
}
EncodedJSValue JSC_HOST_CALL globalFuncIsNaN(ExecState* exec)
@@ -623,7 +622,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec)
"*+-./@_";
JSStringBuilder builder;
- UString str = exec->argument(0).toString(exec);
+ UString str = exec->argument(0).toString(exec)->value(exec);
if (str.is8Bit()) {
const LChar* c = str.characters8();
for (unsigned k = 0; k < str.length(); k++, c++) {
@@ -662,7 +661,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec)
EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec)
{
UStringBuilder builder;
- UString str = exec->argument(0).toString(exec);
+ UString str = exec->argument(0).toString(exec)->value(exec);
int k = 0;
int len = str.length();
diff --git a/Source/JavaScriptCore/runtime/JSGlobalThis.h b/Source/JavaScriptCore/runtime/JSGlobalThis.h
index fa5de0491..fa5c2eb34 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalThis.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalThis.h
@@ -63,7 +63,7 @@ protected:
static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
- static void visitChildren(JSCell*, SlotVisitor&);
+ JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
WriteBarrier<JSGlobalObject> m_unwrappedObject;
};
diff --git a/Source/JavaScriptCore/runtime/JSLock.h b/Source/JavaScriptCore/runtime/JSLock.h
index 7b07b4fb3..a0eb96975 100644
--- a/Source/JavaScriptCore/runtime/JSLock.h
+++ b/Source/JavaScriptCore/runtime/JSLock.h
@@ -56,7 +56,7 @@ namespace JSC {
class JSLock {
WTF_MAKE_NONCOPYABLE(JSLock);
public:
- JSLock(ExecState*);
+ JS_EXPORT_PRIVATE JSLock(ExecState*);
JSLock(JSGlobalData*);
JSLock(JSLockBehavior lockBehavior)
@@ -80,22 +80,22 @@ namespace JSC {
unlock(m_lockBehavior);
}
- static void lock(JSLockBehavior);
- static void unlock(JSLockBehavior);
+ JS_EXPORT_PRIVATE static void lock(JSLockBehavior);
+ JS_EXPORT_PRIVATE static void unlock(JSLockBehavior);
static void lock(ExecState*);
static void unlock(ExecState*);
- static intptr_t lockCount();
- static bool currentThreadIsHoldingLock();
+ JS_EXPORT_PRIVATE static intptr_t lockCount();
+ JS_EXPORT_PRIVATE static bool currentThreadIsHoldingLock();
JSLockBehavior m_lockBehavior;
class DropAllLocks {
WTF_MAKE_NONCOPYABLE(DropAllLocks);
public:
- DropAllLocks(ExecState* exec);
- DropAllLocks(JSLockBehavior);
- ~DropAllLocks();
+ JS_EXPORT_PRIVATE DropAllLocks(ExecState* exec);
+ JS_EXPORT_PRIVATE DropAllLocks(JSLockBehavior);
+ JS_EXPORT_PRIVATE ~DropAllLocks();
private:
intptr_t m_lockCount;
diff --git a/Source/JavaScriptCore/runtime/JSONObject.cpp b/Source/JavaScriptCore/runtime/JSONObject.cpp
index 05c6c2953..83b118429 100644
--- a/Source/JavaScriptCore/runtime/JSONObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSONObject.cpp
@@ -142,7 +142,7 @@ static inline JSValue unwrapBoxedPrimitive(ExecState* exec, JSValue value)
if (object->inherits(&NumberObject::s_info))
return jsNumber(object->toNumber(exec));
if (object->inherits(&StringObject::s_info))
- return jsString(exec, object->toString(exec));
+ return object->toString(exec);
if (object->inherits(&BooleanObject::s_info))
return object->toPrimitive(exec);
return value;
@@ -223,25 +223,12 @@ Stringifier::Stringifier(ExecState* exec, const Local<Unknown>& replacer, const
if (exec->hadException())
break;
- UString propertyName;
- if (name.getString(exec, propertyName)) {
- m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName));
- continue;
- }
-
- if (name.isNumber()) {
- m_arrayReplacerPropertyNames.add(Identifier::from(exec, name.asNumber()));
- continue;
- }
-
if (name.isObject()) {
if (!asObject(name)->inherits(&NumberObject::s_info) && !asObject(name)->inherits(&StringObject::s_info))
continue;
- propertyName = name.toString(exec);
- if (exec->hadException())
- break;
- m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName));
}
+
+ m_arrayReplacerPropertyNames.add(Identifier(exec, name.toString(exec)->value(exec)));
}
return;
}
@@ -825,8 +812,7 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec)
{
if (!exec->argumentCount())
return throwVMError(exec, createError(exec, "JSON.parse requires at least one parameter"));
- JSValue value = exec->argument(0);
- UString source = value.toString(exec);
+ UString source = exec->argument(0).toString(exec)->value(exec);
if (exec->hadException())
return JSValue::encode(jsNull());
diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp
index a813e8416..a443fda86 100644
--- a/Source/JavaScriptCore/runtime/JSObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSObject.cpp
@@ -24,6 +24,7 @@
#include "config.h"
#include "JSObject.h"
+#include "BumpSpaceInlineMethods.h"
#include "DatePrototype.h"
#include "ErrorConstructor.h"
#include "GetterSetter.h"
@@ -83,11 +84,6 @@ static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* class
}
}
-void JSObject::finalize(JSCell* cell)
-{
- delete [] jsCast<JSObject*>(cell)->m_propertyStorage.get();
-}
-
void JSObject::destroy(JSCell* cell)
{
jsCast<JSObject*>(cell)->JSObject::~JSObject();
@@ -106,7 +102,16 @@ void JSObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
PropertyStorage storage = thisObject->propertyStorage();
size_t storageSize = thisObject->structure()->propertyStorageSize();
- visitor.appendValues(storage, storageSize);
+ if (thisObject->isUsingInlineStorage())
+ visitor.appendValues(storage, storageSize);
+ else {
+ // We have this extra temp here to slake GCC's thirst for the blood of those who dereference type-punned pointers.
+ void* temp = storage;
+ visitor.copyAndAppend(&temp, thisObject->structure()->propertyStorageCapacity() * sizeof(WriteBarrierBase<Unknown>), storage->slot(), storageSize);
+ storage = static_cast<PropertyStorage>(temp);
+ thisObject->m_propertyStorage.set(storage, StorageBarrier::Unchecked);
+ }
+
if (thisObject->m_inheritorID)
visitor.append(&thisObject->m_inheritorID);
@@ -162,7 +167,7 @@ void JSObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName
for (JSObject* obj = thisObject; !obj->structure()->hasGetterSetterProperties(); obj = asObject(prototype)) {
prototype = obj->prototype();
if (prototype.isNull()) {
- if (!thisObject->putDirectInternal(globalData, propertyName, value, 0, true, slot, getJSFunction(value)) && slot.isStrictMode())
+ if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value)) && slot.isStrictMode())
throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
return;
}
@@ -205,7 +210,7 @@ void JSObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName
break;
}
- if (!thisObject->putDirectInternal(globalData, propertyName, value, 0, true, slot, getJSFunction(value)) && slot.isStrictMode())
+ if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value)) && slot.isStrictMode())
throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
return;
}
@@ -217,16 +222,28 @@ void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName,
thisObject->methodTable()->put(thisObject, exec, Identifier::from(exec, propertyName), value, slot);
}
-void JSObject::putWithAttributes(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
+void JSObject::putDirectVirtual(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
{
+ ASSERT(!value.isGetterSetter() && !(attributes & Accessor));
PutPropertySlot slot;
- object->putDirectInternal(exec->globalData(), propertyName, value, attributes, true, slot, getJSFunction(value));
+ object->putDirectInternal<PutModeDefineOwnProperty>(exec->globalData(), propertyName, value, attributes, slot, getJSFunction(value));
}
-void JSObject::putWithAttributes(JSGlobalData* globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
+void JSObject::putDirectAccessor(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
{
+ ASSERT(value.isGetterSetter() && (attributes & Accessor));
+ ASSERT(propertyName != globalData.propertyNames->underscoreProto);
+
PutPropertySlot slot;
- putDirectInternal(*globalData, propertyName, value, attributes, true, slot, getJSFunction(value));
+ putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getJSFunction(value));
+
+ // putDirect will change our Structure if we add a new property. For
+ // getters and setters, though, we also need to change our Structure
+ // if we override an existing non-getter or non-setter.
+ if (slot.type() != PutPropertySlot::NewProperty)
+ setStructure(globalData, Structure::attributeChangeTransition(globalData, structure(), propertyName, attributes));
+
+ structure()->setHasGetterSetterProperties(true);
}
bool JSObject::hasProperty(ExecState* exec, const Identifier& propertyName) const
@@ -361,15 +378,13 @@ void JSObject::defineGetter(JSObject* thisObject, ExecState* exec, const Identif
JSGlobalData& globalData = exec->globalData();
PutPropertySlot slot;
GetterSetter* getterSetter = GetterSetter::create(exec);
- thisObject->putDirectInternal(globalData, propertyName, getterSetter, attributes | Getter, true, slot, 0);
+ thisObject->putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, getterSetter, attributes | Accessor, slot, 0);
// putDirect will change our Structure if we add a new property. For
// getters and setters, though, we also need to change our Structure
// if we override an existing non-getter or non-setter.
- if (slot.type() != PutPropertySlot::NewProperty) {
- if (!thisObject->structure()->isDictionary())
- thisObject->setStructure(exec->globalData(), Structure::getterSetterTransition(globalData, thisObject->structure()));
- }
+ if (slot.type() != PutPropertySlot::NewProperty)
+ thisObject->setStructure(exec->globalData(), Structure::attributeChangeTransition(globalData, thisObject->structure(), propertyName, attributes | Accessor));
thisObject->structure()->setHasGetterSetterProperties(true);
getterSetter->setGetter(globalData, getterFunction);
@@ -379,20 +394,17 @@ void JSObject::initializeGetterSetterProperty(ExecState* exec, const Identifier&
{
// Set an inital property on an object; the property must not already exist & the attribute flags must be set correctly.
ASSERT(structure()->get(exec->globalData(), propertyName) == WTF::notFound);
- ASSERT(static_cast<bool>(getterSetter->getter()) == static_cast<bool>(attributes & Getter));
- ASSERT(static_cast<bool>(getterSetter->setter()) == static_cast<bool>(attributes & Setter));
+ ASSERT(static_cast<bool>(attributes & Accessor));
JSGlobalData& globalData = exec->globalData();
PutPropertySlot slot;
- putDirectInternal(globalData, propertyName, getterSetter, attributes | Getter, true, slot, 0);
+ putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, getterSetter, attributes, slot, 0);
// putDirect will change our Structure if we add a new property. For
// getters and setters, though, we also need to change our Structure
// if we override an existing non-getter or non-setter.
- if (slot.type() != PutPropertySlot::NewProperty) {
- if (!structure()->isDictionary())
- setStructure(exec->globalData(), Structure::getterSetterTransition(globalData, structure()));
- }
+ if (slot.type() != PutPropertySlot::NewProperty)
+ setStructure(exec->globalData(), Structure::attributeChangeTransition(globalData, structure(), propertyName, attributes));
structure()->setHasGetterSetterProperties(true);
}
@@ -413,15 +425,13 @@ void JSObject::defineSetter(JSObject* thisObject, ExecState* exec, const Identif
PutPropertySlot slot;
GetterSetter* getterSetter = GetterSetter::create(exec);
- thisObject->putDirectInternal(exec->globalData(), propertyName, getterSetter, attributes | Setter, true, slot, 0);
+ thisObject->putDirectInternal<PutModeDefineOwnProperty>(exec->globalData(), propertyName, getterSetter, attributes | Accessor, slot, 0);
// putDirect will change our Structure if we add a new property. For
// getters and setters, though, we also need to change our Structure
// if we override an existing non-getter or non-setter.
- if (slot.type() != PutPropertySlot::NewProperty) {
- if (!thisObject->structure()->isDictionary())
- thisObject->setStructure(exec->globalData(), Structure::getterSetterTransition(exec->globalData(), thisObject->structure()));
- }
+ if (slot.type() != PutPropertySlot::NewProperty)
+ thisObject->setStructure(exec->globalData(), Structure::attributeChangeTransition(exec->globalData(), thisObject->structure(), propertyName, attributes | Accessor));
thisObject->structure()->setHasGetterSetterProperties(true);
getterSetter->setSetter(exec->globalData(), setterFunction);
@@ -531,11 +541,11 @@ double JSObject::toNumber(ExecState* exec) const
return primitive.toNumber(exec);
}
-UString JSObject::toString(ExecState* exec) const
+JSString* JSObject::toString(ExecState* exec) const
{
JSValue primitive = toPrimitive(exec, PreferString);
if (exec->hadException())
- return "";
+ return jsEmptyString(exec);
return primitive.toString(exec);
}
@@ -646,20 +656,28 @@ void JSObject::allocatePropertyStorage(JSGlobalData& globalData, size_t oldSize,
// It's important that this function not rely on structure(), since
// we might be in the middle of a transition.
- PropertyStorage newPropertyStorage = 0;
- newPropertyStorage = new WriteBarrierBase<Unknown>[newSize];
PropertyStorage oldPropertyStorage = m_propertyStorage.get();
- ASSERT(newPropertyStorage);
+ PropertyStorage newPropertyStorage = 0;
- for (unsigned i = 0; i < oldSize; ++i)
- newPropertyStorage[i] = oldPropertyStorage[i];
+ if (isUsingInlineStorage()) {
+ // We have this extra temp here to slake GCC's thirst for the blood of those who dereference type-punned pointers.
+ void* temp = newPropertyStorage;
+ if (!globalData.heap.tryAllocateStorage(sizeof(WriteBarrierBase<Unknown>) * newSize, &temp))
+ CRASH();
+ newPropertyStorage = static_cast<PropertyStorage>(temp);
- if (isUsingInlineStorage())
- Heap::heap(this)->addFinalizer(this, &finalize);
- else
- delete [] oldPropertyStorage;
+ for (unsigned i = 0; i < oldSize; ++i)
+ newPropertyStorage[i] = oldPropertyStorage[i];
+ } else {
+ // We have this extra temp here to slake GCC's thirst for the blood of those who dereference type-punned pointers.
+ void* temp = oldPropertyStorage;
+ if (!globalData.heap.tryReallocateStorage(&temp, sizeof(WriteBarrierBase<Unknown>) * oldSize, sizeof(WriteBarrierBase<Unknown>) * newSize))
+ CRASH();
+ newPropertyStorage = static_cast<PropertyStorage>(temp);
+ }
+ ASSERT(newPropertyStorage);
m_propertyStorage.set(globalData, this, newPropertyStorage);
}
@@ -692,15 +710,11 @@ static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& p
if (descriptor.isGenericDescriptor() || descriptor.isDataDescriptor()) {
if (descriptor.isGenericDescriptor() && oldDescriptor.isAccessorDescriptor()) {
GetterSetter* accessor = GetterSetter::create(exec);
- if (oldDescriptor.getter()) {
- attributes |= Getter;
- accessor->setGetter(exec->globalData(), asObject(oldDescriptor.getter()));
- }
- if (oldDescriptor.setter()) {
- attributes |= Setter;
- accessor->setSetter(exec->globalData(), asObject(oldDescriptor.setter()));
- }
- target->methodTable()->putWithAttributes(target, exec, propertyName, accessor, attributes);
+ if (oldDescriptor.getterPresent())
+ accessor->setGetter(exec->globalData(), oldDescriptor.getterObject());
+ if (oldDescriptor.setterPresent())
+ accessor->setSetter(exec->globalData(), oldDescriptor.setterObject());
+ target->putDirectAccessor(exec->globalData(), propertyName, accessor, attributes | Accessor);
return true;
}
JSValue newValue = jsUndefined();
@@ -708,21 +722,32 @@ static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& p
newValue = descriptor.value();
else if (oldDescriptor.value())
newValue = oldDescriptor.value();
- target->methodTable()->putWithAttributes(target, exec, propertyName, newValue, attributes & ~(Getter | Setter));
+ target->putDirect(exec->globalData(), propertyName, newValue, attributes & ~Accessor);
return true;
}
attributes &= ~ReadOnly;
- if (descriptor.getter() && descriptor.getter().isObject())
- target->methodTable()->defineGetter(target, exec, propertyName, asObject(descriptor.getter()), attributes);
- if (exec->hadException())
- return false;
- if (descriptor.setter() && descriptor.setter().isObject())
- target->methodTable()->defineSetter(target, exec, propertyName, asObject(descriptor.setter()), attributes);
- return !exec->hadException();
+ GetterSetter* accessor = GetterSetter::create(exec);
+
+ if (descriptor.getterPresent())
+ accessor->setGetter(exec->globalData(), descriptor.getterObject());
+ else if (oldDescriptor.getterPresent())
+ accessor->setGetter(exec->globalData(), oldDescriptor.getterObject());
+ if (descriptor.setterPresent())
+ accessor->setSetter(exec->globalData(), descriptor.setterObject());
+ else if (oldDescriptor.setterPresent())
+ accessor->setSetter(exec->globalData(), oldDescriptor.setterObject());
+
+ target->putDirectAccessor(exec->globalData(), propertyName, accessor, attributes | Accessor);
+ return true;
}
bool JSObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException)
{
+ // __proto__ is magic; we don't currently support setting it as a regular property.
+ // Silent filter out calls to set __proto__ at an early stage; pretend all is okay.
+ if (propertyName == exec->propertyNames().underscoreProto)
+ return true;
+
// If we have a new property we can just put it on normally
PropertyDescriptor current;
if (!object->methodTable()->getOwnPropertyDescriptor(object, exec, propertyName, current)) {
@@ -824,19 +849,15 @@ bool JSObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identi
return false;
GetterSetter* getterSetter = asGetterSetter(accessor);
if (current.attributesEqual(descriptor)) {
- if (descriptor.setter())
- getterSetter->setSetter(exec->globalData(), asObject(descriptor.setter()));
- if (descriptor.getter())
- getterSetter->setGetter(exec->globalData(), asObject(descriptor.getter()));
+ if (descriptor.setterPresent())
+ getterSetter->setSetter(exec->globalData(), descriptor.setterObject());
+ if (descriptor.getterPresent())
+ getterSetter->setGetter(exec->globalData(), descriptor.getterObject());
return true;
}
object->methodTable()->deleteProperty(object, exec, propertyName);
unsigned attrs = current.attributesWithOverride(descriptor);
- if (descriptor.setter())
- attrs |= Setter;
- if (descriptor.getter())
- attrs |= Getter;
- object->putDirect(exec->globalData(), propertyName, getterSetter, attrs);
+ object->putDirectAccessor(exec->globalData(), propertyName, getterSetter, attrs | Accessor);
return true;
}
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h
index e26012dd9..433249c20 100644
--- a/Source/JavaScriptCore/runtime/JSObject.h
+++ b/Source/JavaScriptCore/runtime/JSObject.h
@@ -55,7 +55,7 @@ namespace JSC {
class Structure;
struct HashTable;
- JSObject* throwTypeError(ExecState*, const UString&);
+ JS_EXPORT_PRIVATE JSObject* throwTypeError(ExecState*, const UString&);
extern JS_EXPORTDATA const char* StrictModeReadonlyPropertyWriteError;
// ECMA 262-3 8.6.1
@@ -66,8 +66,7 @@ namespace JSC {
DontEnum = 1 << 2, // property doesn't appear in (for .. in ..)
DontDelete = 1 << 3, // property can't be deleted
Function = 1 << 4, // property is a function - only used by static hashtables
- Getter = 1 << 5, // property is a getter
- Setter = 1 << 6 // property is a setter
+ Accessor = 1 << 5, // property is a getter/setter
};
class JSObject : public JSCell {
@@ -75,18 +74,21 @@ namespace JSC {
friend class JIT;
friend class JSCell;
friend class MarkedBlock;
- friend bool setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot);
+ JS_EXPORT_PRIVATE friend bool setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot);
+
+ enum PutMode {
+ PutModePut,
+ PutModeDefineOwnProperty,
+ };
public:
typedef JSCell Base;
- static void destroy(JSCell*);
-
- static void visitChildren(JSCell*, SlotVisitor&);
+ JS_EXPORT_PRIVATE static void destroy(JSCell*);
- static UString className(const JSObject*);
+ JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
- static void finalize(JSCell*);
+ JS_EXPORT_PRIVATE static UString className(const JSObject*);
JSValue prototype() const;
void setPrototype(JSGlobalData&, JSValue prototype);
@@ -99,43 +101,50 @@ namespace JSC {
bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
- bool getPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&);
+ JS_EXPORT_PRIVATE bool getPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&);
static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&);
- static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
- static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
-
- static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
- static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue);
-
- static void putWithAttributes(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
- void putWithAttributes(JSGlobalData*, const Identifier& propertyName, JSValue, unsigned attributes);
+ JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
+ JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
+
+ JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+ JS_EXPORT_PRIVATE static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue);
+
+ // putDirect is effectively an unchecked vesion of 'defineOwnProperty':
+ // - the prototype chain is not consulted
+ // - accessors are not called.
+ // - attributes will be respected (after the call the property will exist with the given attributes)
+ JS_EXPORT_PRIVATE static void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
+ void putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attributes = 0);
+ void putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, PutPropertySlot&);
+ void putDirectWithoutTransition(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attributes = 0);
+ void putDirectAccessor(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attributes);
bool propertyIsEnumerable(ExecState*, const Identifier& propertyName) const;
- bool hasProperty(ExecState*, const Identifier& propertyName) const;
- bool hasProperty(ExecState*, unsigned propertyName) const;
+ JS_EXPORT_PRIVATE bool hasProperty(ExecState*, const Identifier& propertyName) const;
+ JS_EXPORT_PRIVATE bool hasProperty(ExecState*, unsigned propertyName) const;
bool hasOwnProperty(ExecState*, const Identifier& propertyName) const;
- static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
- static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
+ JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
+ JS_EXPORT_PRIVATE static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
- static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
+ JS_EXPORT_PRIVATE static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
- static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty);
+ JS_EXPORT_PRIVATE static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty);
- static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
- static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+ JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+ JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
- bool toBoolean(ExecState*) const;
+ JS_EXPORT_PRIVATE bool toBoolean(ExecState*) const;
bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
- double toNumber(ExecState*) const;
- UString toString(ExecState*) const;
+ JS_EXPORT_PRIVATE double toNumber(ExecState*) const;
+ JS_EXPORT_PRIVATE JSString* toString(ExecState*) const;
// NOTE: JSObject and its subclasses must be able to gracefully handle ExecState* = 0,
// because this call may come from inside the compiler.
- static JSObject* toThisObject(JSCell*, ExecState*);
+ JS_EXPORT_PRIVATE static JSObject* toThisObject(JSCell*, ExecState*);
JSObject* unwrappedObject();
bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const;
@@ -171,35 +180,37 @@ namespace JSC {
bool hasCustomProperties() { return structure()->didTransition(); }
bool hasGetterSetterProperties() { return structure()->hasGetterSetterProperties(); }
- bool putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, bool checkReadOnly, PutPropertySlot&);
- void putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr = 0);
- bool putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, PutPropertySlot&);
-
- void putDirectWithoutTransition(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr = 0);
+ // putOwnDataProperty has 'put' like semantics, however this method:
+ // - assumes the object contains no own getter/setter properties.
+ // - provides no special handling for __proto__
+ // - does not walk the prototype chain (to check for accessors or non-writable properties).
+ // This is used by JSActivation.
+ bool putOwnDataProperty(JSGlobalData&, const Identifier& propertyName, JSValue, PutPropertySlot&);
// Fast access to known property offsets.
JSValue getDirectOffset(size_t offset) const { return propertyStorage()[offset].get(); }
void putDirectOffset(JSGlobalData& globalData, size_t offset, JSValue value) { propertyStorage()[offset].set(globalData, this, value); }
void putUndefinedAtDirectOffset(size_t offset) { propertyStorage()[offset].setUndefined(); }
- void fillGetterPropertySlot(PropertySlot&, WriteBarrierBase<Unknown>* location);
+ JS_EXPORT_PRIVATE void fillGetterPropertySlot(PropertySlot&, WriteBarrierBase<Unknown>* location);
void initializeGetterSetterProperty(ExecState*, const Identifier&, GetterSetter*, unsigned attributes);
- static void defineGetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes = 0);
- static void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes = 0);
- JSValue lookupGetter(ExecState*, const Identifier& propertyName);
- JSValue lookupSetter(ExecState*, const Identifier& propertyName);
- static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
+ JS_EXPORT_PRIVATE static void defineGetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes = 0);
+ JS_EXPORT_PRIVATE static void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes = 0);
+ JS_EXPORT_PRIVATE JSValue lookupGetter(ExecState*, const Identifier& propertyName);
+ JS_EXPORT_PRIVATE JSValue lookupSetter(ExecState*, const Identifier& propertyName);
+ JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
bool isGlobalObject() const;
bool isVariableObject() const;
+ bool isStaticScopeObject() const;
bool isActivationObject() const;
bool isErrorInstance() const;
bool isGlobalThis() const;
void seal(JSGlobalData&);
void freeze(JSGlobalData&);
- void preventExtensions(JSGlobalData&);
+ JS_EXPORT_PRIVATE void preventExtensions(JSGlobalData&);
bool isSealed(JSGlobalData& globalData) { return structure()->isSealed(globalData); }
bool isFrozen(JSGlobalData& globalData) { return structure()->isFrozen(globalData); }
bool isExtensible() { return structure()->isExtensible(); }
@@ -207,7 +218,7 @@ namespace JSC {
bool staticFunctionsReified() { return structure()->staticFunctionsReified(); }
void reifyStaticFunctionsForDelete(ExecState* exec);
- void allocatePropertyStorage(JSGlobalData&, size_t oldSize, size_t newSize);
+ JS_EXPORT_PRIVATE void allocatePropertyStorage(JSGlobalData&, size_t oldSize, size_t newSize);
bool isUsingInlineStorage() const { return static_cast<const void*>(m_propertyStorage.get()) == static_cast<const void*>(this + 1); }
void* addressOfPropertyStorage()
@@ -281,7 +292,8 @@ namespace JSC {
return &propertyStorage()[offset];
}
- bool putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, bool checkReadOnly, PutPropertySlot&, JSCell*);
+ template<PutMode>
+ bool putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, PutPropertySlot&, JSCell*);
bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
@@ -317,7 +329,7 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineSt
return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
}
- static void destroy(JSCell*);
+ JS_EXPORT_PRIVATE static void destroy(JSCell*);
protected:
explicit JSNonFinalObject(JSGlobalData& globalData, Structure* structure)
@@ -417,6 +429,11 @@ inline bool JSObject::isVariableObject() const
return structure()->typeInfo().type() >= VariableObjectType;
}
+inline bool JSObject::isStaticScopeObject() const
+{
+ return structure()->typeInfo().type() == StaticScopeObjectType;
+}
+
inline bool JSObject::isActivationObject() const
{
return structure()->typeInfo().type() == ActivationObjectType;
@@ -628,9 +645,11 @@ inline JSValue JSObject::get(ExecState* exec, unsigned propertyName) const
return jsUndefined();
}
-inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot, JSCell* specificFunction)
+template<JSObject::PutMode mode>
+inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot, JSCell* specificFunction)
{
ASSERT(value);
+ ASSERT(value.isGetterSetter() == !!(attributes & Accessor));
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
if (structure()->isDictionary()) {
@@ -642,7 +661,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
// or the new value is different, then despecify.
if (currentSpecificFunction && (specificFunction != currentSpecificFunction))
structure()->despecifyDictionaryFunction(globalData, propertyName);
- if (checkReadOnly && currentAttributes & ReadOnly)
+ if ((mode == PutModePut) && currentAttributes & ReadOnly)
return false;
putDirectOffset(globalData, offset, value);
@@ -657,7 +676,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
return true;
}
- if (checkReadOnly && !isExtensible())
+ if ((mode == PutModePut) && !isExtensible())
return false;
size_t currentCapacity = structure()->propertyStorageCapacity();
@@ -693,7 +712,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
JSCell* currentSpecificFunction;
offset = structure()->get(globalData, propertyName, currentAttributes, currentSpecificFunction);
if (offset != WTF::notFound) {
- if (checkReadOnly && currentAttributes & ReadOnly)
+ if ((mode == PutModePut) && currentAttributes & ReadOnly)
return false;
// There are three possibilities here:
@@ -721,7 +740,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
return true;
}
- if (checkReadOnly && !isExtensible())
+ if ((mode == PutModePut) && !isExtensible())
return false;
Structure* structure = Structure::addPropertyTransition(globalData, this->structure(), propertyName, attributes, specificFunction, offset);
@@ -739,27 +758,31 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
return true;
}
-inline bool JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
+inline bool JSObject::putOwnDataProperty(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
ASSERT(value);
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+ ASSERT(!structure()->hasGetterSetterProperties());
- return putDirectInternal(globalData, propertyName, value, attributes, checkReadOnly, slot, getJSFunction(value));
+ return putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value));
}
inline void JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
{
+ ASSERT(!value.isGetterSetter() && !(attributes & Accessor));
PutPropertySlot slot;
- putDirectInternal(globalData, propertyName, value, attributes, false, slot, getJSFunction(value));
+ putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getJSFunction(value));
}
-inline bool JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+inline void JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
- return putDirectInternal(globalData, propertyName, value, 0, false, slot, getJSFunction(value));
+ ASSERT(!value.isGetterSetter());
+ putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, 0, slot, getJSFunction(value));
}
inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
{
+ ASSERT(!value.isGetterSetter() && !(attributes & Accessor));
size_t currentCapacity = structure()->propertyStorageCapacity();
size_t offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, getJSFunction(value));
if (currentCapacity != structure()->propertyStorageCapacity())
@@ -841,13 +864,6 @@ inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValu
asCell()->methodTable()->put(asCell(), exec, propertyName, value, slot);
}
-inline void JSValue::putDirect(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
-{
- ASSERT(isCell() && isObject());
- if (!asObject(asCell())->putDirect(exec->globalData(), propertyName, value, slot) && slot.isStrictMode())
- throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
-}
-
inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value)
{
if (UNLIKELY(!isCell())) {
diff --git a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
index ada921d0e..f8942b5f8 100644
--- a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
@@ -78,7 +78,7 @@ void JSStaticScopeObject::put(JSCell* cell, ExecState* exec, const Identifier& p
ASSERT_NOT_REACHED();
}
-void JSStaticScopeObject::putWithAttributes(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
+void JSStaticScopeObject::putDirectVirtual(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
{
JSStaticScopeObject* thisObject = jsCast<JSStaticScopeObject*>(object);
if (thisObject->symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
diff --git a/Source/JavaScriptCore/runtime/JSStaticScopeObject.h b/Source/JavaScriptCore/runtime/JSStaticScopeObject.h
index 6a2e51a15..bbf03a347 100644
--- a/Source/JavaScriptCore/runtime/JSStaticScopeObject.h
+++ b/Source/JavaScriptCore/runtime/JSStaticScopeObject.h
@@ -47,7 +47,7 @@ namespace JSC{
static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
static void put(JSCell*, ExecState*, const Identifier&, JSValue, PutPropertySlot&);
- static void putWithAttributes(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes);
+ static void putDirectVirtual(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes);
static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(StaticScopeObjectType, StructureFlags), &s_info); }
diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp
index 93193b5e5..4e98f9d18 100644
--- a/Source/JavaScriptCore/runtime/JSString.cpp
+++ b/Source/JavaScriptCore/runtime/JSString.cpp
@@ -229,11 +229,6 @@ double JSString::toNumber(ExecState* exec) const
return jsToNumber(value(exec));
}
-UString JSString::toString(ExecState* exec) const
-{
- return value(exec);
-}
-
inline StringObject* StringObject::create(ExecState* exec, JSGlobalObject* globalObject, JSString* string)
{
StringObject* object = new (NotNull, allocateCell<StringObject>(*exec->heap())) StringObject(exec->globalData(), globalObject->stringObjectStructure());
diff --git a/Source/JavaScriptCore/runtime/JSString.h b/Source/JavaScriptCore/runtime/JSString.h
index f40455571..c0637a6e0 100644
--- a/Source/JavaScriptCore/runtime/JSString.h
+++ b/Source/JavaScriptCore/runtime/JSString.h
@@ -214,10 +214,9 @@ namespace JSC {
unsigned length() { return m_length; }
JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
- bool toBoolean(ExecState*) const;
+ JS_EXPORT_PRIVATE bool toBoolean(ExecState*) const;
bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
JSObject* toObject(ExecState*, JSGlobalObject*) const;
- UString toString(ExecState*) const;
double toNumber(ExecState*) const;
bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
@@ -236,12 +235,12 @@ namespace JSC {
static size_t offsetOfLength() { return OBJECT_OFFSETOF(JSString, m_length); }
static size_t offsetOfValue() { return OBJECT_OFFSETOF(JSString, m_value); }
- static const ClassInfo s_info;
+ static JS_EXPORTDATA const ClassInfo s_info;
static void visitChildren(JSCell*, SlotVisitor&);
private:
- void resolveRope(ExecState*) const;
+ JS_EXPORT_PRIVATE void resolveRope(ExecState*) const;
void resolveRopeSlowCase8(LChar*) const;
void resolveRopeSlowCase(UChar*) const;
void outOfMemory(ExecState*) const;
@@ -453,24 +452,11 @@ namespace JSC {
return isTrue(); // false, null, and undefined all convert to false.
}
- inline UString JSValue::toString(ExecState* exec) const
+ inline JSString* JSValue::toString(ExecState* exec) const
{
if (isString())
- return static_cast<JSString*>(asCell())->value(exec);
- if (isInt32())
- return exec->globalData().numericStrings.add(asInt32());
- if (isDouble())
- return exec->globalData().numericStrings.add(asDouble());
- if (isTrue())
- return "true";
- if (isFalse())
- return "false";
- if (isNull())
- return "null";
- if (isUndefined())
- return "undefined";
- ASSERT(isCell());
- return asCell()->toString(exec);
+ return static_cast<JSString*>(asCell());
+ return toStringSlowCase(exec);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSValue.cpp b/Source/JavaScriptCore/runtime/JSValue.cpp
index a5d3d936a..6b803c316 100644
--- a/Source/JavaScriptCore/runtime/JSValue.cpp
+++ b/Source/JavaScriptCore/runtime/JSValue.cpp
@@ -204,10 +204,9 @@ bool JSValue::isValidCallee()
return asObject(asCell())->globalObject();
}
-JSString* JSValue::toPrimitiveString(ExecState* exec) const
+JSString* JSValue::toStringSlowCase(ExecState* exec) const
{
- if (isString())
- return static_cast<JSString*>(asCell());
+ ASSERT(!isString());
if (isInt32())
return jsString(&exec->globalData(), exec->globalData().numericStrings.add(asInt32()));
if (isDouble())
@@ -222,10 +221,11 @@ JSString* JSValue::toPrimitiveString(ExecState* exec) const
return jsNontrivialString(exec, exec->propertyNames().undefined.ustring());
ASSERT(isCell());
- JSValue v = asCell()->toPrimitive(exec, NoPreference);
- if (v.isString())
- return static_cast<JSString*>(v.asCell());
- return jsString(&exec->globalData(), v.toString(exec));
+ JSValue value = asCell()->toPrimitive(exec, PreferString);
+ if (exec->hadException())
+ return jsEmptyString(exec);
+ ASSERT(!value.isObject());
+ return value.toString(exec);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h
index a00106274..79e50fba0 100644
--- a/Source/JavaScriptCore/runtime/JSValue.h
+++ b/Source/JavaScriptCore/runtime/JSValue.h
@@ -93,7 +93,7 @@ namespace JSC {
};
// This implements ToInt32, defined in ECMA-262 9.5.
- int32_t toInt32(double);
+ JS_EXPORT_PRIVATE int32_t toInt32(double);
// This implements ToUInt32, defined in ECMA-262 9.6.
inline uint32_t toUInt32(double number)
@@ -197,13 +197,12 @@ namespace JSC {
// toNumber conversion is expected to be side effect free if an exception has
// been set in the ExecState already.
double toNumber(ExecState*) const;
- UString toString(ExecState*) const;
- JSString* toPrimitiveString(ExecState*) const;
+ JSString* toString(ExecState*) const;
JSObject* toObject(ExecState*) const;
JSObject* toObject(ExecState*, JSGlobalObject*) const;
// Integer conversions.
- double toInteger(ExecState*) const;
+ JS_EXPORT_PRIVATE double toInteger(ExecState*) const;
double toIntegerPreserveNaN(ExecState*) const;
int32_t toInt32(ExecState*) const;
uint32_t toUInt32(ExecState*) const;
@@ -218,7 +217,6 @@ namespace JSC {
JSValue get(ExecState*, unsigned propertyName) const;
JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const;
void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
- void putDirect(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
void put(ExecState*, unsigned propertyName, JSValue);
JSObject* toThisObject(ExecState*) const;
@@ -232,7 +230,7 @@ namespace JSC {
bool isCell() const;
JSCell* asCell() const;
- bool isValidCallee();
+ JS_EXPORT_PRIVATE bool isValidCallee();
#ifndef NDEBUG
char* description();
@@ -245,11 +243,12 @@ namespace JSC {
JSValue(HashTableDeletedValueTag);
inline const JSValue asValue() const { return *this; }
- double toNumberSlowCase(ExecState*) const;
- JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const;
- JSObject* toThisObjectSlowCase(ExecState*) const;
+ JS_EXPORT_PRIVATE double toNumberSlowCase(ExecState*) const;
+ JS_EXPORT_PRIVATE JSString* toStringSlowCase(ExecState*) const;
+ JS_EXPORT_PRIVATE JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const;
+ JS_EXPORT_PRIVATE JSObject* toThisObjectSlowCase(ExecState*) const;
- JSObject* synthesizePrototype(ExecState*) const;
+ JS_EXPORT_PRIVATE JSObject* synthesizePrototype(ExecState*) const;
JSObject* synthesizeObject(ExecState*) const;
#if USE(JSVALUE32_64)
diff --git a/Source/JavaScriptCore/runtime/JSValueInlineMethods.h b/Source/JavaScriptCore/runtime/JSValueInlineMethods.h
index e13d34745..1373558f7 100644
--- a/Source/JavaScriptCore/runtime/JSValueInlineMethods.h
+++ b/Source/JavaScriptCore/runtime/JSValueInlineMethods.h
@@ -477,6 +477,7 @@ namespace JSC {
inline double JSValue::asDouble() const
{
+ ASSERT(isDouble());
return reinterpretIntptrToDouble(u.asInt64 - DoubleEncodeOffset);
}
diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.cpp b/Source/JavaScriptCore/runtime/JSVariableObject.cpp
index 706e3debb..8ca695074 100644
--- a/Source/JavaScriptCore/runtime/JSVariableObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSVariableObject.cpp
@@ -73,7 +73,7 @@ bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertyDe
return false;
}
-void JSVariableObject::putWithAttributes(JSObject*, ExecState*, const Identifier&, JSValue, unsigned)
+void JSVariableObject::putDirectVirtual(JSObject*, ExecState*, const Identifier&, JSValue, unsigned)
{
ASSERT_NOT_REACHED();
}
diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.h b/Source/JavaScriptCore/runtime/JSVariableObject.h
index 78e624e02..c1d05ff74 100644
--- a/Source/JavaScriptCore/runtime/JSVariableObject.h
+++ b/Source/JavaScriptCore/runtime/JSVariableObject.h
@@ -48,12 +48,12 @@ namespace JSC {
SymbolTable& symbolTable() const { return *m_symbolTable; }
- static void destroy(JSCell*);
+ JS_EXPORT_PRIVATE static void destroy(JSCell*);
- static NO_RETURN_DUE_TO_ASSERT void putWithAttributes(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes);
+ static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes);
- static bool deleteProperty(JSCell*, ExecState*, const Identifier&);
- static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+ JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, const Identifier&);
+ JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
bool isDynamicScope(bool& requiresDynamicChecks) const;
@@ -88,7 +88,7 @@ namespace JSC {
void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray);
bool symbolTableGet(const Identifier&, PropertySlot&);
- bool symbolTableGet(const Identifier&, PropertyDescriptor&);
+ JS_EXPORT_PRIVATE bool symbolTableGet(const Identifier&, PropertyDescriptor&);
bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
bool symbolTablePut(ExecState*, const Identifier&, JSValue, bool shouldThrow);
bool symbolTablePutWithAttributes(JSGlobalData&, const Identifier&, JSValue, unsigned attributes);
diff --git a/Source/JavaScriptCore/runtime/Lookup.h b/Source/JavaScriptCore/runtime/Lookup.h
index 8ed70b41d..64d06b503 100644
--- a/Source/JavaScriptCore/runtime/Lookup.h
+++ b/Source/JavaScriptCore/runtime/Lookup.h
@@ -126,7 +126,7 @@ namespace JSC {
createTable(&exec->globalData());
}
- void deleteTable() const;
+ JS_EXPORT_PRIVATE void deleteTable() const;
// Find an entry in the table, and return the entry.
ALWAYS_INLINE const HashEntry* entry(JSGlobalData* globalData, const Identifier& identifier) const
@@ -218,10 +218,10 @@ namespace JSC {
}
// Convert the hash table keys to identifiers.
- void createTable(JSGlobalData*) const;
+ JS_EXPORT_PRIVATE void createTable(JSGlobalData*) const;
};
- bool setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject* thisObject, const Identifier& propertyName, PropertySlot&);
+ JS_EXPORT_PRIVATE bool setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject* thisObject, const Identifier& propertyName, PropertySlot&);
/**
* This method does it all (looking in the hashtable, checking for function
diff --git a/Source/JavaScriptCore/runtime/MemoryStatistics.h b/Source/JavaScriptCore/runtime/MemoryStatistics.h
index d4b8b6fc1..9a86df296 100644
--- a/Source/JavaScriptCore/runtime/MemoryStatistics.h
+++ b/Source/JavaScriptCore/runtime/MemoryStatistics.h
@@ -37,7 +37,7 @@ struct GlobalMemoryStatistics {
size_t JITBytes;
};
-GlobalMemoryStatistics globalMemoryStatistics();
+JS_EXPORT_PRIVATE GlobalMemoryStatistics globalMemoryStatistics();
}
diff --git a/Source/JavaScriptCore/runtime/NumberPrototype.cpp b/Source/JavaScriptCore/runtime/NumberPrototype.cpp
index 4612b56d2..fb90bcd17 100644
--- a/Source/JavaScriptCore/runtime/NumberPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/NumberPrototype.cpp
@@ -447,7 +447,7 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec)
radix = static_cast<int>(radixValue.toInteger(exec)); // nan -> 0
if (radix == 10)
- return JSValue::encode(jsString(exec, jsNumber(x).toString(exec)));
+ return JSValue::encode(jsNumber(x).toString(exec));
// Fast path for number to character conversion.
if (radix == 36) {
@@ -474,7 +474,7 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState* exec)
if (!toThisNumber(exec->hostThisValue(), x))
return throwVMTypeError(exec);
- return JSValue::encode(jsString(exec, jsNumber(x).toString(exec)));
+ return JSValue::encode(jsNumber(x).toString(exec));
}
EncodedJSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState* exec)
diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
index 65d28c18c..d96c1de7f 100644
--- a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
@@ -149,7 +149,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState
{
if (!exec->argument(0).isObject())
return throwVMError(exec, createTypeError(exec, "Requested property descriptor of a value that is not an object."));
- UString propertyName = exec->argument(1).toString(exec);
+ UString propertyName = exec->argument(1).toString(exec)->value(exec);
if (exec->hadException())
return JSValue::encode(jsNull());
JSObject* object = asObject(exec->argument(0));
@@ -164,8 +164,10 @@ EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState
description->putDirect(exec->globalData(), exec->propertyNames().value, descriptor.value() ? descriptor.value() : jsUndefined(), 0);
description->putDirect(exec->globalData(), exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0);
} else {
- description->putDirect(exec->globalData(), exec->propertyNames().get, descriptor.getter() ? descriptor.getter() : jsUndefined(), 0);
- description->putDirect(exec->globalData(), exec->propertyNames().set, descriptor.setter() ? descriptor.setter() : jsUndefined(), 0);
+ ASSERT(descriptor.getter());
+ ASSERT(descriptor.setter());
+ description->putDirect(exec->globalData(), exec->propertyNames().get, descriptor.getter(), 0);
+ description->putDirect(exec->globalData(), exec->propertyNames().set, descriptor.setter(), 0);
}
description->putDirect(exec->globalData(), exec->propertyNames().enumerable, jsBoolean(descriptor.enumerable()), 0);
@@ -251,8 +253,7 @@ static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor
throwError(exec, createTypeError(exec, "Getter must be a function."));
return false;
}
- } else
- get = JSValue();
+ }
desc.setGetter(get);
}
@@ -267,9 +268,7 @@ static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor
throwError(exec, createTypeError(exec, "Setter must be a function."));
return false;
}
- } else
- set = JSValue();
-
+ }
desc.setSetter(set);
}
@@ -293,13 +292,13 @@ EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState* exec)
if (!exec->argument(0).isObject())
return throwVMError(exec, createTypeError(exec, "Properties can only be defined on Objects."));
JSObject* O = asObject(exec->argument(0));
- UString propertyName = exec->argument(1).toString(exec);
+ UString propertyName = exec->argument(1).toString(exec)->value(exec);
if (exec->hadException())
return JSValue::encode(jsNull());
PropertyDescriptor descriptor;
if (!toPropertyDescriptor(exec, exec->argument(2), descriptor))
return JSValue::encode(jsNull());
- ASSERT((descriptor.attributes() & (Getter | Setter)) || (!descriptor.isAccessorDescriptor()));
+ ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
ASSERT(!exec->hadException());
O->methodTable()->defineOwnProperty(O, exec, Identifier(exec, propertyName), descriptor, true);
return JSValue::encode(O);
diff --git a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
index 3f4dc19db..7ca7dae61 100644
--- a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
@@ -118,7 +118,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncValueOf(ExecState* exec)
EncodedJSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- return JSValue::encode(jsBoolean(thisValue.toObject(exec)->hasOwnProperty(exec, Identifier(exec, exec->argument(0).toString(exec)))));
+ return JSValue::encode(jsBoolean(thisValue.toObject(exec)->hasOwnProperty(exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)))));
}
EncodedJSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState* exec)
@@ -149,7 +149,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineGetter(ExecState* exec)
CallData callData;
if (getCallData(exec->argument(1), callData) == CallTypeNone)
return throwVMError(exec, createSyntaxError(exec, "invalid getter usage"));
- thisObject->methodTable()->defineGetter(thisObject, exec, Identifier(exec, exec->argument(0).toString(exec)), asObject(exec->argument(1)), 0);
+ thisObject->methodTable()->defineGetter(thisObject, exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)), asObject(exec->argument(1)), 0);
return JSValue::encode(jsUndefined());
}
@@ -162,7 +162,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState* exec)
CallData callData;
if (getCallData(exec->argument(1), callData) == CallTypeNone)
return throwVMError(exec, createSyntaxError(exec, "invalid setter usage"));
- thisObject->methodTable()->defineSetter(thisObject, exec, Identifier(exec, exec->argument(0).toString(exec)), asObject(exec->argument(1)), 0);
+ thisObject->methodTable()->defineSetter(thisObject, exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)), asObject(exec->argument(1)), 0);
return JSValue::encode(jsUndefined());
}
@@ -172,7 +172,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupGetter(ExecState* exec)
if (exec->hadException())
return JSValue::encode(jsUndefined());
- return JSValue::encode(thisObject->lookupGetter(exec, Identifier(exec, exec->argument(0).toString(exec))));
+ return JSValue::encode(thisObject->lookupGetter(exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec))));
}
EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState* exec)
@@ -181,13 +181,13 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState* exec)
if (exec->hadException())
return JSValue::encode(jsUndefined());
- return JSValue::encode(thisObject->lookupSetter(exec, Identifier(exec, exec->argument(0).toString(exec))));
+ return JSValue::encode(thisObject->lookupSetter(exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec))));
}
EncodedJSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- return JSValue::encode(jsBoolean(thisValue.toObject(exec)->propertyIsEnumerable(exec, Identifier(exec, exec->argument(0).toString(exec)))));
+ return JSValue::encode(jsBoolean(thisValue.toObject(exec)->propertyIsEnumerable(exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)))));
}
// 15.2.4.3 Object.prototype.toLocaleString()
diff --git a/Source/JavaScriptCore/runtime/ObjectPrototype.h b/Source/JavaScriptCore/runtime/ObjectPrototype.h
index 78b1cbd39..4c49e97a7 100644
--- a/Source/JavaScriptCore/runtime/ObjectPrototype.h
+++ b/Source/JavaScriptCore/runtime/ObjectPrototype.h
@@ -59,7 +59,7 @@ namespace JSC {
bool m_hasNoPropertiesWithUInt32Names;
};
- EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*);
+ JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*);
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/Operations.cpp b/Source/JavaScriptCore/runtime/Operations.cpp
index b89746f3f..459feb466 100644
--- a/Source/JavaScriptCore/runtime/Operations.cpp
+++ b/Source/JavaScriptCore/runtime/Operations.cpp
@@ -47,13 +47,11 @@ NEVER_INLINE JSValue jsAddSlowCase(CallFrame* callFrame, JSValue v1, JSValue v2)
JSValue p1 = v1.toPrimitive(callFrame);
JSValue p2 = v2.toPrimitive(callFrame);
- if (p1.isString()) {
- return p2.isString()
- ? jsString(callFrame, asString(p1), asString(p2))
- : jsString(callFrame, asString(p1), jsString(callFrame, p2.toString(callFrame)));
- }
+ if (p1.isString())
+ return jsString(callFrame, asString(p1), p2.toString(callFrame));
+
if (p2.isString())
- return jsString(callFrame, jsString(callFrame, p1.toString(callFrame)), asString(p2));
+ return jsString(callFrame, p1.toString(callFrame), asString(p2));
return jsNumber(p1.toNumber(callFrame) + p2.toNumber(callFrame));
}
diff --git a/Source/JavaScriptCore/runtime/Operations.h b/Source/JavaScriptCore/runtime/Operations.h
index ca2174fa1..945283899 100644
--- a/Source/JavaScriptCore/runtime/Operations.h
+++ b/Source/JavaScriptCore/runtime/Operations.h
@@ -81,10 +81,7 @@ namespace JSC {
for (unsigned i = 0; i < count; ++i) {
JSValue v = strings[i].jsValue();
- if (v.isString())
- ropeBuilder.append(asString(v));
- else
- ropeBuilder.append(jsString(globalData, v.toString(exec)));
+ ropeBuilder.append(v.toString(exec));
if (ropeBuilder.length() < oldLength) // True for overflow
return throwOutOfMemoryError(exec);
@@ -97,20 +94,13 @@ namespace JSC {
{
JSGlobalData* globalData = &exec->globalData();
JSString::RopeBuilder ropeBuilder(*globalData);
-
- if (thisValue.isString())
- ropeBuilder.append(asString(thisValue));
- else
- ropeBuilder.append(jsString(globalData, thisValue.toString(exec)));
+ ropeBuilder.append(thisValue.toString(exec));
unsigned oldLength = 0;
for (unsigned i = 0; i < exec->argumentCount(); ++i) {
JSValue v = exec->argument(i);
- if (v.isString())
- ropeBuilder.append(asString(v));
- else
- ropeBuilder.append(jsString(globalData, v.toString(exec)));
+ ropeBuilder.append(v.toString(exec));
if (ropeBuilder.length() < oldLength) // True for overflow
return throwOutOfMemoryError(exec);
@@ -300,11 +290,8 @@ namespace JSC {
if (v1.isNumber() && v2.isNumber())
return jsNumber(v1.asNumber() + v2.asNumber());
- if (v1.isString()) {
- return v2.isString()
- ? jsString(callFrame, asString(v1), asString(v2))
- : jsString(callFrame, asString(v1), v2.toPrimitiveString(callFrame));
- }
+ if (v1.isString() && !v2.isObject())
+ return jsString(callFrame, asString(v1), v2.toString(callFrame));
// All other cases are pretty uncommon
return jsAddSlowCase(callFrame, v1, v2);
diff --git a/Source/JavaScriptCore/runtime/Options.cpp b/Source/JavaScriptCore/runtime/Options.cpp
index 68d10b7bd..ddfba6e7c 100644
--- a/Source/JavaScriptCore/runtime/Options.cpp
+++ b/Source/JavaScriptCore/runtime/Options.cpp
@@ -27,6 +27,7 @@
#include "Options.h"
#include <limits>
+#include <wtf/NumberOfCores.h>
#include <wtf/PageBlock.h>
#if OS(DARWIN) && ENABLE(PARALLEL_GC)
@@ -129,10 +130,10 @@ void setHeuristic(T& variable, const char* name, U value)
void initializeOptions()
{
- SET(maximumOptimizationCandidateInstructionCount, 1000);
+ SET(maximumOptimizationCandidateInstructionCount, 1100);
- SET(maximumFunctionForCallInlineCandidateInstructionCount, 150);
- SET(maximumFunctionForConstructInlineCandidateInstructionCount, 80);
+ SET(maximumFunctionForCallInlineCandidateInstructionCount, 180);
+ SET(maximumFunctionForConstructInlineCandidateInstructionCount, 100);
SET(maximumInliningDepth, 5);
@@ -174,12 +175,8 @@ void initializeOptions()
SET(opaqueRootMergeThreshold, 1000);
int cpusToUse = 1;
-#if OS(DARWIN) && ENABLE(PARALLEL_GC)
- int name[2];
- size_t valueSize = sizeof(cpusToUse);
- name[0] = CTL_HW;
- name[1] = HW_AVAILCPU;
- sysctl(name, 2, &cpusToUse, &valueSize, 0, 0);
+#if ENABLE(PARALLEL_GC)
+ cpusToUse = WTF::numberOfProcessorCores();
#endif
// We don't scale so well beyond 4.
if (cpusToUse > 4)
diff --git a/Source/JavaScriptCore/runtime/Options.h b/Source/JavaScriptCore/runtime/Options.h
index f7cc5f4e8..feebd37bb 100644
--- a/Source/JavaScriptCore/runtime/Options.h
+++ b/Source/JavaScriptCore/runtime/Options.h
@@ -73,8 +73,8 @@ extern unsigned gcMarkStackSegmentSize;
extern unsigned minimumNumberOfCellsToKeep;
extern unsigned maximumNumberOfSharedSegments;
extern unsigned sharedStackWakeupThreshold;
-extern unsigned numberOfGCMarkers;
-extern unsigned opaqueRootMergeThreshold;
+JS_EXPORTDATA extern unsigned numberOfGCMarkers;
+JS_EXPORTDATA extern unsigned opaqueRootMergeThreshold;
void initializeOptions();
diff --git a/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp b/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp
index c664952a5..e3458e4b9 100644
--- a/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp
+++ b/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp
@@ -84,24 +84,31 @@ JSValue PropertyDescriptor::setter() const
return m_setter;
}
+JSObject* PropertyDescriptor::getterObject() const
+{
+ ASSERT(isAccessorDescriptor() && getterPresent());
+ return m_getter.isObject() ? asObject(m_getter) : 0;
+}
+
+JSObject* PropertyDescriptor::setterObject() const
+{
+ ASSERT(isAccessorDescriptor() && setterPresent());
+ return m_setter.isObject() ? asObject(m_setter) : 0;
+}
+
void PropertyDescriptor::setDescriptor(JSValue value, unsigned attributes)
{
ASSERT(value);
+ ASSERT(value.isGetterSetter() == !!(attributes & Accessor));
+
m_attributes = attributes;
if (value.isGetterSetter()) {
- GetterSetter* accessor = asGetterSetter(value);
-
- m_getter = accessor->getter();
- if (m_getter)
- m_attributes |= Getter;
+ m_attributes &= ~ReadOnly; // FIXME: we should be able to ASSERT this!
- m_setter = accessor->setter();
- if (m_setter)
- m_attributes |= Setter;
-
- ASSERT(m_getter || m_setter);
+ GetterSetter* accessor = asGetterSetter(value);
+ m_getter = accessor->getter() ? accessor->getter() : jsUndefined();
+ m_setter = accessor->setter() ? accessor->setter() : jsUndefined();
m_seenAttributes = EnumerablePresent | ConfigurablePresent;
- m_attributes &= ~ReadOnly;
} else {
m_value = value;
m_seenAttributes = EnumerablePresent | ConfigurablePresent | WritablePresent;
@@ -110,14 +117,12 @@ void PropertyDescriptor::setDescriptor(JSValue value, unsigned attributes)
void PropertyDescriptor::setAccessorDescriptor(GetterSetter* accessor, unsigned attributes)
{
- ASSERT(attributes & (Getter | Setter));
- ASSERT(accessor->getter() || accessor->setter());
- ASSERT(!accessor->getter() == !(attributes & Getter));
- ASSERT(!accessor->setter() == !(attributes & Setter));
+ ASSERT(attributes & Accessor);
+ attributes &= ~ReadOnly; // FIXME: we should be able to ASSERT this!
+
m_attributes = attributes;
- m_getter = accessor->getter();
- m_setter = accessor->setter();
- m_attributes &= ~ReadOnly;
+ m_getter = accessor->getter() ? accessor->getter() : jsUndefined();
+ m_setter = accessor->setter() ? accessor->setter() : jsUndefined();
m_seenAttributes = EnumerablePresent | ConfigurablePresent;
}
@@ -151,14 +156,14 @@ void PropertyDescriptor::setConfigurable(bool configurable)
void PropertyDescriptor::setSetter(JSValue setter)
{
m_setter = setter;
- m_attributes |= Setter;
+ m_attributes |= Accessor;
m_attributes &= ~ReadOnly;
}
void PropertyDescriptor::setGetter(JSValue getter)
{
m_getter = getter;
- m_attributes |= Getter;
+ m_attributes |= Accessor;
m_attributes &= ~ReadOnly;
}
@@ -217,6 +222,7 @@ unsigned PropertyDescriptor::attributesWithOverride(const PropertyDescriptor& ot
unsigned PropertyDescriptor::attributesOverridingCurrent(const PropertyDescriptor& current) const
{
+ unsigned currentAttributes = current.m_attributes;
unsigned overrideMask = 0;
if (writablePresent())
overrideMask |= ReadOnly;
@@ -225,8 +231,8 @@ unsigned PropertyDescriptor::attributesOverridingCurrent(const PropertyDescripto
if (configurablePresent())
overrideMask |= DontDelete;
if (isAccessorDescriptor())
- overrideMask |= (Getter | Setter);
- return (m_attributes & overrideMask) | (current.m_attributes & ~overrideMask);
+ overrideMask |= Accessor;
+ return (m_attributes & overrideMask) | (currentAttributes & ~overrideMask);
}
}
diff --git a/Source/JavaScriptCore/runtime/PropertyDescriptor.h b/Source/JavaScriptCore/runtime/PropertyDescriptor.h
index 3d481b25e..98af02e66 100644
--- a/Source/JavaScriptCore/runtime/PropertyDescriptor.h
+++ b/Source/JavaScriptCore/runtime/PropertyDescriptor.h
@@ -41,25 +41,27 @@ namespace JSC {
, m_seenAttributes(0)
{
}
- bool writable() const;
- bool enumerable() const;
- bool configurable() const;
- bool isDataDescriptor() const;
+ JS_EXPORT_PRIVATE bool writable() const;
+ JS_EXPORT_PRIVATE bool enumerable() const;
+ JS_EXPORT_PRIVATE bool configurable() const;
+ JS_EXPORT_PRIVATE bool isDataDescriptor() const;
bool isGenericDescriptor() const;
- bool isAccessorDescriptor() const;
+ JS_EXPORT_PRIVATE bool isAccessorDescriptor() const;
unsigned attributes() const { return m_attributes; }
JSValue value() const { return m_value; }
- JSValue getter() const;
- JSValue setter() const;
- void setUndefined();
- void setDescriptor(JSValue value, unsigned attributes);
+ JS_EXPORT_PRIVATE JSValue getter() const;
+ JS_EXPORT_PRIVATE JSValue setter() const;
+ JSObject* getterObject() const;
+ JSObject* setterObject() const;
+ JS_EXPORT_PRIVATE void setUndefined();
+ JS_EXPORT_PRIVATE void setDescriptor(JSValue value, unsigned attributes);
void setAccessorDescriptor(GetterSetter* accessor, unsigned attributes);
- void setWritable(bool);
- void setEnumerable(bool);
- void setConfigurable(bool);
+ JS_EXPORT_PRIVATE void setWritable(bool);
+ JS_EXPORT_PRIVATE void setEnumerable(bool);
+ JS_EXPORT_PRIVATE void setConfigurable(bool);
void setValue(JSValue value) { m_value = value; }
- void setSetter(JSValue);
- void setGetter(JSValue);
+ JS_EXPORT_PRIVATE void setSetter(JSValue);
+ JS_EXPORT_PRIVATE void setGetter(JSValue);
bool isEmpty() const { return !(m_value || m_getter || m_setter || m_seenAttributes); }
bool writablePresent() const { return m_seenAttributes & WritablePresent; }
bool enumerablePresent() const { return m_seenAttributes & EnumerablePresent; }
@@ -72,7 +74,7 @@ namespace JSC {
unsigned attributesOverridingCurrent(const PropertyDescriptor& current) const;
private:
- static unsigned defaultAttributes;
+ JS_EXPORTDATA static unsigned defaultAttributes;
bool operator==(const PropertyDescriptor&){ return false; }
enum { WritablePresent = 1, EnumerablePresent = 2, ConfigurablePresent = 4};
// May be a getter/setter
diff --git a/Source/JavaScriptCore/runtime/PropertyNameArray.h b/Source/JavaScriptCore/runtime/PropertyNameArray.h
index 0da930f17..dabda945b 100644
--- a/Source/JavaScriptCore/runtime/PropertyNameArray.h
+++ b/Source/JavaScriptCore/runtime/PropertyNameArray.h
@@ -69,7 +69,7 @@ namespace JSC {
JSGlobalData* globalData() { return m_globalData; }
void add(const Identifier& identifier) { add(identifier.impl()); }
- void add(StringImpl*);
+ JS_EXPORT_PRIVATE void add(StringImpl*);
void addKnownUnique(StringImpl* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); }
Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; }
diff --git a/Source/JavaScriptCore/runtime/PropertySlot.h b/Source/JavaScriptCore/runtime/PropertySlot.h
index 8557e6d24..cfedf7876 100644
--- a/Source/JavaScriptCore/runtime/PropertySlot.h
+++ b/Source/JavaScriptCore/runtime/PropertySlot.h
@@ -218,7 +218,7 @@ namespace JSC {
return m_getValue;
}
private:
- JSValue functionGetter(ExecState*) const;
+ JS_EXPORT_PRIVATE JSValue functionGetter(ExecState*) const;
GetValueFunc m_getValue;
GetIndexValueFunc m_getIndexValue;
diff --git a/Source/JavaScriptCore/runtime/RegExp.cpp b/Source/JavaScriptCore/runtime/RegExp.cpp
index 0d513d2cc..69bca5df0 100644
--- a/Source/JavaScriptCore/runtime/RegExp.cpp
+++ b/Source/JavaScriptCore/runtime/RegExp.cpp
@@ -330,68 +330,52 @@ void RegExp::compileIfNecessary(JSGlobalData& globalData, Yarr::YarrCharSize cha
compile(&globalData, charSize);
}
-
-int RegExp::match(JSGlobalData& globalData, const UString& s, int startOffset, Vector<int, 32>* ovector)
+int RegExp::match(JSGlobalData& globalData, const UString& s, unsigned startOffset, Vector<int, 32>* ovector)
{
- if (startOffset < 0)
- startOffset = 0;
-
#if ENABLE(REGEXP_TRACING)
m_rtMatchCallCount++;
#endif
- if (static_cast<unsigned>(startOffset) > s.length() || s.isNull())
- return -1;
-
- if (m_state != ParseError) {
- compileIfNecessary(globalData, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
-
- int offsetVectorSize = (m_numSubpatterns + 1) * 2;
- int* offsetVector;
- Vector<int, 32> nonReturnedOvector;
- if (ovector) {
- ovector->resize(offsetVectorSize);
- offsetVector = ovector->data();
- } else {
- nonReturnedOvector.resize(offsetVectorSize);
- offsetVector = nonReturnedOvector.data();
- }
+ ASSERT(m_state != ParseError);
+ compileIfNecessary(globalData, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
- ASSERT(offsetVector);
- // Initialize offsetVector with the return value (index 0) and the
- // first subpattern start indicies (even index values) set to -1.
- // No need to init the subpattern end indicies.
- for (unsigned j = 0, i = 0; i < m_numSubpatterns + 1; j += 2, i++)
- offsetVector[j] = -1;
+ int offsetVectorSize = (m_numSubpatterns + 1) * 2;
+ int* offsetVector;
+ Vector<int, 32> nonReturnedOvector;
+ if (ovector) {
+ ovector->resize(offsetVectorSize);
+ offsetVector = ovector->data();
+ } else {
+ nonReturnedOvector.resize(offsetVectorSize);
+ offsetVector = nonReturnedOvector.data();
+ }
+ ASSERT(offsetVector);
- int result;
+ int result;
#if ENABLE(YARR_JIT)
- if (m_state == JITCode) {
- if (s.is8Bit())
- result = Yarr::execute(m_representation->m_regExpJITCode, s.characters8(), startOffset, s.length(), offsetVector);
- else
- result = Yarr::execute(m_representation->m_regExpJITCode, s.characters16(), startOffset, s.length(), offsetVector);
+ if (m_state == JITCode) {
+ if (s.is8Bit())
+ result = Yarr::execute(m_representation->m_regExpJITCode, s.characters8(), startOffset, s.length(), offsetVector);
+ else
+ result = Yarr::execute(m_representation->m_regExpJITCode, s.characters16(), startOffset, s.length(), offsetVector);
#if ENABLE(YARR_JIT_DEBUG)
- matchCompareWithInterpreter(s, startOffset, offsetVector, result);
+ matchCompareWithInterpreter(s, startOffset, offsetVector, result);
#endif
- } else
+ } else
#endif
- result = Yarr::interpret(m_representation->m_regExpBytecode.get(), s, startOffset, s.length(), offsetVector);
- ASSERT(result >= -1);
+ result = Yarr::interpret(m_representation->m_regExpBytecode.get(), s, startOffset, s.length(), offsetVector);
+ ASSERT(result >= -1);
#if REGEXP_FUNC_TEST_DATA_GEN
- RegExpFunctionalTestCollector::get()->outputOneTest(this, s, startOffset, offsetVector, result);
+ RegExpFunctionalTestCollector::get()->outputOneTest(this, s, startOffset, offsetVector, result);
#endif
#if ENABLE(REGEXP_TRACING)
- if (result != -1)
- m_rtMatchFoundCount++;
+ if (result != -1)
+ m_rtMatchFoundCount++;
#endif
- return result;
- }
-
- return -1;
+ return result;
}
void RegExp::invalidateCode()
diff --git a/Source/JavaScriptCore/runtime/RegExp.h b/Source/JavaScriptCore/runtime/RegExp.h
index 65eb48499..d0201cbfb 100644
--- a/Source/JavaScriptCore/runtime/RegExp.h
+++ b/Source/JavaScriptCore/runtime/RegExp.h
@@ -35,13 +35,13 @@ namespace JSC {
struct RegExpRepresentation;
class JSGlobalData;
- RegExpFlags regExpFlags(const UString&);
+ JS_EXPORT_PRIVATE RegExpFlags regExpFlags(const UString&);
class RegExp : public JSCell {
public:
typedef JSCell Base;
- static RegExp* create(JSGlobalData&, const UString& pattern, RegExpFlags);
+ JS_EXPORT_PRIVATE static RegExp* create(JSGlobalData&, const UString& pattern, RegExpFlags);
static void destroy(JSCell*);
bool global() const { return m_flags & FlagGlobal; }
@@ -53,7 +53,7 @@ namespace JSC {
bool isValid() const { return !m_constructionError && m_flags != InvalidFlags; }
const char* errorMessage() const { return m_constructionError; }
- int match(JSGlobalData&, const UString&, int startOffset, Vector<int, 32>* ovector = 0);
+ JS_EXPORT_PRIVATE int match(JSGlobalData&, const UString&, unsigned startOffset, Vector<int, 32>* ovector = 0);
unsigned numSubpatterns() const { return m_numSubpatterns; }
bool hasCode()
@@ -72,7 +72,7 @@ namespace JSC {
return Structure::create(globalData, globalObject, prototype, TypeInfo(LeafType, 0), &s_info);
}
- static JS_EXPORTDATA const ClassInfo s_info;
+ static const ClassInfo s_info;
RegExpKey key() { return RegExpKey(m_flags, m_patternString); }
diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
index 05832ed0c..53e880e70 100644
--- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
@@ -97,9 +97,18 @@ const ClassInfo RegExpMatchesArray::s_info = {"Array", &JSArray::s_info, 0, 0, C
@end
*/
+RegExpResult& RegExpResult::operator=(const RegExpConstructorPrivate& rhs)
+{
+ this->input = rhs.input;
+ this->ovector = rhs.lastOvector();
+ this->lastNumSubPatterns = rhs.lastNumSubPatterns;
+
+ return *this;
+}
+
+
RegExpConstructor::RegExpConstructor(JSGlobalObject* globalObject, Structure* structure)
: InternalFunction(globalObject, structure)
- , d(adoptPtr(new RegExpConstructorPrivate))
{
}
@@ -122,27 +131,14 @@ void RegExpConstructor::destroy(JSCell* cell)
RegExpMatchesArray::RegExpMatchesArray(ExecState* exec)
: JSArray(exec->globalData(), exec->lexicalGlobalObject()->regExpMatchesArrayStructure())
+ , m_didFillArrayInstance(false)
{
}
-void RegExpMatchesArray::finishCreation(JSGlobalData& globalData, RegExpConstructorPrivate* data)
+void RegExpMatchesArray::finishCreation(JSGlobalData& globalData, const RegExpConstructorPrivate& data)
{
- Base::finishCreation(globalData, data->lastNumSubPatterns + 1);
- RegExpConstructorPrivate* d = new RegExpConstructorPrivate;
- d->input = data->lastInput;
- d->lastInput = data->lastInput;
- d->lastNumSubPatterns = data->lastNumSubPatterns;
- unsigned offsetVectorSize = (data->lastNumSubPatterns + 1) * 2; // only copying the result part of the vector
- d->lastOvector().resize(offsetVectorSize);
- memcpy(d->lastOvector().data(), data->lastOvector().data(), offsetVectorSize * sizeof(int));
- // d->multiline is not needed, and remains uninitialized
-
- setSubclassData(d);
-}
-
-RegExpMatchesArray::~RegExpMatchesArray()
-{
- delete static_cast<RegExpConstructorPrivate*>(subclassData());
+ Base::finishCreation(globalData, data.lastNumSubPatterns + 1);
+ m_regExpResult = data;
}
void RegExpMatchesArray::destroy(JSCell* cell)
@@ -152,65 +148,61 @@ void RegExpMatchesArray::destroy(JSCell* cell)
void RegExpMatchesArray::fillArrayInstance(ExecState* exec)
{
- RegExpConstructorPrivate* d = static_cast<RegExpConstructorPrivate*>(subclassData());
- ASSERT(d);
-
- unsigned lastNumSubpatterns = d->lastNumSubPatterns;
+ unsigned lastNumSubpatterns = m_regExpResult.lastNumSubPatterns;
for (unsigned i = 0; i <= lastNumSubpatterns; ++i) {
- int start = d->lastOvector()[2 * i];
+ int start = m_regExpResult.ovector[2 * i];
if (start >= 0)
- JSArray::putByIndex(this, exec, i, jsSubstring(exec, d->lastInput, start, d->lastOvector()[2 * i + 1] - start));
+ JSArray::putByIndex(this, exec, i, jsSubstring(exec, m_regExpResult.input, start, m_regExpResult.ovector[2 * i + 1] - start));
else
JSArray::putByIndex(this, exec, i, jsUndefined());
}
PutPropertySlot slot;
- JSArray::put(this, exec, exec->propertyNames().index, jsNumber(d->lastOvector()[0]), slot);
- JSArray::put(this, exec, exec->propertyNames().input, jsString(exec, d->input), slot);
+ JSArray::put(this, exec, exec->propertyNames().index, jsNumber(m_regExpResult.ovector[0]), slot);
+ JSArray::put(this, exec, exec->propertyNames().input, jsString(exec, m_regExpResult.input), slot);
- delete d;
- setSubclassData(0);
+ m_didFillArrayInstance = true;
}
JSObject* RegExpConstructor::arrayOfMatches(ExecState* exec) const
{
- return RegExpMatchesArray::create(exec, d.get());
+ return RegExpMatchesArray::create(exec, d);
}
JSValue RegExpConstructor::getBackref(ExecState* exec, unsigned i) const
{
- if (!d->lastOvector().isEmpty() && i <= d->lastNumSubPatterns) {
- int start = d->lastOvector()[2 * i];
+ if (!d.lastOvector().isEmpty() && i <= d.lastNumSubPatterns) {
+ int start = d.lastOvector()[2 * i];
if (start >= 0)
- return jsSubstring(exec, d->lastInput, start, d->lastOvector()[2 * i + 1] - start);
+ return jsSubstring(exec, d.lastInput, start, d.lastOvector()[2 * i + 1] - start);
}
return jsEmptyString(exec);
}
JSValue RegExpConstructor::getLastParen(ExecState* exec) const
{
- unsigned i = d->lastNumSubPatterns;
+ unsigned i = d.lastNumSubPatterns;
if (i > 0) {
- ASSERT(!d->lastOvector().isEmpty());
- int start = d->lastOvector()[2 * i];
+ ASSERT(!d.lastOvector().isEmpty());
+ int start = d.lastOvector()[2 * i];
if (start >= 0)
- return jsSubstring(exec, d->lastInput, start, d->lastOvector()[2 * i + 1] - start);
+ return jsSubstring(exec, d.lastInput, start, d.lastOvector()[2 * i + 1] - start);
}
return jsEmptyString(exec);
}
JSValue RegExpConstructor::getLeftContext(ExecState* exec) const
{
- if (!d->lastOvector().isEmpty())
- return jsSubstring(exec, d->lastInput, 0, d->lastOvector()[0]);
+ if (!d.lastOvector().isEmpty())
+ return jsSubstring(exec, d.lastInput, 0, d.lastOvector()[0]);
return jsEmptyString(exec);
}
JSValue RegExpConstructor::getRightContext(ExecState* exec) const
{
- if (!d->lastOvector().isEmpty())
- return jsSubstring(exec, d->lastInput, d->lastOvector()[1], d->lastInput.length() - d->lastOvector()[1]);
+ if (!d.lastOvector().isEmpty())
+ return jsSubstring(exec, d.lastInput, d.lastOvector()[1], d.lastInput.length() - d.lastOvector()[1]);
return jsEmptyString(exec);
}
@@ -306,7 +298,7 @@ void RegExpConstructor::put(JSCell* cell, ExecState* exec, const Identifier& pro
void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, JSValue value)
{
- asRegExpConstructor(baseObject)->setInput(value.toString(exec));
+ asRegExpConstructor(baseObject)->setInput(value.toString(exec)->value(exec));
}
void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValue value)
@@ -331,13 +323,13 @@ JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const A
return asObject(arg0);
}
- UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec);
+ UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec)->value(exec);
if (exec->hadException())
return 0;
RegExpFlags flags = NoFlags;
if (!arg1.isUndefined()) {
- flags = regExpFlags(arg1.toString(exec));
+ flags = regExpFlags(arg1.toString(exec)->value(exec));
if (exec->hadException())
return 0;
if (flags == InvalidFlags)
@@ -377,24 +369,24 @@ CallType RegExpConstructor::getCallData(JSCell*, CallData& callData)
void RegExpConstructor::setInput(const UString& input)
{
- d->input = input;
+ d.input = input;
}
const UString& RegExpConstructor::input() const
{
// Can detect a distinct initial state that is invisible to JavaScript, by checking for null
// state (since jsString turns null strings to empty strings).
- return d->input;
+ return d.input;
}
void RegExpConstructor::setMultiline(bool multiline)
{
- d->multiline = multiline;
+ d.multiline = multiline;
}
bool RegExpConstructor::multiline() const
{
- return d->multiline;
+ return d.multiline;
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.h b/Source/JavaScriptCore/runtime/RegExpConstructor.h
index 0a43da70a..08a96b544 100644
--- a/Source/JavaScriptCore/runtime/RegExpConstructor.h
+++ b/Source/JavaScriptCore/runtime/RegExpConstructor.h
@@ -55,6 +55,21 @@ namespace JSC {
unsigned lastOvectorIndex : 1;
};
+ struct RegExpResult {
+ WTF_MAKE_FAST_ALLOCATED;
+ public:
+ RegExpResult()
+ : lastNumSubPatterns(0)
+ {
+ }
+
+ RegExpResult& operator=(const RegExpConstructorPrivate&);
+
+ UString input;
+ unsigned lastNumSubPatterns;
+ Vector<int, 32> ovector;
+ };
+
class RegExpConstructor : public InternalFunction {
public:
typedef InternalFunction Base;
@@ -102,7 +117,7 @@ namespace JSC {
static ConstructType getConstructData(JSCell*, ConstructData&);
static CallType getCallData(JSCell*, CallData&);
- OwnPtr<RegExpConstructorPrivate> d;
+ RegExpConstructorPrivate d;
};
RegExpConstructor* asRegExpConstructor(JSValue);
@@ -122,20 +137,20 @@ namespace JSC {
*/
ALWAYS_INLINE void RegExpConstructor::performMatch(JSGlobalData& globalData, RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector)
{
- position = r->match(globalData, s, startOffset, &d->tempOvector());
+ position = r->match(globalData, s, startOffset, &d.tempOvector());
if (ovector)
- *ovector = d->tempOvector().data();
+ *ovector = d.tempOvector().data();
if (position != -1) {
- ASSERT(!d->tempOvector().isEmpty());
+ ASSERT(!d.tempOvector().isEmpty());
- length = d->tempOvector()[1] - d->tempOvector()[0];
+ length = d.tempOvector()[1] - d.tempOvector()[0];
- d->input = s;
- d->lastInput = s;
- d->changeLastOvector();
- d->lastNumSubPatterns = r->numSubpatterns();
+ d.input = s;
+ d.lastInput = s;
+ d.changeLastOvector();
+ d.lastNumSubPatterns = r->numSubpatterns();
}
}
diff --git a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h b/Source/JavaScriptCore/runtime/RegExpMatchesArray.h
index a0a8a8e98..c34920d8d 100644
--- a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h
+++ b/Source/JavaScriptCore/runtime/RegExpMatchesArray.h
@@ -31,30 +31,29 @@ namespace JSC {
public:
typedef JSArray Base;
- static RegExpMatchesArray* create(ExecState* exec, RegExpConstructorPrivate* ctorPrivate)
+ static RegExpMatchesArray* create(ExecState* exec, const RegExpConstructorPrivate& ctorPrivate)
{
RegExpMatchesArray* regExp = new (NotNull, allocateCell<RegExpMatchesArray>(*exec->heap())) RegExpMatchesArray(exec);
regExp->finishCreation(exec->globalData(), ctorPrivate);
return regExp;
}
- ~RegExpMatchesArray();
static void destroy(JSCell*);
- static JS_EXPORTDATA const ClassInfo s_info;
-
+ static const ClassInfo s_info;
+
static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
{
return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
}
-
+
protected:
- void finishCreation(JSGlobalData&, RegExpConstructorPrivate* data);
+ void finishCreation(JSGlobalData&, const RegExpConstructorPrivate& data);
private:
static bool getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell);
- if (thisObject->subclassData())
+ if (!thisObject->m_didFillArrayInstance)
thisObject->fillArrayInstance(exec);
return JSArray::getOwnPropertySlot(thisObject, exec, propertyName, slot);
}
@@ -62,7 +61,7 @@ namespace JSC {
static bool getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, PropertySlot& slot)
{
RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell);
- if (thisObject->subclassData())
+ if (!thisObject->m_didFillArrayInstance)
thisObject->fillArrayInstance(exec);
return JSArray::getOwnPropertySlotByIndex(thisObject, exec, propertyName, slot);
}
@@ -70,7 +69,7 @@ namespace JSC {
static bool getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(object);
- if (thisObject->subclassData())
+ if (!thisObject->m_didFillArrayInstance)
thisObject->fillArrayInstance(exec);
return JSArray::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
}
@@ -78,7 +77,7 @@ namespace JSC {
static void put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue v, PutPropertySlot& slot)
{
RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell);
- if (thisObject->subclassData())
+ if (!thisObject->m_didFillArrayInstance)
thisObject->fillArrayInstance(exec);
JSArray::put(thisObject, exec, propertyName, v, slot);
}
@@ -86,7 +85,7 @@ namespace JSC {
static void putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue v)
{
RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell);
- if (thisObject->subclassData())
+ if (!thisObject->m_didFillArrayInstance)
thisObject->fillArrayInstance(exec);
JSArray::putByIndex(thisObject, exec, propertyName, v);
}
@@ -94,7 +93,7 @@ namespace JSC {
static bool deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
{
RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell);
- if (thisObject->subclassData())
+ if (!thisObject->m_didFillArrayInstance)
thisObject->fillArrayInstance(exec);
return JSArray::deleteProperty(thisObject, exec, propertyName);
}
@@ -102,7 +101,7 @@ namespace JSC {
static bool deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned propertyName)
{
RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell);
- if (thisObject->subclassData())
+ if (!thisObject->m_didFillArrayInstance)
thisObject->fillArrayInstance(exec);
return JSArray::deletePropertyByIndex(thisObject, exec, propertyName);
}
@@ -110,12 +109,15 @@ namespace JSC {
static void getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& arr, EnumerationMode mode = ExcludeDontEnumProperties)
{
RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(object);
- if (thisObject->subclassData())
+ if (!thisObject->m_didFillArrayInstance)
thisObject->fillArrayInstance(exec);
JSArray::getOwnPropertyNames(thisObject, exec, arr, mode);
}
void fillArrayInstance(ExecState*);
+
+ RegExpResult m_regExpResult;
+ bool m_didFillArrayInstance;
};
}
diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp
index 4553f7ad0..4c192ff90 100644
--- a/Source/JavaScriptCore/runtime/RegExpObject.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp
@@ -231,7 +231,7 @@ JSValue RegExpObject::exec(ExecState* exec)
bool RegExpObject::match(ExecState* exec)
{
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
- UString input = exec->argument(0).toString(exec);
+ UString input = exec->argument(0).toString(exec)->value(exec);
JSGlobalData* globalData = &exec->globalData();
if (!regExp()->global()) {
int position;
diff --git a/Source/JavaScriptCore/runtime/RegExpObject.h b/Source/JavaScriptCore/runtime/RegExpObject.h
index 4e84d3831..081a7f111 100644
--- a/Source/JavaScriptCore/runtime/RegExpObject.h
+++ b/Source/JavaScriptCore/runtime/RegExpObject.h
@@ -75,8 +75,8 @@ namespace JSC {
}
protected:
- RegExpObject(JSGlobalObject*, Structure*, RegExp*);
- void finishCreation(JSGlobalObject*);
+ JS_EXPORT_PRIVATE RegExpObject(JSGlobalObject*, Structure*, RegExp*);
+ JS_EXPORT_PRIVATE void finishCreation(JSGlobalObject*);
static void destroy(JSCell*);
static const unsigned StructureFlags = OverridesVisitChildren | OverridesGetOwnPropertySlot | Base::StructureFlags;
diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
index 6c79f9428..9074e97c3 100644
--- a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
@@ -110,13 +110,13 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec)
return throwVMError(exec, createTypeError(exec, "Cannot supply flags when constructing one RegExp from another."));
regExp = asRegExpObject(arg0)->regExp();
} else {
- UString pattern = !exec->argumentCount() ? UString("") : arg0.toString(exec);
+ UString pattern = !exec->argumentCount() ? UString("") : arg0.toString(exec)->value(exec);
if (exec->hadException())
return JSValue::encode(jsUndefined());
RegExpFlags flags = NoFlags;
if (!arg1.isUndefined()) {
- flags = regExpFlags(arg1.toString(exec));
+ flags = regExpFlags(arg1.toString(exec)->value(exec));
if (exec->hadException())
return JSValue::encode(jsUndefined());
if (flags == InvalidFlags)
@@ -153,7 +153,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec)
postfix[index++] = 'i';
if (thisObject->get(exec, exec->propertyNames().multiline).toBoolean(exec))
postfix[index] = 'm';
- UString source = thisObject->get(exec, exec->propertyNames().source).toString(exec);
+ UString source = thisObject->get(exec, exec->propertyNames().source).toString(exec)->value(exec);
// If source is empty, use "/(?:)/" to avoid colliding with comment syntax
return JSValue::encode(jsMakeNontrivialString(exec, "/", source.length() ? source : UString("(?:)"), postfix));
}
diff --git a/Source/JavaScriptCore/runtime/SamplingCounter.h b/Source/JavaScriptCore/runtime/SamplingCounter.h
index 664b0280e..329a5cfd3 100644
--- a/Source/JavaScriptCore/runtime/SamplingCounter.h
+++ b/Source/JavaScriptCore/runtime/SamplingCounter.h
@@ -46,7 +46,7 @@ public:
m_counter += count;
}
- static void dump();
+ JS_EXPORT_PRIVATE static void dump();
int64_t* addressOfCounter() { return &m_counter; }
@@ -74,7 +74,7 @@ protected:
AbstractSamplingCounter** m_referer;
// Null object used to detect end of static chain.
static AbstractSamplingCounter s_abstractSamplingCounterChainEnd;
- static AbstractSamplingCounter* s_abstractSamplingCounterChain;
+ JS_EXPORTDATA static AbstractSamplingCounter* s_abstractSamplingCounterChain;
static bool s_completed;
};
diff --git a/Source/JavaScriptCore/runtime/SmallStrings.h b/Source/JavaScriptCore/runtime/SmallStrings.h
index 9c6ed9a32..cd8e63095 100644
--- a/Source/JavaScriptCore/runtime/SmallStrings.h
+++ b/Source/JavaScriptCore/runtime/SmallStrings.h
@@ -60,7 +60,7 @@ namespace JSC {
return m_singleCharacterStrings[character];
}
- StringImpl* singleCharacterStringRep(unsigned char character);
+ JS_EXPORT_PRIVATE StringImpl* singleCharacterStringRep(unsigned char character);
void finalizeSmallStrings();
void clear();
@@ -72,8 +72,8 @@ namespace JSC {
private:
static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1;
- void createEmptyString(JSGlobalData*);
- void createSingleCharacterString(JSGlobalData*, unsigned char);
+ JS_EXPORT_PRIVATE void createEmptyString(JSGlobalData*);
+ JS_EXPORT_PRIVATE void createSingleCharacterString(JSGlobalData*, unsigned char);
JSString* m_emptyString;
JSString* m_singleCharacterStrings[singleCharacterStringCount];
diff --git a/Source/JavaScriptCore/runtime/StringConstructor.cpp b/Source/JavaScriptCore/runtime/StringConstructor.cpp
index d2f75a060..e03a87f03 100644
--- a/Source/JavaScriptCore/runtime/StringConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/StringConstructor.cpp
@@ -95,10 +95,7 @@ static EncodedJSValue JSC_HOST_CALL constructWithStringConstructor(ExecState* ex
if (!exec->argumentCount())
return JSValue::encode(StringObject::create(exec, globalObject->stringObjectStructure()));
- JSString* string = exec->argument(0).isString()
- ? asString(exec->argument(0))
- : jsString(exec, exec->argument(0).toString(exec));
- return JSValue::encode(StringObject::create(exec, globalObject->stringObjectStructure(), string));
+ return JSValue::encode(StringObject::create(exec, globalObject->stringObjectStructure(), exec->argument(0).toString(exec)));
}
ConstructType StringConstructor::getConstructData(JSCell*, ConstructData& constructData)
@@ -111,7 +108,7 @@ static EncodedJSValue JSC_HOST_CALL callStringConstructor(ExecState* exec)
{
if (!exec->argumentCount())
return JSValue::encode(jsEmptyString(exec));
- return JSValue::encode(jsString(exec, exec->argument(0).toString(exec)));
+ return JSValue::encode(exec->argument(0).toString(exec));
}
CallType StringConstructor::getCallData(JSCell*, CallData& callData)
diff --git a/Source/JavaScriptCore/runtime/StringObject.h b/Source/JavaScriptCore/runtime/StringObject.h
index 528668691..248c71601 100644
--- a/Source/JavaScriptCore/runtime/StringObject.h
+++ b/Source/JavaScriptCore/runtime/StringObject.h
@@ -64,9 +64,9 @@ namespace JSC {
}
protected:
- void finishCreation(JSGlobalData&, JSString*);
+ JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, JSString*);
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSWrapperObject::StructureFlags;
- StringObject(JSGlobalData&, Structure*);
+ JS_EXPORT_PRIVATE StringObject(JSGlobalData&, Structure*);
};
StringObject* asStringObject(JSValue);
diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp
index 740916a69..63c00e27e 100644
--- a/Source/JavaScriptCore/runtime/StringPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp
@@ -170,9 +170,10 @@ static inline JSString* jsStringWithReuse(ExecState* exec, JSValue originalValue
return jsString(exec, string);
}
+template <typename CharType>
static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacement, const UString& source, const int* ovector, RegExp* reg, size_t i)
{
- Vector<UChar> substitutedReplacement;
+ Vector<CharType> substitutedReplacement;
int offset = 0;
do {
if (i + 1 == replacement.length())
@@ -182,7 +183,7 @@ static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacem
if (ref == '$') {
// "$$" -> "$"
++i;
- substitutedReplacement.append(replacement.characters() + offset, i - offset);
+ substitutedReplacement.append(replacement.getCharacters<CharType>() + offset, i - offset);
offset = i + 1;
continue;
}
@@ -222,15 +223,15 @@ static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacem
continue;
if (i - offset)
- substitutedReplacement.append(replacement.characters() + offset, i - offset);
+ substitutedReplacement.append(replacement.getCharacters<CharType>() + offset, i - offset);
i += 1 + advance;
offset = i + 1;
if (backrefStart >= 0)
- substitutedReplacement.append(source.characters() + backrefStart, backrefLength);
+ substitutedReplacement.append(source.getCharacters<CharType>() + backrefStart, backrefLength);
} while ((i = replacement.find('$', i + 1)) != notFound);
if (replacement.length() - offset)
- substitutedReplacement.append(replacement.characters() + offset, replacement.length() - offset);
+ substitutedReplacement.append(replacement.getCharacters<CharType>() + offset, replacement.length() - offset);
substitutedReplacement.shrinkToFit();
return UString::adopt(substitutedReplacement);
@@ -239,8 +240,11 @@ static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacem
static inline UString substituteBackreferences(const UString& replacement, const UString& source, const int* ovector, RegExp* reg)
{
size_t i = replacement.find('$', 0);
- if (UNLIKELY(i != notFound))
- return substituteBackreferencesSlow(replacement, source, ovector, reg, i);
+ if (UNLIKELY(i != notFound)) {
+ if (replacement.is8Bit() && source.is8Bit())
+ return substituteBackreferencesSlow<LChar>(replacement, source, ovector, reg, i);
+ return substituteBackreferencesSlow<UChar>(replacement, source, ovector, reg, i);
+ }
return replacement;
}
@@ -398,13 +402,54 @@ static ALWAYS_INLINE JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, J
return jsString(exec, impl.release());
}
+static NEVER_INLINE EncodedJSValue removeUsingRegExpSearch(ExecState* exec, JSString* string, const UString& source, RegExp* regExp)
+{
+ int lastIndex = 0;
+ unsigned startPosition = 0;
+
+ Vector<StringRange, 16> sourceRanges;
+ JSGlobalData* globalData = &exec->globalData();
+ RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
+ unsigned sourceLen = source.length();
+
+ while (true) {
+ int matchIndex;
+ int matchLen = 0;
+ int* ovector;
+ regExpConstructor->performMatch(*globalData, regExp, source, startPosition, matchIndex, matchLen, &ovector);
+ if (matchIndex < 0)
+ break;
+
+ if (lastIndex < matchIndex)
+ sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex));
+
+ lastIndex = matchIndex + matchLen;
+ startPosition = lastIndex;
+
+ // special case of empty match
+ if (!matchLen) {
+ startPosition++;
+ if (startPosition > sourceLen)
+ break;
+ }
+ }
+
+ if (!lastIndex)
+ return JSValue::encode(string);
+
+ if (static_cast<unsigned>(lastIndex) < sourceLen)
+ sourceRanges.append(StringRange(lastIndex, sourceLen - lastIndex));
+
+ return JSValue::encode(jsSpliceSubstrings(exec, string, source, sourceRanges.data(), sourceRanges.size()));
+}
+
static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSString* string, JSValue searchValue, JSValue replaceValue)
{
UString replacementString;
CallData callData;
CallType callType = getCallData(replaceValue, callData);
if (callType == CallTypeNone)
- replacementString = replaceValue.toString(exec);
+ replacementString = replaceValue.toString(exec)->value(exec);
const UString& source = string->value(exec);
unsigned sourceLen = source.length();
@@ -413,45 +458,10 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS
RegExp* regExp = asRegExpObject(searchValue)->regExp();
bool global = regExp->global();
- RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
-
- // Optimization for substring removal (replace with empty).
- if (global && callType == CallTypeNone && !replacementString.length()) {
- int lastIndex = 0;
- unsigned startPosition = 0;
-
- Vector<StringRange, 16> sourceRanges;
- JSGlobalData* globalData = &exec->globalData();
- while (true) {
- int matchIndex;
- int matchLen = 0;
- int* ovector;
- regExpConstructor->performMatch(*globalData, regExp, source, startPosition, matchIndex, matchLen, &ovector);
- if (matchIndex < 0)
- break;
-
- if (lastIndex < matchIndex)
- sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex));
-
- lastIndex = matchIndex + matchLen;
- startPosition = lastIndex;
-
- // special case of empty match
- if (!matchLen) {
- startPosition++;
- if (startPosition > sourceLen)
- break;
- }
- }
-
- if (!lastIndex)
- return JSValue::encode(string);
-
- if (static_cast<unsigned>(lastIndex) < sourceLen)
- sourceRanges.append(StringRange(lastIndex, sourceLen - lastIndex));
+ if (global && callType == CallTypeNone && !replacementString.length())
+ return removeUsingRegExpSearch(exec, string, source, regExp);
- return JSValue::encode(jsSpliceSubstrings(exec, string, source, sourceRanges.data(), sourceRanges.size()));
- }
+ RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
int lastIndex = 0;
unsigned startPosition = 0;
@@ -496,10 +506,7 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS
cachedCall.setThis(jsUndefined());
JSValue result = cachedCall.call();
- if (LIKELY(result.isString()))
- replacements.append(asString(result)->value(exec));
- else
- replacements.append(result.toString(cachedCall.newCallFrame(exec)));
+ replacements.append(result.toString(cachedCall.newCallFrame(exec))->value(exec));
if (exec->hadException())
break;
@@ -541,10 +548,7 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS
cachedCall.setThis(jsUndefined());
JSValue result = cachedCall.call();
- if (LIKELY(result.isString()))
- replacements.append(asString(result)->value(exec));
- else
- replacements.append(result.toString(cachedCall.newCallFrame(exec)));
+ replacements.append(result.toString(cachedCall.newCallFrame(exec))->value(exec));
if (exec->hadException())
break;
@@ -588,7 +592,7 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS
args.append(jsNumber(completeMatchStart));
args.append(string);
- replacements.append(call(exec, replaceValue, callType, callData, jsUndefined(), args).toString(exec));
+ replacements.append(call(exec, replaceValue, callType, callData, jsUndefined(), args).toString(exec)->value(exec));
if (exec->hadException())
break;
} else {
@@ -627,7 +631,7 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS
static NEVER_INLINE EncodedJSValue replaceUsingStringSearch(ExecState* exec, JSString* jsString, JSValue searchValue, JSValue replaceValue)
{
const UString& string = jsString->value(exec);
- UString searchString = searchValue.toString(exec);
+ UString searchString = searchValue.toString(exec)->value(exec);
if (exec->hadException())
return JSValue::encode(jsUndefined());
@@ -647,7 +651,7 @@ static NEVER_INLINE EncodedJSValue replaceUsingStringSearch(ExecState* exec, JSS
return JSValue::encode(jsUndefined());
}
- UString replaceString = replaceValue.toString(exec);
+ UString replaceString = replaceValue.toString(exec)->value(exec);
if (exec->hadException())
return JSValue::encode(jsUndefined());
@@ -659,12 +663,9 @@ static NEVER_INLINE EncodedJSValue replaceUsingStringSearch(ExecState* exec, JSS
EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (!thisValue.isString()) {
- if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
- return throwVMTypeError(exec);
- thisValue = jsString(exec, thisValue.toString(exec));
- }
- JSString* string = asString(thisValue);
+ if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+ return throwVMTypeError(exec);
+ JSString* string = thisValue.toString(exec);
JSValue searchValue = exec->argument(0);
JSValue replaceValue = exec->argument(1);
@@ -692,7 +693,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
unsigned len = s.length();
JSValue a0 = exec->argument(0);
if (a0.isUInt32()) {
@@ -712,7 +713,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
unsigned len = s.length();
JSValue a0 = exec->argument(0);
if (a0.isUInt32()) {
@@ -733,12 +734,9 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState* exec)
EncodedJSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- if (thisValue.isString() && (exec->argumentCount() == 1)) {
- JSValue v = exec->argument(0);
- return JSValue::encode(v.isString()
- ? jsString(exec, asString(thisValue), asString(v))
- : jsString(exec, asString(thisValue), jsString(&exec->globalData(), v.toString(exec))));
- }
+ if (thisValue.isString() && (exec->argumentCount() == 1))
+ return JSValue::encode(jsString(exec, asString(thisValue), exec->argument(0).toString(exec)));
+
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
return JSValue::encode(jsStringFromArguments(exec, thisValue));
@@ -749,12 +747,12 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
int len = s.length();
JSValue a0 = exec->argument(0);
JSValue a1 = exec->argument(1);
- UString u2 = a0.toString(exec);
+ UString u2 = a0.toString(exec)->value(exec);
int pos;
if (a1.isUndefined())
pos = 0;
@@ -780,13 +778,13 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
int len = s.length();
JSValue a0 = exec->argument(0);
JSValue a1 = exec->argument(1);
- UString u2 = a0.toString(exec);
+ UString u2 = a0.toString(exec)->value(exec);
double dpos = a1.toIntegerPreserveNaN(exec);
if (dpos < 0)
dpos = 0;
@@ -804,7 +802,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
JSGlobalData* globalData = &exec->globalData();
JSValue a0 = exec->argument(0);
@@ -819,7 +817,9 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec)
* replaced with the result of the expression new RegExp(regexp).
* Per ECMA 15.10.4.1, if a0 is undefined substitute the empty string.
*/
- reg = RegExp::create(exec->globalData(), a0.isUndefined() ? UString("") : a0.toString(exec), NoFlags);
+ reg = RegExp::create(exec->globalData(), a0.isUndefined() ? UString("") : a0.toString(exec)->value(exec), NoFlags);
+ if (!reg->isValid())
+ return throwVMError(exec, createSyntaxError(exec, reg->errorMessage()));
}
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
int pos;
@@ -854,7 +854,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
JSGlobalData* globalData = &exec->globalData();
JSValue a0 = exec->argument(0);
@@ -869,7 +869,9 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec)
* replaced with the result of the expression new RegExp(regexp).
* Per ECMA 15.10.4.1, if a0 is undefined substitute the empty string.
*/
- reg = RegExp::create(exec->globalData(), a0.isUndefined() ? UString("") : a0.toString(exec), NoFlags);
+ reg = RegExp::create(exec->globalData(), a0.isUndefined() ? UString("") : a0.toString(exec)->value(exec), NoFlags);
+ if (!reg->isValid())
+ return throwVMError(exec, createSyntaxError(exec, reg->errorMessage()));
}
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
int pos;
@@ -883,7 +885,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
int len = s.length();
JSValue a0 = exec->argument(0);
@@ -915,7 +917,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
// 2. Let S be the result of calling ToString, giving it the this value as its argument.
// 6. Let s be the number of characters in S.
- UString input = thisValue.toString(exec);
+ UString input = thisValue.toString(exec)->value(exec);
// 3. Let A be a new array created as if by the expression new Array()
// where Array is the standard built-in constructor with that name.
@@ -1017,7 +1019,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
}
}
} else {
- UString separator = separatorValue.toString(exec);
+ UString separator = separatorValue.toString(exec)->value(exec);
// 9. If lim == 0, return A.
if (!limit)
@@ -1104,7 +1106,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState* exec)
// CheckObjectCoercible
return throwVMTypeError(exec);
} else {
- uString = thisValue.toString(exec);
+ uString = thisValue.toString(exec)->value(exec);
if (exec->hadException())
return JSValue::encode(jsUndefined());
len = uString.length();
@@ -1134,24 +1136,16 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState* exec)
EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
- int len;
- JSString* jsString = 0;
- UString uString;
- if (thisValue.isString()) {
- jsString = static_cast<JSString*>(thisValue.asCell());
- len = jsString->length();
- } else if (thisValue.isUndefinedOrNull()) {
- // CheckObjectCoercible
+ if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- } else {
- uString = thisValue.toString(exec);
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
- len = uString.length();
- }
+
+ JSString* jsString = thisValue.toString(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
JSValue a0 = exec->argument(0);
JSValue a1 = exec->argument(1);
+ int len = jsString->length();
double start = a0.toNumber(exec);
double end;
@@ -1175,9 +1169,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec)
}
unsigned substringStart = static_cast<unsigned>(start);
unsigned substringLength = static_cast<unsigned>(end) - substringStart;
- if (jsString)
- return JSValue::encode(jsSubstring(exec, jsString, substringStart, substringLength));
- return JSValue::encode(jsSubstring(exec, uString, substringStart, substringLength));
+ return JSValue::encode(jsSubstring(exec, jsString, substringStart, substringLength));
}
EncodedJSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec)
@@ -1185,16 +1177,16 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- JSString* sVal = thisValue.isString() ? asString(thisValue) : jsString(exec, thisValue.toString(exec));
+ JSString* sVal = thisValue.toString(exec);
const UString& s = sVal->value(exec);
int sSize = s.length();
if (!sSize)
return JSValue::encode(sVal);
- StringImpl* ourImpl = s.impl();
+ StringImpl* ourImpl = s.impl();
RefPtr<StringImpl> lower = ourImpl->lower();
- if (ourImpl == lower.get())
+ if (ourImpl == lower)
return JSValue::encode(sVal);
return JSValue::encode(jsString(exec, UString(lower.release())));
}
@@ -1204,39 +1196,18 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- JSString* sVal = thisValue.isString() ? asString(thisValue) : jsString(exec, thisValue.toString(exec));
+ JSString* sVal = thisValue.toString(exec);
const UString& s = sVal->value(exec);
int sSize = s.length();
if (!sSize)
return JSValue::encode(sVal);
- const UChar* sData = s.characters();
- Vector<UChar> buffer(sSize);
-
- UChar ored = 0;
- for (int i = 0; i < sSize; i++) {
- UChar c = sData[i];
- ored |= c;
- buffer[i] = toASCIIUpper(c);
- }
- if (!(ored & ~0x7f))
- return JSValue::encode(jsString(exec, UString::adopt(buffer)));
-
- bool error;
- int length = Unicode::toUpper(buffer.data(), sSize, sData, sSize, &error);
- if (error) {
- buffer.resize(length);
- length = Unicode::toUpper(buffer.data(), length, sData, sSize, &error);
- if (error)
- return JSValue::encode(sVal);
- }
- if (length == sSize) {
- if (memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0)
- return JSValue::encode(sVal);
- } else
- buffer.resize(length);
- return JSValue::encode(jsString(exec, UString::adopt(buffer)));
+ StringImpl* sImpl = s.impl();
+ RefPtr<StringImpl> upper = sImpl->upper();
+ if (sImpl == upper)
+ return JSValue::encode(sVal);
+ return JSValue::encode(jsString(exec, UString(upper.release())));
}
EncodedJSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec)
@@ -1247,10 +1218,10 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
JSValue a0 = exec->argument(0);
- return JSValue::encode(jsNumber(localeCompare(s, a0.toString(exec))));
+ return JSValue::encode(jsNumber(localeCompare(s, a0.toString(exec)->value(exec))));
}
EncodedJSValue JSC_HOST_CALL stringProtoFuncBig(ExecState* exec)
@@ -1258,7 +1229,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncBig(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
return JSValue::encode(jsMakeNontrivialString(exec, "<big>", s, "</big>"));
}
@@ -1267,7 +1238,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
return JSValue::encode(jsMakeNontrivialString(exec, "<small>", s, "</small>"));
}
@@ -1276,7 +1247,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
return JSValue::encode(jsMakeNontrivialString(exec, "<blink>", s, "</blink>"));
}
@@ -1285,7 +1256,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncBold(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
return JSValue::encode(jsMakeNontrivialString(exec, "<b>", s, "</b>"));
}
@@ -1294,7 +1265,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
return JSValue::encode(jsMakeNontrivialString(exec, "<tt>", s, "</tt>"));
}
@@ -1303,7 +1274,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncItalics(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
return JSValue::encode(jsMakeNontrivialString(exec, "<i>", s, "</i>"));
}
@@ -1312,7 +1283,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncStrike(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
return JSValue::encode(jsMakeNontrivialString(exec, "<strike>", s, "</strike>"));
}
@@ -1321,7 +1292,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSub(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
return JSValue::encode(jsMakeNontrivialString(exec, "<sub>", s, "</sub>"));
}
@@ -1330,7 +1301,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSup(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
return JSValue::encode(jsMakeNontrivialString(exec, "<sup>", s, "</sup>"));
}
@@ -1339,9 +1310,9 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
JSValue a0 = exec->argument(0);
- return JSValue::encode(jsMakeNontrivialString(exec, "<font color=\"", a0.toString(exec), "\">", s, "</font>"));
+ return JSValue::encode(jsMakeNontrivialString(exec, "<font color=\"", a0.toString(exec)->value(exec), "\">", s, "</font>"));
}
EncodedJSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec)
@@ -1349,7 +1320,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
JSValue a0 = exec->argument(0);
uint32_t smallInteger;
@@ -1386,7 +1357,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec)
return JSValue::encode(jsNontrivialString(exec, impl));
}
- return JSValue::encode(jsMakeNontrivialString(exec, "<font size=\"", a0.toString(exec), "\">", s, "</font>"));
+ return JSValue::encode(jsMakeNontrivialString(exec, "<font size=\"", a0.toString(exec)->value(exec), "\">", s, "</font>"));
}
EncodedJSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec)
@@ -1394,9 +1365,9 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
JSValue a0 = exec->argument(0);
- return JSValue::encode(jsMakeNontrivialString(exec, "<a name=\"", a0.toString(exec), "\">", s, "</a>"));
+ return JSValue::encode(jsMakeNontrivialString(exec, "<a name=\"", a0.toString(exec)->value(exec), "\">", s, "</a>"));
}
EncodedJSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec)
@@ -1404,9 +1375,9 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec)
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
- UString s = thisValue.toString(exec);
+ UString s = thisValue.toString(exec)->value(exec);
JSValue a0 = exec->argument(0);
- UString linkText = a0.toString(exec);
+ UString linkText = a0.toString(exec)->value(exec);
unsigned linkTextSize = linkText.length();
unsigned stringSize = s.length();
@@ -1449,7 +1420,7 @@ static inline JSValue trimString(ExecState* exec, JSValue thisValue, int trimKin
{
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwTypeError(exec);
- UString str = thisValue.toString(exec);
+ UString str = thisValue.toString(exec)->value(exec);
unsigned left = 0;
if (trimKind & TrimLeft) {
while (left < str.length() && isTrimWhitespace(str[left]))
diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp
index dda8c73e9..f387cf283 100644
--- a/Source/JavaScriptCore/runtime/Structure.cpp
+++ b/Source/JavaScriptCore/runtime/Structure.cpp
@@ -401,17 +401,26 @@ Structure* Structure::despecifyFunctionTransition(JSGlobalData& globalData, Stru
return transition;
}
-Structure* Structure::getterSetterTransition(JSGlobalData& globalData, Structure* structure)
+Structure* Structure::attributeChangeTransition(JSGlobalData& globalData, Structure* structure, const Identifier& propertyName, unsigned attributes)
{
- Structure* transition = create(globalData, structure);
+ if (!structure->isUncacheableDictionary()) {
+ Structure* transition = create(globalData, structure);
- // Don't set m_offset, as one can not transition to this.
+ // Don't set m_offset, as one can not transition to this.
- structure->materializePropertyMapIfNecessary(globalData);
- transition->m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);
- transition->pin();
+ structure->materializePropertyMapIfNecessary(globalData);
+ transition->m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);
+ transition->pin();
+
+ structure = transition;
+ }
- return transition;
+ ASSERT(structure->m_propertyTable);
+ PropertyMapEntry* entry = structure->m_propertyTable->find(propertyName.impl()).first;
+ ASSERT(entry);
+ entry->attributes = attributes;
+
+ return structure;
}
Structure* Structure::toDictionaryTransition(JSGlobalData& globalData, Structure* structure, DictionaryKind kind)
diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h
index 70e968014..ced296856 100644
--- a/Source/JavaScriptCore/runtime/Structure.h
+++ b/Source/JavaScriptCore/runtime/Structure.h
@@ -84,12 +84,12 @@ namespace JSC {
public:
static void dumpStatistics();
- static Structure* addPropertyTransition(JSGlobalData&, Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
- static Structure* addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
+ JS_EXPORT_PRIVATE static Structure* addPropertyTransition(JSGlobalData&, Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
+ JS_EXPORT_PRIVATE static Structure* addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
static Structure* removePropertyTransition(JSGlobalData&, Structure*, const Identifier& propertyName, size_t& offset);
- static Structure* changePrototypeTransition(JSGlobalData&, Structure*, JSValue prototype);
- static Structure* despecifyFunctionTransition(JSGlobalData&, Structure*, const Identifier&);
- static Structure* getterSetterTransition(JSGlobalData&, Structure*);
+ JS_EXPORT_PRIVATE static Structure* changePrototypeTransition(JSGlobalData&, Structure*, JSValue prototype);
+ JS_EXPORT_PRIVATE static Structure* despecifyFunctionTransition(JSGlobalData&, Structure*, const Identifier&);
+ static Structure* attributeChangeTransition(JSGlobalData&, Structure*, const Identifier& propertyName, unsigned attributes);
static Structure* toCacheableDictionaryTransition(JSGlobalData&, Structure*);
static Structure* toUncacheableDictionaryTransition(JSGlobalData&, Structure*);
static Structure* sealTransition(JSGlobalData&, Structure*);
@@ -106,7 +106,7 @@ namespace JSC {
static void destroy(JSCell*);
// These should be used with caution.
- size_t addPropertyWithoutTransition(JSGlobalData&, const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
+ JS_EXPORT_PRIVATE size_t addPropertyWithoutTransition(JSGlobalData&, const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
size_t removePropertyWithoutTransition(JSGlobalData&, const Identifier& propertyName);
void setPrototypeWithoutTransition(JSGlobalData& globalData, JSValue prototype) { m_prototype.set(globalData, this, prototype); }
@@ -136,7 +136,7 @@ namespace JSC {
size_t get(JSGlobalData&, const Identifier& propertyName);
size_t get(JSGlobalData&, const UString& name);
- size_t get(JSGlobalData&, StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue);
+ JS_EXPORT_PRIVATE size_t get(JSGlobalData&, StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue);
size_t get(JSGlobalData& globalData, const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue)
{
ASSERT(!propertyName.isNull());
@@ -151,7 +151,7 @@ namespace JSC {
bool isEmpty() const { return m_propertyTable ? m_propertyTable->isEmpty() : m_offset == noOffset; }
- void despecifyDictionaryFunction(JSGlobalData&, const Identifier& propertyName);
+ JS_EXPORT_PRIVATE void despecifyDictionaryFunction(JSGlobalData&, const Identifier& propertyName);
void disableSpecificFunctionTracking() { m_specificFunctionThrashCount = maxSpecificFunctionThrashCount; }
void setEnumerationCache(JSGlobalData&, JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
@@ -196,7 +196,7 @@ namespace JSC {
static JS_EXPORTDATA const ClassInfo s_info;
private:
- Structure(JSGlobalData&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*);
+ JS_EXPORT_PRIVATE Structure(JSGlobalData&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*);
Structure(JSGlobalData&);
Structure(JSGlobalData&, const Structure*);
@@ -226,7 +226,7 @@ namespace JSC {
PassOwnPtr<PropertyTable> copyPropertyTable(JSGlobalData&, Structure* owner);
PassOwnPtr<PropertyTable> copyPropertyTableForPinning(JSGlobalData&, Structure* owner);
- void materializePropertyMap(JSGlobalData&);
+ JS_EXPORT_PRIVATE void materializePropertyMap(JSGlobalData&);
void materializePropertyMapIfNecessary(JSGlobalData& globalData)
{
ASSERT(structure()->classInfo() == &s_info);
diff --git a/Source/JavaScriptCore/runtime/TimeoutChecker.h b/Source/JavaScriptCore/runtime/TimeoutChecker.h
index 5925641f8..89d6158cc 100644
--- a/Source/JavaScriptCore/runtime/TimeoutChecker.h
+++ b/Source/JavaScriptCore/runtime/TimeoutChecker.h
@@ -57,9 +57,9 @@ namespace JSC {
--m_startCount;
}
- void reset();
+ JS_EXPORT_PRIVATE void reset();
- bool didTimeOut(ExecState*);
+ JS_EXPORT_PRIVATE bool didTimeOut(ExecState*);
private:
unsigned m_timeoutInterval;
diff --git a/Source/JavaScriptCore/runtime/UString.h b/Source/JavaScriptCore/runtime/UString.h
index c05ae5081..668eb0489 100644
--- a/Source/JavaScriptCore/runtime/UString.h
+++ b/Source/JavaScriptCore/runtime/UString.h
@@ -33,18 +33,18 @@ public:
UString() { }
// Construct a string with UTF-16 data.
- UString(const UChar* characters, unsigned length);
+ JS_EXPORT_PRIVATE UString(const UChar* characters, unsigned length);
// Construct a string with UTF-16 data, from a null-terminated source.
- UString(const UChar*);
+ JS_EXPORT_PRIVATE UString(const UChar*);
// Construct a string with latin1 data.
UString(const LChar* characters, unsigned length);
- UString(const char* characters, unsigned length);
+ JS_EXPORT_PRIVATE UString(const char* characters, unsigned length);
// Construct a string with latin1 data, from a null-terminated source.
UString(const LChar* characters);
- UString(const char* characters);
+ JS_EXPORT_PRIVATE UString(const char* characters);
// Construct a string referencing an existing StringImpl.
UString(StringImpl* impl) : m_impl(impl) { }
@@ -99,9 +99,9 @@ public:
bool is8Bit() const { return m_impl->is8Bit(); }
- CString ascii() const;
+ JS_EXPORT_PRIVATE CString ascii() const;
CString latin1() const;
- CString utf8(bool strict = false) const;
+ JS_EXPORT_PRIVATE CString utf8(bool strict = false) const;
UChar operator[](unsigned index) const
{
@@ -112,11 +112,11 @@ public:
return m_impl->characters16()[index];
}
- static UString number(int);
- static UString number(unsigned);
- static UString number(long);
+ JS_EXPORT_PRIVATE static UString number(int);
+ JS_EXPORT_PRIVATE static UString number(unsigned);
+ JS_EXPORT_PRIVATE static UString number(long);
static UString number(long long);
- static UString number(double);
+ JS_EXPORT_PRIVATE static UString number(double);
// Find a single character or string, also with match function & latin1 forms.
size_t find(UChar c, unsigned start = 0) const
@@ -132,25 +132,17 @@ public:
size_t reverseFind(const UString& str, unsigned start = UINT_MAX) const
{ return m_impl ? m_impl->reverseFind(str.impl(), start) : notFound; }
- UString substringSharingImpl(unsigned pos, unsigned len = UINT_MAX) const;
+ JS_EXPORT_PRIVATE UString substringSharingImpl(unsigned pos, unsigned len = UINT_MAX) const;
private:
RefPtr<StringImpl> m_impl;
};
template<>
-inline const LChar* UString::getCharacters<LChar>() const
-{
- ASSERT(is8Bit());
- return characters8();
-}
+inline const LChar* UString::getCharacters<LChar>() const { return characters8(); }
template<>
-inline const UChar* UString::getCharacters<UChar>() const
-{
- ASSERT(!is8Bit());
- return characters16();
-}
+inline const UChar* UString::getCharacters<UChar>() const { return characters(); }
NEVER_INLINE bool equalSlowCase(const UString& s1, const UString& s2);
@@ -189,10 +181,10 @@ inline bool operator!=(const UString& s1, const UString& s2)
return !JSC::operator==(s1, s2);
}
-bool operator<(const UString& s1, const UString& s2);
-bool operator>(const UString& s1, const UString& s2);
+JS_EXPORT_PRIVATE bool operator<(const UString& s1, const UString& s2);
+JS_EXPORT_PRIVATE bool operator>(const UString& s1, const UString& s2);
-bool operator==(const UString& s1, const char* s2);
+JS_EXPORT_PRIVATE bool operator==(const UString& s1, const char* s2);
inline bool operator!=(const UString& s1, const char* s2)
{
diff --git a/Source/JavaScriptCore/runtime/WriteBarrier.h b/Source/JavaScriptCore/runtime/WriteBarrier.h
index 525fc0926..a7bd7a100 100644
--- a/Source/JavaScriptCore/runtime/WriteBarrier.h
+++ b/Source/JavaScriptCore/runtime/WriteBarrier.h
@@ -40,8 +40,8 @@ class JSGlobalObject;
template<class T> class WriteBarrierBase;
template<> class WriteBarrierBase<JSValue>;
-void slowValidateCell(JSCell*);
-void slowValidateCell(JSGlobalObject*);
+JS_EXPORT_PRIVATE void slowValidateCell(JSCell*);
+JS_EXPORT_PRIVATE void slowValidateCell(JSGlobalObject*);
#if ENABLE(GC_VALIDATION)
template<class T> inline void validateCell(T cell)
diff --git a/Source/JavaScriptCore/tools/CodeProfile.cpp b/Source/JavaScriptCore/tools/CodeProfile.cpp
new file mode 100644
index 000000000..7794f58d3
--- /dev/null
+++ b/Source/JavaScriptCore/tools/CodeProfile.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2012 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 "CodeProfile.h"
+
+#include "CodeBlock.h"
+#include "CodeProfiling.h"
+#include "LinkBuffer.h"
+#include "ProfileTreeNode.h"
+#include "Vector.h"
+#include <wtf/text/WTFString.h>
+
+#if PLATFORM(MAC)
+#include <cxxabi.h>
+#include <dlfcn.h>
+#include <execinfo.h>
+#endif
+
+namespace JSC {
+
+// Map from CodeType enum to a corresponding name.
+const char* CodeProfile::s_codeTypeNames[CodeProfile::NumberOfCodeTypes] = {
+ "[[EngineCode]]",
+ "[[GlobalThunk]]",
+ "[[RegExpCode]]",
+ "[[DFGJIT]]",
+ "[[BaselineOnly]]",
+ "[[BaselineProfile]]",
+ "[[BaselineOSR]]",
+ "[[EngineFrame]]"
+};
+
+// Helper function, find the symbol name for a pc in JSC.
+static const char* symbolName(void* address)
+{
+#if PLATFORM(MAC)
+ Dl_info info;
+ if (!dladdr(address, &info) || !info.dli_sname)
+ return "<unknown>";
+
+ const char* mangledName = info.dli_sname;
+ const char* cxaDemangled = abi::__cxa_demangle(mangledName, 0, 0, 0);
+ return cxaDemangled ? cxaDemangled : mangledName;
+#else
+ UNUSED_PARAM(address);
+ return "<unknown>";
+#endif
+}
+
+// Helper function, truncate traces to prune the output & make very verbose mode a little more readable.
+static bool truncateTrace(const char* symbolName)
+{
+ return !strcmp(symbolName, "JSC::BytecodeGenerator::generate()")
+ || !strcmp(symbolName, "JSC::Parser<JSC::Lexer<unsigned char> >::parseInner()")
+ || !strcmp(symbolName, "WTF::fastMalloc(unsigned long)")
+ || !strcmp(symbolName, "WTF::calculateUTCOffset()")
+ || !strcmp(symbolName, "JSC::DFG::ByteCodeParser::parseCodeBlock()");
+
+}
+
+// Each trace consists of a sequence of zero or more 'EngineFrame' entries,
+// followed by a sample in JIT code, or one or more 'EngineFrame' entries,
+// followed by a 'EngineCode' terminator.
+void CodeProfile::sample(void* pc, void** framePointer)
+{
+ // Disallow traces containing only a 'EngineCode' terminator, without any 'EngineFrame' frames.
+ if (!framePointer)
+ return;
+
+ while (framePointer) {
+ CodeType type;
+
+#if ENABLE(JIT)
+ // Determine if this sample fell in JIT code, and if so, from which JIT & why.
+ void* ownerUID = CodeProfiling::getOwnerUIDForPC(pc);
+
+ if (!ownerUID)
+ type = EngineFrame;
+ else if (ownerUID == GLOBAL_THUNK_ID)
+ type = GlobalThunk;
+ else if (ownerUID == REGEXP_CODE_ID)
+ type = RegExpCode;
+ else {
+ CodeBlock* codeBlock = static_cast<CodeBlock*>(ownerUID);
+ if (codeBlock->getJITType() == JITCode::DFGJIT)
+ type = DFGJIT;
+ else if (codeBlock->canCompileWithDFGState() == CodeBlock::CompileWithDFGFalse)
+ type = BaselineOnly;
+ else if (codeBlock->replacement())
+ type = BaselineOSR;
+ else
+ type = BaselineProfile;
+ }
+#else
+ type = EngineFrame;
+#endif
+
+ // A sample in JIT code terminates the trace.
+ m_samples.append(CodeRecord(pc, type));
+ if (type != EngineFrame)
+ return;
+
+ // Walk up the stack.
+#if PLATFORM(MAC) && CPU(X86_64)
+ pc = framePointer[1];
+ framePointer = reinterpret_cast<void**>(*framePointer);
+#else
+ // This platform is not yet supported!
+ ASSERT_NOT_REACHED();
+#endif
+ }
+
+ // If we get here, we walked the entire stack without finding any frames of JIT code.
+ m_samples.append(CodeRecord(0, EngineCode));
+}
+
+void CodeProfile::report()
+{
+ fprintf(stdout, "<CodeProfiling %s:%d>\n", m_file.data(), m_lineNo);
+
+ // How many frames of C-code to print - 0, if not verbose, 1 if verbose, up to 1024 if very verbose.
+ unsigned recursionLimit = CodeProfiling::beVeryVerbose() ? 1024 : CodeProfiling::beVerbose();
+
+ ProfileTreeNode profile;
+
+ // Walk through the sample buffer.
+ size_t trace = 0;
+ while (trace < m_samples.size()) {
+
+ // All traces are zero or more 'EngineFrame's, followed by a non-'EngineFrame'.
+ // Scan to find the last sample in the trace.
+ size_t lastInTrace = trace;
+ while (m_samples[lastInTrace].type == EngineFrame)
+ ++lastInTrace;
+
+ // We use the last sample type to look up a name (used as a bucket in the profiler).
+ ProfileTreeNode* callbacks = profile.sampleChild(s_codeTypeNames[m_samples[lastInTrace].type]);
+
+ // If there are any samples in C-code, add up to recursionLimit of them into the profile tree.
+ size_t lastEngineFrame = lastInTrace;
+ for (unsigned count = 0; lastEngineFrame > trace && count < recursionLimit; ++count) {
+ --lastEngineFrame;
+ ASSERT(m_samples[lastEngineFrame].type == EngineFrame);
+ const char* name = symbolName(m_samples[lastEngineFrame].pc);
+ callbacks = callbacks->sampleChild(name);
+ if (truncateTrace(name))
+ break;
+ }
+
+ // Move on to the next trace.
+ trace = lastInTrace + 1;
+ ASSERT(trace <= m_samples.size());
+ }
+
+ // Output the profile tree.
+ fprintf(stdout, "Total samples: %lld\n", static_cast<long long>(profile.childCount()));
+ profile.dump();
+
+ for (size_t i = 0 ; i < m_children.size(); ++i)
+ m_children[i]->report();
+
+ fprintf(stdout, "</CodeProfiling %s:%d>\n", m_file.data(), m_lineNo);
+}
+
+}
diff --git a/Source/JavaScriptCore/tools/CodeProfile.h b/Source/JavaScriptCore/tools/CodeProfile.h
new file mode 100644
index 000000000..ea360bcbc
--- /dev/null
+++ b/Source/JavaScriptCore/tools/CodeProfile.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2012 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 CodeProfile_h
+#define CodeProfile_h
+
+#include "SourceCode.h"
+#include "TieredMMapArray.h"
+#include <wtf/text/CString.h>
+
+namespace JSC {
+
+class CodeProfile {
+public:
+ CodeProfile(const SourceCode& source, CodeProfile* parent)
+ : m_file(source.provider()->url().utf8())
+ , m_lineNo(source.firstLine())
+ , m_parent(parent)
+ {
+ if (parent)
+ parent->addChild(this);
+ }
+
+ void sample(void* pc, void** framePointer);
+ void report();
+
+ CodeProfile* parent()
+ {
+ return m_parent;
+ }
+
+ void addChild(CodeProfile* child)
+ {
+ m_children.append(adoptPtr(child));
+ }
+
+private:
+ enum CodeType {
+ EngineCode,
+ GlobalThunk,
+ RegExpCode,
+ DFGJIT,
+ BaselineOnly,
+ BaselineProfile,
+ BaselineOSR,
+ EngineFrame,
+ NumberOfCodeTypes
+ };
+ struct CodeRecord {
+ CodeRecord(void* pc, CodeType type)
+ : pc(pc)
+ , type(type)
+ {
+ }
+ void* pc;
+ CodeType type;
+ };
+
+ CString m_file;
+ unsigned m_lineNo;
+ CodeProfile* m_parent;
+ Vector< OwnPtr<CodeProfile> > m_children;
+ TieredMMapArray<CodeRecord> m_samples;
+
+ static const char* s_codeTypeNames[NumberOfCodeTypes];
+};
+
+}
+
+#endif // CodeProfile_h
+
diff --git a/Source/JavaScriptCore/tools/CodeProfiling.cpp b/Source/JavaScriptCore/tools/CodeProfiling.cpp
new file mode 100644
index 000000000..f236484c9
--- /dev/null
+++ b/Source/JavaScriptCore/tools/CodeProfiling.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2012 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 "CodeProfiling.h"
+
+#include "CodeProfile.h"
+#include "MetaAllocator.h"
+#include "signal.h"
+
+namespace JSC {
+
+volatile CodeProfile* CodeProfiling::s_profileStack = 0;
+CodeProfiling::Mode CodeProfiling::s_mode = CodeProfiling::Disabled;
+WTF::MetaAllocatorTracker* CodeProfiling::s_tracker = 0;
+
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmissing-noreturn"
+#endif
+
+#if PLATFORM(MAC) && CPU(X86_64)
+// Helper function to start & stop the timer.
+// Presently we're using the wall-clock timer, since this seems to give the best results.
+static void setProfileTimer(unsigned usec)
+{
+ itimerval timer;
+ timer.it_value.tv_sec = 0;
+ timer.it_value.tv_usec = usec;
+ timer.it_interval.tv_sec = 0;
+ timer.it_interval.tv_usec = usec;
+ setitimer(ITIMER_REAL, &timer, 0);
+}
+#endif
+
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
+
+#if PLATFORM(MAC) && CPU(X86_64)
+static void profilingTimer(int, siginfo_t*, void* uap)
+{
+ mcontext_t context = static_cast<ucontext_t*>(uap)->uc_mcontext;
+ CodeProfiling::sample(reinterpret_cast<void*>(context->__ss.__rip),
+ reinterpret_cast<void**>(context->__ss.__rbp));
+}
+#endif
+
+// Callback triggered when the timer is fired.
+void CodeProfiling::sample(void* pc, void** framePointer)
+{
+ CodeProfile* profileStack = const_cast<CodeProfile*>(s_profileStack);
+ if (profileStack)
+ profileStack->sample(pc, framePointer);
+}
+
+void CodeProfiling::notifyAllocator(WTF::MetaAllocator* allocator)
+{
+ // Check for JSC_CODE_PROFILING.
+ const char* codeProfilingMode = getenv("JSC_CODE_PROFILING");
+ if (!codeProfilingMode)
+ return;
+
+ // Check for a valid mode, currently "1", "2", or "3".
+ if (!codeProfilingMode[0] || codeProfilingMode[1])
+ return;
+ switch (*codeProfilingMode) {
+ case '1':
+ s_mode = Enabled;
+ break;
+ case '2':
+ s_mode = Verbose;
+ break;
+ case '3':
+ s_mode = VeryVerbose;
+ break;
+ default:
+ return;
+ }
+
+ ASSERT(enabled());
+ ASSERT(!s_tracker);
+ s_tracker = new WTF::MetaAllocatorTracker();
+ allocator->trackAllocations(s_tracker);
+}
+
+void* CodeProfiling::getOwnerUIDForPC(void* address)
+{
+ if (!s_tracker)
+ return 0;
+ WTF::MetaAllocatorHandle* handle = s_tracker->find(address);
+ if (!handle)
+ return 0;
+ return handle->ownerUID();
+}
+
+void CodeProfiling::begin(const SourceCode& source)
+{
+ // Push a new CodeProfile onto the stack for each script encountered.
+ CodeProfile* profileStack = const_cast<CodeProfile*>(s_profileStack);
+ bool alreadyProfiling = profileStack;
+ s_profileStack = profileStack = new CodeProfile(source, profileStack);
+
+ // Is the profiler already running - if so, the timer will already be set up.
+ if (alreadyProfiling)
+ return;
+
+#if PLATFORM(MAC) && CPU(X86_64)
+ // Regsiter a signal handler & itimer.
+ struct sigaction action;
+ action.sa_sigaction = reinterpret_cast<void (*)(int, struct __siginfo *, void *)>(profilingTimer);
+ sigfillset(&action.sa_mask);
+ action.sa_flags = SA_SIGINFO;
+ sigaction(SIGALRM, &action, 0);
+ setProfileTimer(100);
+#endif
+}
+
+void CodeProfiling::end()
+{
+ // Pop the current profiler off the stack.
+ CodeProfile* current = const_cast<CodeProfile*>(s_profileStack);
+ ASSERT(current);
+ s_profileStack = current->parent();
+
+ // Is this the outermost script being profiled? - if not, just return.
+ // We perform all output of profiles recursively from the outermost script,
+ // to minimize profiling overhead from skewing results.
+ if (s_profileStack)
+ return;
+
+#if PLATFORM(MAC) && CPU(X86_64)
+ // Stop profiling
+ setProfileTimer(0);
+#endif
+
+ current->report();
+ delete current;
+}
+
+}
diff --git a/Source/JavaScriptCore/tools/CodeProfiling.h b/Source/JavaScriptCore/tools/CodeProfiling.h
new file mode 100644
index 000000000..9b0f5daa3
--- /dev/null
+++ b/Source/JavaScriptCore/tools/CodeProfiling.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012 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 CodeProfiling_h
+#define CodeProfiling_h
+
+namespace WTF {
+
+class MetaAllocator;
+class MetaAllocatorTracker;
+
+}
+
+namespace JSC {
+
+class CodeProfile;
+class SourceCode;
+
+class CodeProfiling {
+ enum Mode {
+ Disabled,
+ Enabled,
+ Verbose,
+ VeryVerbose
+ };
+
+public:
+ CodeProfiling(const SourceCode& source)
+ : m_active(enabled())
+ {
+ if (m_active)
+ begin(source);
+ }
+
+ ~CodeProfiling()
+ {
+ if (m_active)
+ end();
+ }
+
+ static bool enabled() { return s_mode != Disabled; }
+ static bool beVerbose() { return s_mode >= Verbose; }
+ static bool beVeryVerbose() { return s_mode >= VeryVerbose; }
+
+ static void notifyAllocator(WTF::MetaAllocator*);
+ static void* getOwnerUIDForPC(void*);
+ static void sample(void* pc, void** framePointer);
+
+private:
+ void begin(const SourceCode&);
+ void end();
+
+ bool m_active;
+
+ static Mode s_mode;
+ static WTF::MetaAllocatorTracker* s_tracker;
+ static volatile CodeProfile* s_profileStack;
+};
+
+}
+
+#endif // CodeProfiling_h
+
diff --git a/Source/JavaScriptCore/tools/ProfileTreeNode.h b/Source/JavaScriptCore/tools/ProfileTreeNode.h
new file mode 100644
index 000000000..6c5fdc185
--- /dev/null
+++ b/Source/JavaScriptCore/tools/ProfileTreeNode.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2012 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 ProfileTreeNode_h
+#define ProfileTreeNode_h
+
+namespace JSC {
+
+class ProfileTreeNode {
+ typedef HashMap<String, ProfileTreeNode> Map;
+ typedef std::pair<String, ProfileTreeNode> MapEntry;
+
+public:
+ ProfileTreeNode()
+ : m_count(0)
+ , m_children(0)
+ {
+ }
+
+ ~ProfileTreeNode()
+ {
+ delete m_children;
+ }
+
+ ProfileTreeNode* sampleChild(const char* name)
+ {
+ if (!m_children)
+ m_children = new Map();
+
+ ProfileTreeNode newEntry;
+ pair<Map::iterator, bool> result = m_children->add(String(name), newEntry);
+ ProfileTreeNode* childInMap = &result.first->second;
+ ++childInMap->m_count;
+ return childInMap;
+ }
+
+ void dump()
+ {
+ dumpInternal(0);
+ }
+
+ uint64_t count()
+ {
+ return m_count;
+ }
+
+ uint64_t childCount()
+ {
+ if (!m_children)
+ return 0;
+ uint64_t childCount = 0;
+ for (Map::iterator it = m_children->begin(); it != m_children->end(); ++it)
+ childCount += it->second.count();
+ return childCount;
+ }
+
+private:
+ void dumpInternal(unsigned indent)
+ {
+ if (!m_children)
+ return;
+
+ // Copy pointers to all children into a vector, and sort the vector by sample count.
+ Vector<MapEntry*> entries;
+ for (Map::iterator it = m_children->begin(); it != m_children->end(); ++it)
+ entries.append(&*it);
+ qsort(entries.begin(), entries.size(), sizeof(MapEntry*), compareEntries);
+
+ // Iterate over the children in sample-frequency order.
+ for (size_t e = 0; e < entries.size(); ++e) {
+ MapEntry* entry = entries[e];
+
+ // Print the number of samples, the name of this node, and the number of samples that are stack-top
+ // in this node (samples directly within this node, excluding samples in children.
+ for (unsigned i = 0; i < indent; ++i)
+ fprintf(stdout, " ");
+ fprintf(stdout, "% 8lld: %s (%lld stack top)\n",
+ static_cast<long long>(entry->second.count()),
+ entry->first.utf8().data(),
+ static_cast<long long>(entry->second.count() - entry->second.childCount()));
+
+ // Recursively dump the child nodes.
+ entry->second.dumpInternal(indent + 1);
+ }
+ }
+
+ static int compareEntries(const void* a, const void* b)
+ {
+ uint64_t da = (*static_cast<MapEntry* const *>(a))->second.count();
+ uint64_t db = (*static_cast<MapEntry* const *>(b))->second.count();
+ return (da < db) - (da > db);
+ }
+
+ uint64_t m_count;
+ Map* m_children;
+};
+
+}
+
+#endif // ProfileTreeNode_h
+
diff --git a/Source/JavaScriptCore/tools/TieredMMapArray.h b/Source/JavaScriptCore/tools/TieredMMapArray.h
new file mode 100644
index 000000000..fa6e5ae1f
--- /dev/null
+++ b/Source/JavaScriptCore/tools/TieredMMapArray.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2012 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 TieredMMapArray_h
+#define TieredMMapArray_h
+
+#include "OSAllocator.h"
+
+namespace JSC {
+
+// This class implements a simple array class that can be grown by appending items to the end.
+// This class is implemented purely in terms of system allocations, with no malloc/free, so that
+// it can safely be used from a secondary thread whilst the main thrad is paused (potentially
+// holding the fast malloc heap lock).
+template<typename T>
+class TieredMMapArray {
+ static const size_t entriesPerBlock = 4096;
+
+public:
+ TieredMMapArray()
+ : m_directoryCount(4096)
+ , m_directory(static_cast<T**>(OSAllocator::reserveAndCommit(m_directoryCount * sizeof(T*))))
+ , m_size(0)
+ {
+ for (size_t block = 0; block < m_directoryCount; ++block)
+ m_directory[block] = 0;
+ }
+
+ ~TieredMMapArray()
+ {
+ size_t usedCount = (m_size + (entriesPerBlock - 1)) / entriesPerBlock;
+ ASSERT(usedCount == m_directoryCount || !m_directory[usedCount]);
+
+ for (size_t block = 0; block < usedCount; ++block) {
+ ASSERT(m_directory[block]);
+ OSAllocator::decommitAndRelease(m_directory[block], entriesPerBlock * sizeof(T));
+ }
+
+ OSAllocator::decommitAndRelease(m_directory, m_directoryCount * sizeof(T*));
+ }
+
+ T& operator[](size_t index)
+ {
+ ASSERT(index < m_size);
+ size_t block = index / entriesPerBlock;
+ size_t offset = index % entriesPerBlock;
+
+ ASSERT(m_directory[block]);
+ return m_directory[block][offset];
+ }
+
+ void append(const T& value)
+ {
+ // Check if the array is completely full, if so create more capacity in the directory.
+ if (m_size == m_directoryCount * entriesPerBlock) {
+ // Reallocate the directory.
+ size_t oldDirectorySize = m_directoryCount * sizeof(T*);
+ size_t newDirectorySize = oldDirectorySize * 2;
+ if (newDirectorySize < oldDirectorySize)
+ CRASH();
+ m_directory = OSAllocator::reallocateCommitted(m_directory, oldDirectorySize, newDirectorySize);
+
+ //
+ size_t newDirectoryCount = m_directoryCount * 2;
+ for (size_t block = m_directoryCount; block < newDirectoryCount; ++block)
+ m_directory[block] = 0;
+ m_directoryCount = newDirectoryCount;
+ }
+
+ size_t index = m_size;
+ size_t block = index / entriesPerBlock;
+ size_t offset = index % entriesPerBlock;
+
+ if (!offset) {
+ ASSERT(!m_directory[block]);
+ m_directory[block] = static_cast<T*>(OSAllocator::reserveAndCommit(entriesPerBlock * sizeof(T)));
+ }
+
+ ASSERT(m_directory[block]);
+ ++m_size;
+ m_directory[block][offset] = value;
+ }
+
+ size_t size() const { return m_size; }
+
+private:
+ size_t m_directoryCount;
+ T** m_directory;
+ size_t m_size;
+};
+
+}
+
+#endif // TieredMMapArray_h
+
diff --git a/Source/JavaScriptCore/wtf/ASCIICType.h b/Source/JavaScriptCore/wtf/ASCIICType.h
index 17006ae2d..18e108e1b 100644
--- a/Source/JavaScriptCore/wtf/ASCIICType.h
+++ b/Source/JavaScriptCore/wtf/ASCIICType.h
@@ -111,6 +111,16 @@ template<typename CharType> inline CharType toASCIILower(CharType c)
return c | ((c >= 'A' && c <= 'Z') << 5);
}
+template<typename CharType> inline CharType toASCIILowerUnchecked(CharType character)
+{
+ // This function can be used for comparing any input character
+ // to a lowercase English character. The isASCIIAlphaCaselessEqual
+ // below should be used for regular comparison of ASCII alpha
+ // characters, but switch statements in CSS tokenizer require
+ // direct use of this function.
+ return character | 0x20;
+}
+
template<typename CharType> inline CharType toASCIIUpper(CharType c)
{
return c & ~((c >= 'a' && c <= 'z') << 5);
@@ -140,6 +150,14 @@ inline char upperNibbleToASCIIHexDigit(char c)
return nibble < 10 ? '0' + nibble : 'A' + nibble - 10;
}
+template<typename CharType> inline bool isASCIIAlphaCaselessEqual(CharType cssCharacter, char character)
+{
+ // This function compares a (preferrably) constant ASCII
+ // lowercase letter to any input character.
+ ASSERT(character >= 'a' && character <= 'z');
+ return LIKELY(toASCIILowerUnchecked(cssCharacter) == character);
+}
+
}
using WTF::isASCII;
@@ -154,8 +172,10 @@ using WTF::isASCIISpace;
using WTF::isASCIIUpper;
using WTF::toASCIIHexValue;
using WTF::toASCIILower;
+using WTF::toASCIILowerUnchecked;
using WTF::toASCIIUpper;
using WTF::lowerNibbleToASCIIHexDigit;
using WTF::upperNibbleToASCIIHexDigit;
+using WTF::isASCIIAlphaCaselessEqual;
#endif
diff --git a/Source/JavaScriptCore/wtf/Alignment.h b/Source/JavaScriptCore/wtf/Alignment.h
index d42b307ed..9b443efc6 100644
--- a/Source/JavaScriptCore/wtf/Alignment.h
+++ b/Source/JavaScriptCore/wtf/Alignment.h
@@ -26,7 +26,7 @@
namespace WTF {
-#if COMPILER(GCC) || COMPILER(MINGW) || COMPILER(RVCT) || COMPILER(GCCE)
+#if COMPILER(GCC) || COMPILER(MINGW) || COMPILER(RVCT) || COMPILER(GCCE) || (COMPILER(SUNCC) && __SUNPRO_CC > 0x590)
#define WTF_ALIGN_OF(type) __alignof__(type)
#define WTF_ALIGNED(variable_type, variable, n) variable_type variable __attribute__((__aligned__(n)))
#elif COMPILER(MSVC)
diff --git a/Source/JavaScriptCore/wtf/ArrayBufferView.h b/Source/JavaScriptCore/wtf/ArrayBufferView.h
index ccb7fd348..24ce25a5e 100644
--- a/Source/JavaScriptCore/wtf/ArrayBufferView.h
+++ b/Source/JavaScriptCore/wtf/ArrayBufferView.h
@@ -40,6 +40,7 @@ class ArrayBufferView : public RefCounted<ArrayBufferView> {
public:
virtual bool isByteArray() const { return false; }
virtual bool isUnsignedByteArray() const { return false; }
+ virtual bool isUnsignedByteClampedArray() const { return false; }
virtual bool isShortArray() const { return false; }
virtual bool isUnsignedShortArray() const { return false; }
virtual bool isIntArray() const { return false; }
@@ -65,10 +66,10 @@ class ArrayBufferView : public RefCounted<ArrayBufferView> {
virtual unsigned byteLength() const = 0;
- virtual ~ArrayBufferView();
+ WTF_EXPORT_PRIVATE virtual ~ArrayBufferView();
protected:
- ArrayBufferView(PassRefPtr<ArrayBuffer>, unsigned byteOffset);
+ WTF_EXPORT_PRIVATE ArrayBufferView(PassRefPtr<ArrayBuffer>, unsigned byteOffset);
inline bool setImpl(ArrayBufferView*, unsigned byteOffset);
@@ -118,7 +119,7 @@ class ArrayBufferView : public RefCounted<ArrayBufferView> {
*numElements = std::min(remainingElements, *numElements);
}
- virtual void neuter();
+ WTF_EXPORT_PRIVATE virtual void neuter();
// This is the address of the ArrayBuffer's storage, plus the byte offset.
void* m_baseAddress;
diff --git a/Source/JavaScriptCore/wtf/Assertions.cpp b/Source/JavaScriptCore/wtf/Assertions.cpp
index 3da67effe..80afcf414 100644
--- a/Source/JavaScriptCore/wtf/Assertions.cpp
+++ b/Source/JavaScriptCore/wtf/Assertions.cpp
@@ -272,6 +272,16 @@ void WTFGetBacktrace(void** stack, int* size)
#endif
}
+#if OS(DARWIN) || OS(LINUX)
+# if PLATFORM(QT) || PLATFORM(GTK)
+# if defined(__GLIBC__) && !defined(__UCLIBC__)
+# define WTF_USE_BACKTRACE_SYMBOLS 1
+# endif
+# else
+# define WTF_USE_DLADDR 1
+# endif
+#endif
+
void WTFReportBacktrace()
{
static const int framesToShow = 31;
@@ -281,11 +291,18 @@ void WTFReportBacktrace()
WTFGetBacktrace(samples, &frames);
+#if USE(BACKTRACE_SYMBOLS)
+ char** symbols = backtrace_symbols(samples, frames);
+ if (!symbols)
+ return;
+#endif
+
for (int i = framesToSkip; i < frames; ++i) {
const char* mangledName = 0;
char* cxaDemangled = 0;
-
-#if !PLATFORM(GTK) && !PLATFORM(QT) && (OS(DARWIN) || OS(LINUX))
+#if USE(BACKTRACE_SYMBOLS)
+ mangledName = symbols[i];
+#elif USE(DLADDR)
Dl_info info;
if (dladdr(samples[i], &info) && info.dli_sname)
mangledName = info.dli_sname;
@@ -299,6 +316,26 @@ void WTFReportBacktrace()
printf_stderr_common("%-3d %p\n", frameNumber, samples[i]);
free(cxaDemangled);
}
+
+#if USE(BACKTRACE_SYMBOLS)
+ free(symbols);
+#endif
+}
+
+#undef WTF_USE_BACKTRACE_SYMBOLS
+#undef WTF_USE_DLADDR
+
+static WTFCrashHookFunction globalHook = 0;
+
+void WTFSetCrashHook(WTFCrashHookFunction function)
+{
+ globalHook = function;
+}
+
+void WTFInvokeCrashHook()
+{
+ if (globalHook)
+ globalHook();
}
void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...)
diff --git a/Source/JavaScriptCore/wtf/Assertions.h b/Source/JavaScriptCore/wtf/Assertions.h
index 2b3d794a4..42dc0bd35 100644
--- a/Source/JavaScriptCore/wtf/Assertions.h
+++ b/Source/JavaScriptCore/wtf/Assertions.h
@@ -147,6 +147,10 @@ WTF_EXPORT_PRIVATE void WTFLogVerbose(const char* file, int line, const char* fu
WTF_EXPORT_PRIVATE void WTFGetBacktrace(void** stack, int* size);
WTF_EXPORT_PRIVATE void WTFReportBacktrace();
+typedef void (*WTFCrashHookFunction)();
+WTF_EXPORT_PRIVATE void WTFSetCrashHook(WTFCrashHookFunction);
+WTF_EXPORT_PRIVATE void WTFInvokeCrashHook();
+
#ifdef __cplusplus
}
#endif
@@ -163,12 +167,14 @@ WTF_EXPORT_PRIVATE void WTFReportBacktrace();
#if COMPILER(CLANG)
#define CRASH() do { \
WTFReportBacktrace(); \
+ WTFInvokeCrashHook(); \
*(int *)(uintptr_t)0xbbadbeef = 0; \
__builtin_trap(); \
} while (false)
#else
#define CRASH() do { \
WTFReportBacktrace(); \
+ WTFInvokeCrashHook(); \
*(int *)(uintptr_t)0xbbadbeef = 0; \
((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
} while (false)
diff --git a/Source/JavaScriptCore/wtf/ByteArray.h b/Source/JavaScriptCore/wtf/ByteArray.h
index 6964a33df..f68d032fd 100644
--- a/Source/JavaScriptCore/wtf/ByteArray.h
+++ b/Source/JavaScriptCore/wtf/ByteArray.h
@@ -83,7 +83,7 @@ namespace WTF {
}
}
- static PassRefPtr<ByteArray> create(size_t size);
+ WTF_EXPORT_PRIVATE static PassRefPtr<ByteArray> create(size_t size);
static size_t offsetOfSize() { return OBJECT_OFFSETOF(ByteArray, m_size); }
static size_t offsetOfData() { return OBJECT_OFFSETOF(ByteArray, m_data); }
diff --git a/Source/JavaScriptCore/wtf/CMakeLists.txt b/Source/JavaScriptCore/wtf/CMakeLists.txt
index 52d3e3c4d..c22ae5185 100644
--- a/Source/JavaScriptCore/wtf/CMakeLists.txt
+++ b/Source/JavaScriptCore/wtf/CMakeLists.txt
@@ -53,6 +53,7 @@ SET(WTF_HEADERS
Noncopyable.h
NotFound.h
NullPtr.h
+ NumberOfCores.h
OSAllocator.h
OSRandomSource.h
OwnArrayPtr.h
@@ -146,6 +147,7 @@ SET(WTF_SOURCES
MainThread.cpp
MD5.cpp
OSRandomSource.cpp
+ NumberOfCores.cpp
PageAllocationAligned.cpp
PageBlock.cpp
ParallelJobsGeneric.cpp
diff --git a/Source/JavaScriptCore/wtf/CheckedBoolean.h b/Source/JavaScriptCore/wtf/CheckedBoolean.h
new file mode 100644
index 000000000..c65c70ef8
--- /dev/null
+++ b/Source/JavaScriptCore/wtf/CheckedBoolean.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2011 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 CheckedBoolean_h
+#define CheckedBoolean_h
+
+#include <wtf/Assertions.h>
+
+class CheckedBoolean {
+public:
+ CheckedBoolean(bool value)
+ : m_value(value)
+#if !ASSERT_DISABLED
+ , m_checked(false)
+#endif
+ {
+ }
+
+ ~CheckedBoolean()
+ {
+ ASSERT(m_checked);
+ }
+
+ operator bool()
+ {
+#if !ASSERT_DISABLED
+ m_checked = true;
+#endif
+ return m_value;
+ }
+
+private:
+ bool m_value;
+#if !ASSERT_DISABLED
+ bool m_checked;
+#endif
+};
+
+#endif
diff --git a/Source/JavaScriptCore/wtf/Compiler.h b/Source/JavaScriptCore/wtf/Compiler.h
index 93d3316bf..96ad6e40e 100644
--- a/Source/JavaScriptCore/wtf/Compiler.h
+++ b/Source/JavaScriptCore/wtf/Compiler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -239,4 +239,14 @@
#define FINAL
#endif
+/* OBJC_CLASS */
+
+#ifndef OBJC_CLASS
+#ifdef __OBJC__
+#define OBJC_CLASS @class
+#else
+#define OBJC_CLASS class
+#endif
+#endif
+
#endif /* WTF_Compiler_h */
diff --git a/Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.h b/Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.h
index 348242e25..2262b6c3b 100644
--- a/Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.h
+++ b/Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.h
@@ -31,8 +31,8 @@
namespace WTF {
#if USE(OS_RANDOMNESS)
-uint32_t cryptographicallyRandomNumber();
-void cryptographicallyRandomValues(void* buffer, size_t length);
+WTF_EXPORT_PRIVATE uint32_t cryptographicallyRandomNumber();
+WTF_EXPORT_PRIVATE void cryptographicallyRandomValues(void* buffer, size_t length);
#endif
}
diff --git a/Source/JavaScriptCore/wtf/CurrentTime.h b/Source/JavaScriptCore/wtf/CurrentTime.h
index 71775c273..ee49f8d25 100644
--- a/Source/JavaScriptCore/wtf/CurrentTime.h
+++ b/Source/JavaScriptCore/wtf/CurrentTime.h
@@ -39,7 +39,7 @@ namespace WTF {
// Returns the current UTC time in seconds, counted from January 1, 1970.
// Precision varies depending on platform but is usually as good or better
// than a millisecond.
-double currentTime();
+WTF_EXPORT_PRIVATE double currentTime();
// Same thing, in milliseconds.
inline double currentTimeMS()
@@ -60,7 +60,7 @@ inline void getLocalTime(const time_t* localTime, struct tm* localTM)
// Provides a monotonically increasing time in seconds since an arbitrary point in the past.
// On unsupported platforms, this function only guarantees the result will be non-decreasing.
-double monotonicallyIncreasingTime();
+WTF_EXPORT_PRIVATE double monotonicallyIncreasingTime();
} // namespace WTF
diff --git a/Source/JavaScriptCore/wtf/DateMath.h b/Source/JavaScriptCore/wtf/DateMath.h
index 114acf8a8..fc1a8d8e4 100644
--- a/Source/JavaScriptCore/wtf/DateMath.h
+++ b/Source/JavaScriptCore/wtf/DateMath.h
@@ -61,7 +61,7 @@ int equivalentYearForDST(int year);
// Not really math related, but this is currently the only shared place to put these.
double parseES5DateFromNullTerminatedCharacters(const char* dateString);
-double parseDateFromNullTerminatedCharacters(const char* dateString);
+WTF_EXPORT_PRIVATE double parseDateFromNullTerminatedCharacters(const char* dateString);
double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveTZ, int& offset);
double timeClip(double);
// dayOfWeek: [0, 6] 0 being Monday, day: [1, 31], month: [0, 11], year: ex: 2011, hours: [0, 23], minutes: [0, 59], seconds: [0, 59], utcOffset: [-720,720].
@@ -89,18 +89,18 @@ const double msPerMonth = 2592000000.0;
bool isLeapYear(int year);
// Returns the number of days from 1970-01-01 to the specified date.
-double dateToDaysFrom1970(int year, int month, int day);
-int msToYear(double ms);
+WTF_EXPORT_PRIVATE double dateToDaysFrom1970(int year, int month, int day);
+WTF_EXPORT_PRIVATE int msToYear(double ms);
double msToDays(double ms);
int msToMinutes(double ms);
int msToHours(double ms);
-int dayInYear(double ms, int year);
-int monthFromDayInYear(int dayInYear, bool leapYear);
-int dayInMonthFromDayInYear(int dayInYear, bool leapYear);
+WTF_EXPORT_PRIVATE int dayInYear(double ms, int year);
+WTF_EXPORT_PRIVATE int monthFromDayInYear(int dayInYear, bool leapYear);
+WTF_EXPORT_PRIVATE int dayInMonthFromDayInYear(int dayInYear, bool leapYear);
// Returns offset milliseconds for UTC and DST.
-int32_t calculateUTCOffset();
-double calculateDSTOffset(double ms, double utcOffset);
+WTF_EXPORT_PRIVATE int32_t calculateUTCOffset();
+WTF_EXPORT_PRIVATE double calculateDSTOffset(double ms, double utcOffset);
} // namespace WTF
diff --git a/Source/JavaScriptCore/wtf/DecimalNumber.h b/Source/JavaScriptCore/wtf/DecimalNumber.h
index ac7b80058..61effcdd3 100644
--- a/Source/JavaScriptCore/wtf/DecimalNumber.h
+++ b/Source/JavaScriptCore/wtf/DecimalNumber.h
@@ -81,11 +81,11 @@ public:
ASSERT(m_significand[0] != '0' || !m_exponent);
}
- unsigned bufferLengthForStringDecimal() const;
- unsigned bufferLengthForStringExponential() const;
+ WTF_EXPORT_PRIVATE unsigned bufferLengthForStringDecimal() const;
+ WTF_EXPORT_PRIVATE unsigned bufferLengthForStringExponential() const;
- unsigned toStringDecimal(UChar* buffer, unsigned bufferLength) const;
- unsigned toStringExponential(UChar* buffer, unsigned bufferLength) const;
+ WTF_EXPORT_PRIVATE unsigned toStringDecimal(UChar* buffer, unsigned bufferLength) const;
+ WTF_EXPORT_PRIVATE unsigned toStringExponential(UChar* buffer, unsigned bufferLength) const;
bool sign() const { return m_sign; }
int exponent() const { return m_exponent; }
diff --git a/Source/JavaScriptCore/wtf/DoublyLinkedList.h b/Source/JavaScriptCore/wtf/DoublyLinkedList.h
index 18aa00e17..361d71d7b 100644
--- a/Source/JavaScriptCore/wtf/DoublyLinkedList.h
+++ b/Source/JavaScriptCore/wtf/DoublyLinkedList.h
@@ -77,6 +77,7 @@ public:
T* head() const;
T* removeHead();
+ void push(T*);
void append(T*);
void remove(T*);
@@ -115,6 +116,24 @@ template<typename T> inline T* DoublyLinkedList<T>::head() const
return m_head;
}
+template<typename T> inline void DoublyLinkedList<T>::push(T* node)
+{
+ if (!m_head) {
+ ASSERT(!m_tail);
+ m_head = node;
+ m_tail = node;
+ node->setPrev(0);
+ node->setNext(0);
+ return;
+ }
+
+ ASSERT(m_tail);
+ m_head->setPrev(node);
+ node->setNext(m_head);
+ node->setPrev(0);
+ m_head = node;
+}
+
template<typename T> inline void DoublyLinkedList<T>::append(T* node)
{
if (!m_tail) {
diff --git a/Source/JavaScriptCore/wtf/FastMalloc.cpp b/Source/JavaScriptCore/wtf/FastMalloc.cpp
index 5c684500f..6b92f5542 100644
--- a/Source/JavaScriptCore/wtf/FastMalloc.cpp
+++ b/Source/JavaScriptCore/wtf/FastMalloc.cpp
@@ -182,7 +182,7 @@ namespace WTF {
namespace Internal {
#if !ENABLE(WTF_MALLOC_VALIDATION)
-void fastMallocMatchFailed(void*);
+WTF_EXPORT_PRIVATE void fastMallocMatchFailed(void*);
#else
COMPILE_ASSERT(((sizeof(ValidationHeader) % sizeof(AllocAlignmentInteger)) == 0), ValidationHeader_must_produce_correct_alignment);
#endif
@@ -400,7 +400,7 @@ size_t fastMallocSize(const void* p)
#if OS(DARWIN)
// This symbol is present in the JavaScriptCore exports file even when FastMalloc is disabled.
// It will never be used in this case, so it's type and value are less interesting than its presence.
-extern "C" const int jscore_fastmalloc_introspection = 0;
+extern "C" WTF_EXPORT_PRIVATE const int jscore_fastmalloc_introspection = 0;
#endif
#else // FORCE_SYSTEM_MALLOC
diff --git a/Source/JavaScriptCore/wtf/FastMalloc.h b/Source/JavaScriptCore/wtf/FastMalloc.h
index b4f74e47b..b115908ba 100644
--- a/Source/JavaScriptCore/wtf/FastMalloc.h
+++ b/Source/JavaScriptCore/wtf/FastMalloc.h
@@ -29,12 +29,12 @@
namespace WTF {
// These functions call CRASH() if an allocation fails.
- void* fastMalloc(size_t);
- void* fastZeroedMalloc(size_t);
- void* fastCalloc(size_t numElements, size_t elementSize);
- void* fastRealloc(void*, size_t);
- char* fastStrDup(const char*);
- size_t fastMallocSize(const void*);
+ WTF_EXPORT_PRIVATE void* fastMalloc(size_t);
+ WTF_EXPORT_PRIVATE void* fastZeroedMalloc(size_t);
+ WTF_EXPORT_PRIVATE void* fastCalloc(size_t numElements, size_t elementSize);
+ WTF_EXPORT_PRIVATE void* fastRealloc(void*, size_t);
+ WTF_EXPORT_PRIVATE char* fastStrDup(const char*);
+ WTF_EXPORT_PRIVATE size_t fastMallocSize(const void*);
struct TryMallocReturnValue {
TryMallocReturnValue(void* data)
@@ -68,26 +68,26 @@ namespace WTF {
return returnValue;
}
- TryMallocReturnValue tryFastMalloc(size_t n);
+ WTF_EXPORT_PRIVATE TryMallocReturnValue tryFastMalloc(size_t n);
TryMallocReturnValue tryFastZeroedMalloc(size_t n);
- TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size);
- TryMallocReturnValue tryFastRealloc(void* p, size_t n);
+ WTF_EXPORT_PRIVATE TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size);
+ WTF_EXPORT_PRIVATE TryMallocReturnValue tryFastRealloc(void* p, size_t n);
- void fastFree(void*);
+ WTF_EXPORT_PRIVATE void fastFree(void*);
#ifndef NDEBUG
void fastMallocForbid();
void fastMallocAllow();
#endif
- void releaseFastMallocFreeMemory();
+ WTF_EXPORT_PRIVATE void releaseFastMallocFreeMemory();
struct FastMallocStatistics {
size_t reservedVMBytes;
size_t committedVMBytes;
size_t freeListBytes;
};
- FastMallocStatistics fastMallocStatistics();
+ WTF_EXPORT_PRIVATE FastMallocStatistics fastMallocStatistics();
// This defines a type which holds an unsigned integer and is the same
// size as the minimally aligned memory allocation.
diff --git a/Source/JavaScriptCore/wtf/Forward.h b/Source/JavaScriptCore/wtf/Forward.h
index 3c97849cc..b81ab2580 100644
--- a/Source/JavaScriptCore/wtf/Forward.h
+++ b/Source/JavaScriptCore/wtf/Forward.h
@@ -51,6 +51,7 @@ namespace WTF {
class StringBuilder;
class StringImpl;
class Uint8Array;
+ class Uint8ClampedArray;
class Uint16Array;
class Uint32Array;
}
@@ -82,6 +83,7 @@ using WTF::StringBuffer;
using WTF::StringBuilder;
using WTF::StringImpl;
using WTF::Uint8Array;
+using WTF::Uint8ClampedArray;
using WTF::Uint16Array;
using WTF::Uint32Array;
diff --git a/Source/JavaScriptCore/wtf/InlineASM.h b/Source/JavaScriptCore/wtf/InlineASM.h
index c8a93f99c..379ebd364 100644
--- a/Source/JavaScriptCore/wtf/InlineASM.h
+++ b/Source/JavaScriptCore/wtf/InlineASM.h
@@ -44,6 +44,8 @@
#if (OS(LINUX) || OS(FREEBSD)) && CPU(X86_64)
#define SYMBOL_STRING_RELOCATION(name) #name "@plt"
+#elif OS(DARWIN) || (CPU(X86_64) && COMPILER(MINGW) && !GCC_VERSION_AT_LEAST(4, 5, 0))
+#define SYMBOL_STRING_RELOCATION(name) "_" #name
#elif CPU(X86) && COMPILER(MINGW)
#define SYMBOL_STRING_RELOCATION(name) "@" #name "@4"
#else
diff --git a/Source/JavaScriptCore/wtf/MD5.h b/Source/JavaScriptCore/wtf/MD5.h
index 3caa810ba..ef027ccad 100644
--- a/Source/JavaScriptCore/wtf/MD5.h
+++ b/Source/JavaScriptCore/wtf/MD5.h
@@ -37,16 +37,16 @@ namespace WTF {
class MD5 {
public:
- MD5();
+ WTF_EXPORT_PRIVATE MD5();
void addBytes(const Vector<uint8_t>& input)
{
addBytes(input.data(), input.size());
}
- void addBytes(const uint8_t* input, size_t length);
+ WTF_EXPORT_PRIVATE void addBytes(const uint8_t* input, size_t length);
// checksum has a side effect of resetting the state of the object.
- void checksum(Vector<uint8_t, 16>&);
+ WTF_EXPORT_PRIVATE void checksum(Vector<uint8_t, 16>&);
private:
uint32_t m_buf[4];
diff --git a/Source/JavaScriptCore/wtf/MainThread.h b/Source/JavaScriptCore/wtf/MainThread.h
index c153d1eba..ff76a5fd3 100644
--- a/Source/JavaScriptCore/wtf/MainThread.h
+++ b/Source/JavaScriptCore/wtf/MainThread.h
@@ -40,21 +40,21 @@ typedef uint32_t ThreadIdentifier;
typedef void MainThreadFunction(void*);
// Must be called from the main thread.
-void initializeMainThread();
+WTF_EXPORT_PRIVATE void initializeMainThread();
-void callOnMainThread(MainThreadFunction*, void* context);
-void callOnMainThreadAndWait(MainThreadFunction*, void* context);
-void cancelCallOnMainThread(MainThreadFunction*, void* context);
+WTF_EXPORT_PRIVATE void callOnMainThread(MainThreadFunction*, void* context);
+WTF_EXPORT_PRIVATE void callOnMainThreadAndWait(MainThreadFunction*, void* context);
+WTF_EXPORT_PRIVATE void cancelCallOnMainThread(MainThreadFunction*, void* context);
template<typename> class Function;
-void callOnMainThread(const Function<void ()>&);
+WTF_EXPORT_PRIVATE void callOnMainThread(const Function<void ()>&);
-void setMainThreadCallbacksPaused(bool paused);
+WTF_EXPORT_PRIVATE void setMainThreadCallbacksPaused(bool paused);
-bool isMainThread();
+WTF_EXPORT_PRIVATE bool isMainThread();
#if ENABLE(PARALLEL_GC)
void registerGCThread();
-bool isMainThreadOrGCThread();
+WTF_EXPORT_PRIVATE bool isMainThreadOrGCThread();
#elif PLATFORM(MAC)
bool isMainThreadOrGCThread();
#else
@@ -70,7 +70,7 @@ void dispatchFunctionsFromMainThread();
// This version of initializeMainThread sets up the main thread as corresponding
// to the process's main thread, and not necessarily the thread that calls this
// function. It should only be used as a legacy aid for Mac WebKit.
-void initializeMainThreadToProcessMainThread();
+WTF_EXPORT_PRIVATE void initializeMainThreadToProcessMainThread();
void initializeMainThreadToProcessMainThreadPlatform();
#endif
diff --git a/Source/JavaScriptCore/wtf/MetaAllocator.cpp b/Source/JavaScriptCore/wtf/MetaAllocator.cpp
index 92205a5d8..d153faab7 100644
--- a/Source/JavaScriptCore/wtf/MetaAllocator.cpp
+++ b/Source/JavaScriptCore/wtf/MetaAllocator.cpp
@@ -33,10 +33,33 @@
namespace WTF {
-MetaAllocatorHandle::MetaAllocatorHandle(MetaAllocator* allocator, void* start, size_t sizeInBytes)
+void MetaAllocatorTracker::notify(MetaAllocatorHandle* handle)
+{
+ m_allocations.insert(handle);
+}
+
+void MetaAllocatorTracker::release(MetaAllocatorHandle* handle)
+{
+ m_allocations.remove(handle);
+}
+
+ALWAYS_INLINE void MetaAllocator::release(MetaAllocatorHandle* handle)
+{
+ SpinLockHolder locker(&m_lock);
+ if (handle->sizeInBytes()) {
+ decrementPageOccupancy(handle->start(), handle->sizeInBytes());
+ addFreeSpaceFromReleasedHandle(handle->start(), handle->sizeInBytes());
+ }
+
+ if (UNLIKELY(!!m_tracker))
+ m_tracker->release(handle);
+}
+
+MetaAllocatorHandle::MetaAllocatorHandle(MetaAllocator* allocator, void* start, size_t sizeInBytes, void* ownerUID)
: m_allocator(allocator)
, m_start(start)
, m_sizeInBytes(sizeInBytes)
+ , m_ownerUID(ownerUID)
{
ASSERT(allocator);
ASSERT(start);
@@ -45,24 +68,14 @@ MetaAllocatorHandle::MetaAllocatorHandle(MetaAllocator* allocator, void* start,
MetaAllocatorHandle::~MetaAllocatorHandle()
{
- if (!m_allocator)
- return;
- SpinLockHolder locker(&m_allocator->m_lock);
- if (m_sizeInBytes) {
- m_allocator->decrementPageOccupancy(m_start, m_sizeInBytes);
- m_allocator->addFreeSpaceFromReleasedHandle(m_start, m_sizeInBytes);
- }
+ ASSERT(m_allocator);
+ m_allocator->release(this);
}
void MetaAllocatorHandle::shrink(size_t newSizeInBytes)
{
ASSERT(newSizeInBytes <= m_sizeInBytes);
- if (!m_allocator) {
- m_sizeInBytes = newSizeInBytes;
- return;
- }
-
SpinLockHolder locker(&m_allocator->m_lock);
newSizeInBytes = m_allocator->roundUp(newSizeInBytes);
@@ -91,6 +104,7 @@ MetaAllocator::MetaAllocator(size_t allocationGranule)
, m_bytesAllocated(0)
, m_bytesReserved(0)
, m_bytesCommitted(0)
+ , m_tracker(0)
#ifndef NDEBUG
, m_mallocBalance(0)
#endif
@@ -116,7 +130,7 @@ MetaAllocator::MetaAllocator(size_t allocationGranule)
ASSERT(static_cast<size_t>(1) << m_logAllocationGranule == m_allocationGranule);
}
-PassRefPtr<MetaAllocatorHandle> MetaAllocator::allocate(size_t sizeInBytes)
+PassRefPtr<MetaAllocatorHandle> MetaAllocator::allocate(size_t sizeInBytes, void* ownerUID)
{
SpinLockHolder locker(&m_lock);
@@ -154,10 +168,13 @@ PassRefPtr<MetaAllocatorHandle> MetaAllocator::allocate(size_t sizeInBytes)
m_numAllocations++;
#endif
- MetaAllocatorHandle* handle = new MetaAllocatorHandle(this, start, sizeInBytes);
+ MetaAllocatorHandle* handle = new MetaAllocatorHandle(this, start, sizeInBytes, ownerUID);
// FIXME: Implement a verifier scheme that groks MetaAllocatorHandles
handle->deprecatedTurnOffVerifier();
+ if (UNLIKELY(!!m_tracker))
+ m_tracker->notify(handle);
+
return adoptRef(handle);
}
@@ -178,18 +195,18 @@ void* MetaAllocator::findAndRemoveFreeSpace(size_t sizeInBytes)
if (!node)
return 0;
- ASSERT(node->m_key >= sizeInBytes);
+ ASSERT(node->m_sizeInBytes >= sizeInBytes);
m_freeSpaceSizeMap.remove(node);
void* result;
- if (node->m_key == sizeInBytes) {
+ if (node->m_sizeInBytes == sizeInBytes) {
// Easy case: perfect fit, so just remove the node entirely.
- result = node->m_value;
+ result = node->m_start;
- m_freeSpaceStartAddressMap.remove(node->m_value);
- m_freeSpaceEndAddressMap.remove(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(node->m_value) + node->m_key));
+ m_freeSpaceStartAddressMap.remove(node->m_start);
+ m_freeSpaceEndAddressMap.remove(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(node->m_start) + node->m_sizeInBytes));
freeFreeSpaceNode(node);
} else {
// Try to be a good citizen and ensure that the returned chunk of memory
@@ -199,31 +216,31 @@ void* MetaAllocator::findAndRemoveFreeSpace(size_t sizeInBytes)
// of committed pages, since in the long run, smaller fragmentation means
// fewer committed pages and fewer failures in general.
- uintptr_t firstPage = reinterpret_cast<uintptr_t>(node->m_value) >> m_logPageSize;
- uintptr_t lastPage = (reinterpret_cast<uintptr_t>(node->m_value) + node->m_key - 1) >> m_logPageSize;
+ uintptr_t firstPage = reinterpret_cast<uintptr_t>(node->m_start) >> m_logPageSize;
+ uintptr_t lastPage = (reinterpret_cast<uintptr_t>(node->m_start) + node->m_sizeInBytes - 1) >> m_logPageSize;
- uintptr_t lastPageForLeftAllocation = (reinterpret_cast<uintptr_t>(node->m_value) + sizeInBytes - 1) >> m_logPageSize;
- uintptr_t firstPageForRightAllocation = (reinterpret_cast<uintptr_t>(node->m_value) + node->m_key - sizeInBytes) >> m_logPageSize;
+ uintptr_t lastPageForLeftAllocation = (reinterpret_cast<uintptr_t>(node->m_start) + sizeInBytes - 1) >> m_logPageSize;
+ uintptr_t firstPageForRightAllocation = (reinterpret_cast<uintptr_t>(node->m_start) + node->m_sizeInBytes - sizeInBytes) >> m_logPageSize;
if (lastPageForLeftAllocation - firstPage + 1 <= lastPage - firstPageForRightAllocation + 1) {
// Allocate in the left side of the returned chunk, and slide the node to the right.
- result = node->m_value;
+ result = node->m_start;
- m_freeSpaceStartAddressMap.remove(node->m_value);
+ m_freeSpaceStartAddressMap.remove(node->m_start);
- node->m_key -= sizeInBytes;
- node->m_value = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(node->m_value) + sizeInBytes);
+ node->m_sizeInBytes -= sizeInBytes;
+ node->m_start = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(node->m_start) + sizeInBytes);
m_freeSpaceSizeMap.insert(node);
- m_freeSpaceStartAddressMap.add(node->m_value, node);
+ m_freeSpaceStartAddressMap.add(node->m_start, node);
} else {
// Allocate in the right size of the returned chunk, and slide the node to the left;
- result = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(node->m_value) + node->m_key - sizeInBytes);
+ result = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(node->m_start) + node->m_sizeInBytes - sizeInBytes);
- m_freeSpaceEndAddressMap.remove(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(node->m_value) + node->m_key));
+ m_freeSpaceEndAddressMap.remove(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(node->m_start) + node->m_sizeInBytes));
- node->m_key -= sizeInBytes;
+ node->m_sizeInBytes -= sizeInBytes;
m_freeSpaceSizeMap.insert(node);
m_freeSpaceEndAddressMap.add(result, node);
@@ -255,7 +272,7 @@ size_t MetaAllocator::debugFreeSpaceSize()
SpinLockHolder locker(&m_lock);
size_t result = 0;
for (FreeSpaceNode* node = m_freeSpaceSizeMap.first(); node; node = node->successor())
- result += node->m_key;
+ result += node->m_sizeInBytes;
return result;
#else
CRASH();
@@ -274,12 +291,12 @@ void MetaAllocator::addFreeSpace(void* start, size_t sizeInBytes)
// We have something we can coalesce with on the left. Remove it from the tree, and
// remove its end from the end address map.
- ASSERT(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(leftNeighbor->second->m_value) + leftNeighbor->second->m_key) == leftNeighbor->first);
+ ASSERT(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(leftNeighbor->second->m_start) + leftNeighbor->second->m_sizeInBytes) == leftNeighbor->first);
FreeSpaceNode* leftNode = leftNeighbor->second;
- void* leftStart = leftNode->m_value;
- size_t leftSize = leftNode->m_key;
+ void* leftStart = leftNode->m_start;
+ size_t leftSize = leftNode->m_sizeInBytes;
void* leftEnd = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(leftStart) + leftSize);
ASSERT(leftEnd == start);
@@ -292,11 +309,11 @@ void MetaAllocator::addFreeSpace(void* start, size_t sizeInBytes)
// Freeing something in the middle of free blocks. Coalesce both left and
// right, whilst removing the right neighbor from the maps.
- ASSERT(rightNeighbor->second->m_value == rightNeighbor->first);
+ ASSERT(rightNeighbor->second->m_start == rightNeighbor->first);
FreeSpaceNode* rightNode = rightNeighbor->second;
void* rightStart = rightNeighbor->first;
- size_t rightSize = rightNode->m_key;
+ size_t rightSize = rightNode->m_sizeInBytes;
void* rightEnd = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(rightStart) + rightSize);
ASSERT(rightStart == end);
@@ -308,12 +325,12 @@ void MetaAllocator::addFreeSpace(void* start, size_t sizeInBytes)
freeFreeSpaceNode(rightNode);
- leftNode->m_key += sizeInBytes + rightSize;
+ leftNode->m_sizeInBytes += sizeInBytes + rightSize;
m_freeSpaceSizeMap.insert(leftNode);
m_freeSpaceEndAddressMap.add(rightEnd, leftNode);
} else {
- leftNode->m_key += sizeInBytes;
+ leftNode->m_sizeInBytes += sizeInBytes;
m_freeSpaceSizeMap.insert(leftNode);
m_freeSpaceEndAddressMap.add(end, leftNode);
@@ -324,7 +341,7 @@ void MetaAllocator::addFreeSpace(void* start, size_t sizeInBytes)
if (rightNeighbor != m_freeSpaceStartAddressMap.end()) {
FreeSpaceNode* rightNode = rightNeighbor->second;
void* rightStart = rightNeighbor->first;
- size_t rightSize = rightNode->m_key;
+ size_t rightSize = rightNode->m_sizeInBytes;
void* rightEnd = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(rightStart) + rightSize);
ASSERT(rightStart == end);
@@ -333,8 +350,8 @@ void MetaAllocator::addFreeSpace(void* start, size_t sizeInBytes)
m_freeSpaceSizeMap.remove(rightNode);
m_freeSpaceStartAddressMap.remove(rightStart);
- rightNode->m_key += sizeInBytes;
- rightNode->m_value = start;
+ rightNode->m_sizeInBytes += sizeInBytes;
+ rightNode->m_start = start;
m_freeSpaceSizeMap.insert(rightNode);
m_freeSpaceStartAddressMap.add(start, rightNode);
@@ -343,8 +360,8 @@ void MetaAllocator::addFreeSpace(void* start, size_t sizeInBytes)
FreeSpaceNode* node = allocFreeSpaceNode();
- node->m_key = sizeInBytes;
- node->m_value = start;
+ node->m_sizeInBytes = sizeInBytes;
+ node->m_start = start;
m_freeSpaceSizeMap.insert(node);
m_freeSpaceStartAddressMap.add(start, node);
diff --git a/Source/JavaScriptCore/wtf/MetaAllocator.h b/Source/JavaScriptCore/wtf/MetaAllocator.h
index cf971b720..ffd55667e 100644
--- a/Source/JavaScriptCore/wtf/MetaAllocator.h
+++ b/Source/JavaScriptCore/wtf/MetaAllocator.h
@@ -43,15 +43,36 @@ namespace WTF {
#define ENABLE_META_ALLOCATOR_PROFILE 0
+class MetaAllocatorTracker {
+public:
+ void notify(MetaAllocatorHandle*);
+ void release(MetaAllocatorHandle*);
+
+ MetaAllocatorHandle* find(void* address)
+ {
+ MetaAllocatorHandle* handle = m_allocations.findGreatestLessThanOrEqual(address);
+ if (handle && address < handle->end())
+ return handle;
+ return 0;
+ }
+
+ RedBlackTree<MetaAllocatorHandle, void*> m_allocations;
+};
+
class MetaAllocator {
WTF_MAKE_NONCOPYABLE(MetaAllocator);
+
public:
-
- MetaAllocator(size_t allocationGranule);
+ WTF_EXPORT_PRIVATE MetaAllocator(size_t allocationGranule);
virtual ~MetaAllocator();
- PassRefPtr<MetaAllocatorHandle> allocate(size_t sizeInBytes);
+ WTF_EXPORT_PRIVATE PassRefPtr<MetaAllocatorHandle> allocate(size_t sizeInBytes, void* ownerUID);
+
+ void trackAllocations(MetaAllocatorTracker* tracker)
+ {
+ m_tracker = tracker;
+ }
// Non-atomic methods for getting allocator statistics.
size_t bytesAllocated() { return m_bytesAllocated; }
@@ -69,11 +90,11 @@ public:
// Add more free space to the allocator. Call this directly from
// the constructor if you wish to operate the allocator within a
// fixed pool.
- void addFreshFreeSpace(void* start, size_t sizeInBytes);
+ WTF_EXPORT_PRIVATE void addFreshFreeSpace(void* start, size_t sizeInBytes);
// This is meant only for implementing tests. Never call this in release
// builds.
- size_t debugFreeSpaceSize();
+ WTF_EXPORT_PRIVATE size_t debugFreeSpaceSize();
#if ENABLE(META_ALLOCATOR_PROFILE)
void dumpProfile();
@@ -101,8 +122,26 @@ private:
friend class MetaAllocatorHandle;
- typedef RedBlackTree<size_t, void*> Tree;
- typedef Tree::Node FreeSpaceNode;
+ class FreeSpaceNode : public RedBlackTree<FreeSpaceNode, size_t>::Node {
+ public:
+ FreeSpaceNode(void* start, size_t sizeInBytes)
+ : m_start(start)
+ , m_sizeInBytes(sizeInBytes)
+ {
+ }
+
+ size_t key()
+ {
+ return m_sizeInBytes;
+ }
+
+ void* m_start;
+ size_t m_sizeInBytes;
+ };
+ typedef RedBlackTree<FreeSpaceNode, size_t> Tree;
+
+ // Release a MetaAllocatorHandle.
+ void release(MetaAllocatorHandle*);
// Remove free space from the allocator. This is effectively
// the allocate() function, except that it does not mark the
@@ -121,13 +160,13 @@ private:
void incrementPageOccupancy(void* address, size_t sizeInBytes);
void decrementPageOccupancy(void* address, size_t sizeInBytes);
-
+
// Utilities.
size_t roundUp(size_t sizeInBytes);
FreeSpaceNode* allocFreeSpaceNode();
- void freeFreeSpaceNode(FreeSpaceNode*);
+ WTF_EXPORT_PRIVATE void freeFreeSpaceNode(FreeSpaceNode*);
size_t m_allocationGranule;
unsigned m_logAllocationGranule;
@@ -145,6 +184,8 @@ private:
SpinLock m_lock;
+ MetaAllocatorTracker* m_tracker;
+
#ifndef NDEBUG
size_t m_mallocBalance;
#endif
diff --git a/Source/JavaScriptCore/wtf/MetaAllocatorHandle.h b/Source/JavaScriptCore/wtf/MetaAllocatorHandle.h
index 5a32081d4..c43f491f3 100644
--- a/Source/JavaScriptCore/wtf/MetaAllocatorHandle.h
+++ b/Source/JavaScriptCore/wtf/MetaAllocatorHandle.h
@@ -30,6 +30,7 @@
#define WTF_MetaAllocatorHandle_h
#include <wtf/Assertions.h>
+#include <wtf/RedBlackTree.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
@@ -37,25 +38,12 @@ namespace WTF {
class MetaAllocator;
-class MetaAllocatorHandle : public RefCounted<MetaAllocatorHandle> {
+class MetaAllocatorHandle : public RefCounted<MetaAllocatorHandle>, public RedBlackTree<MetaAllocatorHandle, void*>::Node {
private:
- MetaAllocatorHandle(MetaAllocator*, void* start, size_t sizeInBytes);
-
- MetaAllocatorHandle(void* start, size_t sizeInBytes)
- : m_allocator(0)
- , m_start(start)
- , m_sizeInBytes(sizeInBytes)
- {
- ASSERT(start);
- }
+ MetaAllocatorHandle(MetaAllocator*, void* start, size_t sizeInBytes, void* ownerUID);
public:
- ~MetaAllocatorHandle();
-
- static PassRefPtr<MetaAllocatorHandle> createSelfManagedHandle(void* start, size_t sizeInBytes)
- {
- return adoptRef(new MetaAllocatorHandle(start, sizeInBytes));
- }
+ WTF_EXPORT_PRIVATE ~MetaAllocatorHandle();
void* start()
{
@@ -72,7 +60,7 @@ public:
return m_sizeInBytes;
}
- void shrink(size_t newSizeInBytes);
+ WTF_EXPORT_PRIVATE void shrink(size_t newSizeInBytes);
bool isManaged()
{
@@ -84,6 +72,16 @@ public:
ASSERT(m_allocator);
return m_allocator;
}
+
+ void* ownerUID()
+ {
+ return m_ownerUID;
+ }
+
+ void* key()
+ {
+ return m_start;
+ }
private:
friend class MetaAllocator;
@@ -91,6 +89,7 @@ private:
MetaAllocator* m_allocator;
void* m_start;
size_t m_sizeInBytes;
+ void* m_ownerUID;
};
}
diff --git a/Source/JavaScriptCore/wtf/NumberOfCores.cpp b/Source/JavaScriptCore/wtf/NumberOfCores.cpp
new file mode 100644
index 000000000..1e7f45f5c
--- /dev/null
+++ b/Source/JavaScriptCore/wtf/NumberOfCores.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 University of Szeged. 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 "NumberOfCores.h"
+
+#if OS(DARWIN) || OS(OPENBSD) || OS(NETBSD) || OS(FREEBSD)
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#elif OS(LINUX) || OS(AIX) || OS(SOLARIS)
+#include <unistd.h>
+#elif OS(WINDOWS)
+#include <windows.h>
+#include <wtf/UnusedParam.h>
+#endif
+
+namespace WTF {
+
+int numberOfProcessorCores()
+{
+ const int defaultIfUnavailable = 1;
+ static int s_numberOfCores = -1;
+
+ if (s_numberOfCores > 0)
+ return s_numberOfCores;
+
+#if OS(DARWIN) || OS(OPENBSD) || OS(NETBSD) || OS(FREEBSD)
+ unsigned result;
+ size_t length = sizeof(result);
+ int name[] = {
+ CTL_HW,
+ HW_NCPU
+ };
+ int sysctlResult = sysctl(name, sizeof(name) / sizeof(int), &result, &length, 0, 0);
+
+ s_numberOfCores = sysctlResult < 0 ? defaultIfUnavailable : result;
+#elif OS(LINUX) || OS(AIX) || OS(SOLARIS)
+ long sysconfResult = sysconf(_SC_NPROCESSORS_ONLN);
+
+ s_numberOfCores = sysconfResult < 0 ? defaultIfUnavailable : static_cast<int>(sysconfResult);
+#elif OS(WINDOWS)
+ UNUSED_PARAM(defaultIfUnavailable);
+ SYSTEM_INFO sysInfo;
+ GetSystemInfo(&sysInfo);
+
+ s_numberOfCores = sysInfo.dwNumberOfProcessors;
+#else
+ s_numberOfCores = defaultIfUnavailable;
+#endif
+ return s_numberOfCores;
+}
+
+}
diff --git a/Source/JavaScriptCore/wtf/NumberOfCores.h b/Source/JavaScriptCore/wtf/NumberOfCores.h
new file mode 100644
index 000000000..8bc8d9455
--- /dev/null
+++ b/Source/JavaScriptCore/wtf/NumberOfCores.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 University of Szeged. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NumberOfCores_h
+#define NumberOfCores_h
+
+namespace WTF {
+
+int numberOfProcessorCores();
+
+}
+
+#endif
diff --git a/Source/JavaScriptCore/wtf/OSAllocator.h b/Source/JavaScriptCore/wtf/OSAllocator.h
index bf9f04968..9ea4f6b51 100644
--- a/Source/JavaScriptCore/wtf/OSAllocator.h
+++ b/Source/JavaScriptCore/wtf/OSAllocator.h
@@ -26,6 +26,7 @@
#ifndef OSAllocator_h
#define OSAllocator_h
+#include <algorithm>
#include <wtf/UnusedParam.h>
#include <wtf/VMTags.h>
#include <wtf/VMTags.h>
@@ -46,7 +47,7 @@ public:
// releaseDecommitted should be called on a region of VM allocated by a single reservation,
// the memory must all currently be in a decommitted state.
static void* reserveUncommitted(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false, bool includesGuardPages = false);
- static void releaseDecommitted(void*, size_t);
+ WTF_EXPORT_PRIVATE static void releaseDecommitted(void*, size_t);
// These methods are symmetric; they commit or decommit a region of VM (uncommitted VM should
// never be accessed, since the OS may not have attached physical memory for these regions).
@@ -57,7 +58,7 @@ public:
// These methods are symmetric; reserveAndCommit allocates VM in an committed state,
// decommitAndRelease should be called on a region of VM allocated by a single reservation,
// the memory must all currently be in a committed state.
- static void* reserveAndCommit(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false, bool includesGuardPages = false);
+ WTF_EXPORT_PRIVATE static void* reserveAndCommit(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false, bool includesGuardPages = false);
static void decommitAndRelease(void* base, size_t size);
// These methods are akin to reserveAndCommit/decommitAndRelease, above - however rather than
@@ -65,6 +66,12 @@ public:
// specified.
static void* reserveAndCommit(size_t reserveSize, size_t commitSize, Usage = UnknownUsage, bool writable = true, bool executable = false);
static void decommitAndRelease(void* releaseBase, size_t releaseSize, void* decommitBase, size_t decommitSize);
+
+ // Reallocate an existing, committed allocation.
+ // The prior allocation must be fully comitted, and the new size will also be fully committed.
+ // This interface is provided since it may be possible to optimize this operation on some platforms.
+ template<typename T>
+ static T* reallocateCommitted(T*, size_t oldSize, size_t newSize, Usage = UnknownUsage, bool writable = true, bool executable = false);
};
inline void* OSAllocator::reserveAndCommit(size_t reserveSize, size_t commitSize, Usage usage, bool writable, bool executable)
@@ -93,6 +100,15 @@ inline void OSAllocator::decommitAndRelease(void* base, size_t size)
decommitAndRelease(base, size, base, size);
}
+template<typename T>
+inline T* OSAllocator::reallocateCommitted(T* oldBase, size_t oldSize, size_t newSize, Usage usage, bool writable, bool executable)
+{
+ void* newBase = reserveAndCommit(newSize, usage, writable, executable);
+ memcpy(newBase, oldBase, std::min(oldSize, newSize));
+ decommitAndRelease(oldBase, oldSize);
+ return static_cast<T*>(newBase);
+}
+
} // namespace WTF
using WTF::OSAllocator;
diff --git a/Source/JavaScriptCore/wtf/OSAllocatorPosix.cpp b/Source/JavaScriptCore/wtf/OSAllocatorPosix.cpp
index b264f685a..56c6089ff 100644
--- a/Source/JavaScriptCore/wtf/OSAllocatorPosix.cpp
+++ b/Source/JavaScriptCore/wtf/OSAllocatorPosix.cpp
@@ -37,7 +37,9 @@ namespace WTF {
void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable, bool executable, bool includesGuardPages)
{
void* result = reserveAndCommit(bytes, usage, writable, executable, includesGuardPages);
-#if HAVE(MADV_FREE_REUSE)
+#if OS(QNX)
+ posix_madvise(result, bytes, POSIX_MADV_DONTNEED);
+#elif HAVE(MADV_FREE_REUSE)
// To support the "reserve then commit" model, we have to initially decommit.
while (madvise(result, bytes, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
#endif
@@ -120,7 +122,9 @@ void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bo
void OSAllocator::commit(void* address, size_t bytes, bool, bool)
{
-#if HAVE(MADV_FREE_REUSE)
+#if OS(QNX)
+ posix_madvise(address, bytes, POSIX_MADV_WILLNEED);
+#elif HAVE(MADV_FREE_REUSE)
while (madvise(address, bytes, MADV_FREE_REUSE) == -1 && errno == EAGAIN) { }
#else
// Non-MADV_FREE_REUSE reservations automatically commit on demand.
@@ -131,7 +135,9 @@ void OSAllocator::commit(void* address, size_t bytes, bool, bool)
void OSAllocator::decommit(void* address, size_t bytes)
{
-#if HAVE(MADV_FREE_REUSE)
+#if OS(QNX)
+ posix_madvise(address, bytes, POSIX_MADV_DONTNEED);
+#elif HAVE(MADV_FREE_REUSE)
while (madvise(address, bytes, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
#elif HAVE(MADV_FREE)
while (madvise(address, bytes, MADV_FREE) == -1 && errno == EAGAIN) { }
diff --git a/Source/JavaScriptCore/wtf/OwnPtrCommon.h b/Source/JavaScriptCore/wtf/OwnPtrCommon.h
index 16283aed2..315db8954 100644
--- a/Source/JavaScriptCore/wtf/OwnPtrCommon.h
+++ b/Source/JavaScriptCore/wtf/OwnPtrCommon.h
@@ -28,7 +28,7 @@
#ifndef WTF_OwnPtrCommon_h
#define WTF_OwnPtrCommon_h
-#if PLATFORM(WIN)
+#if OS(WINDOWS)
typedef struct HBITMAP__* HBITMAP;
typedef struct HBRUSH__* HBRUSH;
typedef struct HDC__* HDC;
@@ -41,6 +41,7 @@ typedef struct HRGN__* HRGN;
#if PLATFORM(EFL)
typedef struct _Ecore_Evas Ecore_Evas;
typedef struct _Ecore_Pipe Ecore_Pipe;
+typedef struct _Eina_Module Eina_Module;
typedef struct _Evas_Object Evas_Object;
#endif
@@ -53,7 +54,7 @@ namespace WTF {
delete ptr;
}
-#if PLATFORM(WIN)
+#if OS(WINDOWS)
void deleteOwnedPtr(HBITMAP);
void deleteOwnedPtr(HBRUSH);
void deleteOwnedPtr(HDC);
@@ -66,6 +67,7 @@ namespace WTF {
#if PLATFORM(EFL)
void deleteOwnedPtr(Ecore_Evas*);
void deleteOwnedPtr(Ecore_Pipe*);
+ void deleteOwnedPtr(Eina_Module*);
void deleteOwnedPtr(Evas_Object*);
#endif
diff --git a/Source/JavaScriptCore/wtf/PageBlock.h b/Source/JavaScriptCore/wtf/PageBlock.h
index e17c5460a..3c348a0e3 100644
--- a/Source/JavaScriptCore/wtf/PageBlock.h
+++ b/Source/JavaScriptCore/wtf/PageBlock.h
@@ -28,7 +28,7 @@
namespace WTF {
-size_t pageSize();
+WTF_EXPORT_PRIVATE size_t pageSize();
inline bool isPageAligned(void* address) { return !(reinterpret_cast<intptr_t>(address) & (pageSize() - 1)); }
inline bool isPageAligned(size_t size) { return !(size & (pageSize() - 1)); }
inline bool isPowerOfTwo(size_t size) { return !(size & (size - 1)); }
diff --git a/Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp b/Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp
index b6207dc88..fd5b1f847 100644
--- a/Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp
+++ b/Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp
@@ -30,34 +30,22 @@
#if ENABLE(THREADING_GENERIC)
#include "ParallelJobs.h"
-#include "UnusedParam.h"
-
-#if OS(DARWIN) || OS(OPENBSD) || OS(NETBSD)
-#include <sys/sysctl.h>
-#include <sys/types.h>
-#elif OS(LINUX) || OS(AIX) || OS(SOLARIS)
-#include <unistd.h>
-#elif OS(WINDOWS)
-#include <windows.h>
-#endif
+#include <wtf/NumberOfCores.h>
namespace WTF {
Vector< RefPtr<ParallelEnvironment::ThreadPrivate> >* ParallelEnvironment::s_threadPool = 0;
-int ParallelEnvironment::s_maxNumberOfParallelThreads = -1;
-
ParallelEnvironment::ParallelEnvironment(ThreadFunction threadFunction, size_t sizeOfParameter, int requestedJobNumber) :
m_threadFunction(threadFunction),
m_sizeOfParameter(sizeOfParameter)
{
ASSERT_ARG(requestedJobNumber, requestedJobNumber >= 1);
- if (s_maxNumberOfParallelThreads == -1)
- determineMaxNumberOfParallelThreads();
+ int maxNumberOfCores = numberOfProcessorCores();
- if (!requestedJobNumber || requestedJobNumber > s_maxNumberOfParallelThreads)
- requestedJobNumber = static_cast<unsigned>(s_maxNumberOfParallelThreads);
+ if (!requestedJobNumber || requestedJobNumber > maxNumberOfCores)
+ requestedJobNumber = static_cast<unsigned>(maxNumberOfCores);
if (!s_threadPool)
s_threadPool = new Vector< RefPtr<ThreadPrivate> >();
@@ -65,7 +53,7 @@ ParallelEnvironment::ParallelEnvironment(ThreadFunction threadFunction, size_t s
// The main thread should be also a worker.
int maxNumberOfNewThreads = requestedJobNumber - 1;
- for (int i = 0; i < s_maxNumberOfParallelThreads && m_threads.size() < static_cast<unsigned>(maxNumberOfNewThreads); ++i) {
+ for (int i = 0; i < maxNumberOfCores && m_threads.size() < static_cast<unsigned>(maxNumberOfNewThreads); ++i) {
if (s_threadPool->size() < static_cast<unsigned>(i) + 1U)
s_threadPool->append(ThreadPrivate::create());
@@ -93,32 +81,6 @@ void ParallelEnvironment::execute(void* parameters)
m_threads[i]->waitForFinish();
}
-void ParallelEnvironment::determineMaxNumberOfParallelThreads()
-{
- const int defaultIfUnavailable = 2;
-#if OS(DARWIN) || OS(OPENBSD) || OS(NETBSD)
- unsigned result;
- size_t length = sizeof(result);
- int name[] = {
- CTL_HW,
- HW_NCPU
- };
- int sysctlResult = sysctl(name, sizeof(name) / sizeof(int), &result, &length, 0, 0);
- s_maxNumberOfParallelThreads = sysctlResult < 0 ? defaultIfUnavailable : result;
-#elif OS(LINUX) || OS(AIX) || OS(SOLARIS)
- long sysconfResult = sysconf(_SC_NPROCESSORS_ONLN);
- s_maxNumberOfParallelThreads = sysconfResult < 0 ? defaultIfUnavailable : static_cast<int>(sysconfResult);
-#elif OS(WINDOWS)
- UNUSED_PARAM(defaultIfUnavailable);
-
- SYSTEM_INFO sysInfo;
- GetSystemInfo(&sysInfo);
- s_maxNumberOfParallelThreads = sysInfo.dwNumberOfProcessors;
-#else
- s_maxNumberOfParallelThreads = defaultIfUnavailable;
-#endif
-}
-
bool ParallelEnvironment::ThreadPrivate::tryLockFor(ParallelEnvironment* parent)
{
bool locked = m_mutex.tryLock();
diff --git a/Source/JavaScriptCore/wtf/ParallelJobsGeneric.h b/Source/JavaScriptCore/wtf/ParallelJobsGeneric.h
index dab6dd9fb..1c7d63c16 100644
--- a/Source/JavaScriptCore/wtf/ParallelJobsGeneric.h
+++ b/Source/JavaScriptCore/wtf/ParallelJobsGeneric.h
@@ -84,15 +84,12 @@ public:
};
private:
- static void determineMaxNumberOfParallelThreads();
-
ThreadFunction m_threadFunction;
size_t m_sizeOfParameter;
int m_numberOfJobs;
Vector< RefPtr<ThreadPrivate> > m_threads;
static Vector< RefPtr<ThreadPrivate> >* s_threadPool;
- static int s_maxNumberOfParallelThreads;
};
} // namespace WTF
diff --git a/Source/JavaScriptCore/wtf/Platform.h b/Source/JavaScriptCore/wtf/Platform.h
index bb1462e1e..cecd5ddcd 100644
--- a/Source/JavaScriptCore/wtf/Platform.h
+++ b/Source/JavaScriptCore/wtf/Platform.h
@@ -386,6 +386,9 @@
#define WTF_OS_WINDOWS 1
#endif
+#define WTF_OS_WIN ERROR "USE WINDOWS WITH OS NOT WIN"
+#define WTF_OS_MAC ERROR "USE MAC_OS_X WITH OS NOT MAC"
+
/* OS(UNIX) - Any Unix-like system */
#if OS(AIX) \
|| OS(ANDROID) \
@@ -543,7 +546,9 @@
#define ENABLE_SMOOTH_SCROLLING 1
#define ENABLE_WEB_ARCHIVE 1
#define ENABLE_WEB_AUDIO 1
+#if defined(ENABLE_VIDEO)
#define ENABLE_VIDEO_TRACK 1
+#endif
#endif /* PLATFORM(MAC) && !PLATFORM(IOS) */
#if PLATFORM(CHROMIUM) && OS(DARWIN)
@@ -667,7 +672,7 @@
#endif
#endif
-#if !OS(WINDOWS) && !OS(SOLARIS) && !OS(QNX) \
+#if !OS(WINDOWS) && !OS(SOLARIS) \
&& !OS(RVCT) \
&& !OS(ANDROID)
#define HAVE_TM_GMTOFF 1
@@ -721,6 +726,8 @@
#define HAVE_ERRNO_H 1
#define HAVE_MMAP 1
+#define HAVE_MADV_FREE_REUSE 1
+#define HAVE_MADV_FREE 1
#define HAVE_SBRK 1
#define HAVE_STRINGS_H 1
#define HAVE_SYS_PARAM_H 1
@@ -1159,5 +1166,8 @@
/* Using V8 implies not using JSC and vice versa */
#define WTF_USE_JSC !WTF_USE_V8
+#if ENABLE(NOTIFICATIONS) && PLATFORM(MAC)
+#define ENABLE_TEXT_NOTIFICATIONS_ONLY 1
+#endif
#endif /* WTF_Platform_h */
diff --git a/Source/JavaScriptCore/wtf/PlatformEfl.cmake b/Source/JavaScriptCore/wtf/PlatformEfl.cmake
index 5805c4180..3887ead8c 100644
--- a/Source/JavaScriptCore/wtf/PlatformEfl.cmake
+++ b/Source/JavaScriptCore/wtf/PlatformEfl.cmake
@@ -31,6 +31,7 @@ LIST(APPEND WTF_LIBRARIES
${ICU_I18N_LIBRARIES}
${ECORE_LIBRARIES}
${ECORE_EVAS_LIBRARIES}
+ ${EINA_LIBRARIES}
${EVAS_LIBRARIES}
${CMAKE_DL_LIBS}
)
diff --git a/Source/JavaScriptCore/wtf/RandomNumber.h b/Source/JavaScriptCore/wtf/RandomNumber.h
index f2e7e8f50..76b223582 100644
--- a/Source/JavaScriptCore/wtf/RandomNumber.h
+++ b/Source/JavaScriptCore/wtf/RandomNumber.h
@@ -30,7 +30,7 @@ namespace WTF {
// Returns a pseudo-random number in the range [0, 1), attempts to be
// cryptographically secure if possible on the target platform
- double randomNumber();
+ WTF_EXPORT_PRIVATE double randomNumber();
}
diff --git a/Source/JavaScriptCore/wtf/RedBlackTree.h b/Source/JavaScriptCore/wtf/RedBlackTree.h
index af4e5c88a..19460c141 100644
--- a/Source/JavaScriptCore/wtf/RedBlackTree.h
+++ b/Source/JavaScriptCore/wtf/RedBlackTree.h
@@ -41,7 +41,7 @@ namespace WTF {
// reference to this node.
// - The key type must implement operator< and ==.
-template<typename KeyType, typename ValueType>
+template<class NodeType, typename KeyType>
class RedBlackTree {
WTF_MAKE_NONCOPYABLE(RedBlackTree);
private:
@@ -55,18 +55,12 @@ public:
friend class RedBlackTree;
public:
- Node(KeyType key, ValueType value)
- : m_key(key)
- , m_value(value)
- {
- }
-
- const Node* successor() const
+ const NodeType* successor() const
{
const Node* x = this;
if (x->right())
return treeMinimum(x->right());
- const Node* y = x->parent();
+ const NodeType* y = x->parent();
while (y && x == y->right()) {
x = y;
y = y->parent();
@@ -74,12 +68,12 @@ public:
return y;
}
- const Node* predecessor() const
+ const NodeType* predecessor() const
{
const Node* x = this;
if (x->left())
return treeMaximum(x->left());
- const Node* y = x->parent();
+ const NodeType* y = x->parent();
while (y && x == y->left()) {
x = y;
y = y->parent();
@@ -87,18 +81,15 @@ public:
return y;
}
- Node* successor()
+ NodeType* successor()
{
- return const_cast<Node*>(const_cast<const Node*>(this)->successor());
+ return const_cast<NodeType*>(const_cast<const Node*>(this)->successor());
}
-
- Node* predecessor()
+
+ NodeType* predecessor()
{
- return const_cast<Node*>(const_cast<const Node*>(this)->predecessor());
+ return const_cast<NodeType*>(const_cast<const Node*>(this)->predecessor());
}
-
- KeyType m_key;
- ValueType m_value;
private:
void reset()
@@ -110,32 +101,32 @@ public:
// NOTE: these methods should pack the parent and red into a single
// word. But doing so appears to reveal a bug in the compiler.
- Node* parent() const
+ NodeType* parent() const
{
- return reinterpret_cast<Node*>(m_parentAndRed & ~static_cast<uintptr_t>(1));
+ return reinterpret_cast<NodeType*>(m_parentAndRed & ~static_cast<uintptr_t>(1));
}
- void setParent(Node* newParent)
+ void setParent(NodeType* newParent)
{
m_parentAndRed = reinterpret_cast<uintptr_t>(newParent) | (m_parentAndRed & 1);
}
- Node* left() const
+ NodeType* left() const
{
return m_left;
}
- void setLeft(Node* node)
+ void setLeft(NodeType* node)
{
m_left = node;
}
- Node* right() const
+ NodeType* right() const
{
return m_right;
}
- void setRight(Node* node)
+ void setRight(NodeType* node)
{
m_right = node;
}
@@ -155,17 +146,17 @@ public:
m_parentAndRed &= ~static_cast<uintptr_t>(1);
}
- Node* m_left;
- Node* m_right;
+ NodeType* m_left;
+ NodeType* m_right;
uintptr_t m_parentAndRed;
};
-
+
RedBlackTree()
: m_root(0)
{
}
- void insert(Node* x)
+ void insert(NodeType* x)
{
x->reset();
treeInsert(x);
@@ -173,7 +164,7 @@ public:
while (x != m_root && x->parent()->color() == Red) {
if (x->parent() == x->parent()->parent()->left()) {
- Node* y = x->parent()->parent()->right();
+ NodeType* y = x->parent()->parent()->right();
if (y && y->color() == Red) {
// Case 1
x->parent()->setColor(Black);
@@ -193,7 +184,7 @@ public:
}
} else {
// Same as "then" clause with "right" and "left" exchanged.
- Node* y = x->parent()->parent()->left();
+ NodeType* y = x->parent()->parent()->left();
if (y && y->color() == Red) {
// Case 1
x->parent()->setColor(Black);
@@ -217,20 +208,20 @@ public:
m_root->setColor(Black);
}
- Node* remove(Node* z)
+ NodeType* remove(NodeType* z)
{
ASSERT(z);
ASSERT(z->parent() || z == m_root);
// Y is the node to be unlinked from the tree.
- Node* y;
+ NodeType* y;
if (!z->left() || !z->right())
y = z;
else
y = z->successor();
// Y is guaranteed to be non-null at this point.
- Node* x;
+ NodeType* x;
if (y->left())
x = y->left();
else
@@ -238,7 +229,7 @@ public:
// X is the child of y which might potentially replace y in
// the tree. X might be null at this point.
- Node* xParent;
+ NodeType* xParent;
if (x) {
x->setParent(y->parent());
xParent = x->parent();
@@ -281,20 +272,20 @@ public:
return z;
}
- Node* remove(const KeyType& key)
+ NodeType* remove(const KeyType& key)
{
- Node* result = findExact(key);
+ NodeType* result = findExact(key);
if (!result)
return 0;
return remove(result);
}
- Node* findExact(const KeyType& key) const
+ NodeType* findExact(const KeyType& key) const
{
- for (Node* current = m_root; current;) {
- if (current->m_key == key)
+ for (NodeType* current = m_root; current;) {
+ if (current->key() == key)
return current;
- if (key < current->m_key)
+ if (key < current->key())
current = current->left();
else
current = current->right();
@@ -302,13 +293,13 @@ public:
return 0;
}
- Node* findLeastGreaterThanOrEqual(const KeyType& key) const
+ NodeType* findLeastGreaterThanOrEqual(const KeyType& key) const
{
- Node* best = 0;
- for (Node* current = m_root; current;) {
- if (current->m_key == key)
+ NodeType* best = 0;
+ for (NodeType* current = m_root; current;) {
+ if (current->key() == key)
return current;
- if (current->m_key < key)
+ if (current->key() < key)
current = current->right();
else {
best = current;
@@ -318,13 +309,13 @@ public:
return best;
}
- Node* findGreatestLessThanOrEqual(const KeyType& key) const
+ NodeType* findGreatestLessThanOrEqual(const KeyType& key) const
{
- Node* best = 0;
- for (Node* current = m_root; current;) {
- if (current->m_key == key)
+ NodeType* best = 0;
+ for (NodeType* current = m_root; current;) {
+ if (current->key() == key)
return current;
- if (current->m_key > key)
+ if (current->key() > key)
current = current->left();
else {
best = current;
@@ -334,14 +325,14 @@ public:
return best;
}
- Node* first() const
+ NodeType* first() const
{
if (!m_root)
return 0;
return treeMinimum(m_root);
}
- Node* last() const
+ NodeType* last() const
{
if (!m_root)
return 0;
@@ -352,7 +343,7 @@ public:
size_t size()
{
size_t result = 0;
- for (Node* current = first(); current; current = current->successor())
+ for (NodeType* current = first(); current; current = current->successor())
result++;
return result;
}
@@ -366,46 +357,46 @@ public:
private:
// Finds the minimum element in the sub-tree rooted at the given
// node.
- static Node* treeMinimum(Node* x)
+ static NodeType* treeMinimum(NodeType* x)
{
while (x->left())
x = x->left();
return x;
}
- static Node* treeMaximum(Node* x)
+ static NodeType* treeMaximum(NodeType* x)
{
while (x->right())
x = x->right();
return x;
}
- static const Node* treeMinimum(const Node* x)
+ static const NodeType* treeMinimum(const NodeType* x)
{
while (x->left())
x = x->left();
return x;
}
- static const Node* treeMaximum(const Node* x)
+ static const NodeType* treeMaximum(const NodeType* x)
{
while (x->right())
x = x->right();
return x;
}
- void treeInsert(Node* z)
+ void treeInsert(NodeType* z)
{
ASSERT(!z->left());
ASSERT(!z->right());
ASSERT(!z->parent());
ASSERT(z->color() == Red);
- Node* y = 0;
- Node* x = m_root;
+ NodeType* y = 0;
+ NodeType* x = m_root;
while (x) {
y = x;
- if (z->m_key < x->m_key)
+ if (z->key() < x->key())
x = x->left();
else
x = x->right();
@@ -414,7 +405,7 @@ private:
if (!y)
m_root = z;
else {
- if (z->m_key < y->m_key)
+ if (z->key() < y->key())
y->setLeft(z);
else
y->setRight(z);
@@ -427,10 +418,10 @@ private:
// Left-rotates the subtree rooted at x.
// Returns the new root of the subtree (x's right child).
- Node* leftRotate(Node* x)
+ NodeType* leftRotate(NodeType* x)
{
// Set y.
- Node* y = x->right();
+ NodeType* y = x->right();
// Turn y's left subtree into x's right subtree.
x->setRight(y->left());
@@ -457,10 +448,10 @@ private:
// Right-rotates the subtree rooted at y.
// Returns the new root of the subtree (y's left child).
- Node* rightRotate(Node* y)
+ NodeType* rightRotate(NodeType* y)
{
// Set x.
- Node* x = y->left();
+ NodeType* x = y->left();
// Turn x's right subtree into y's left subtree.
y->setLeft(x->right());
@@ -488,7 +479,7 @@ private:
// Restores the red-black property to the tree after splicing out
// a node. Note that x may be null, which is why xParent must be
// supplied.
- void removeFixup(Node* x, Node* xParent)
+ void removeFixup(NodeType* x, NodeType* xParent)
{
while (x != m_root && (!x || x->color() == Black)) {
if (x == xParent->left()) {
@@ -496,7 +487,7 @@ private:
// The reason is not obvious from simply looking at
// the code; it comes about from the properties of the
// red-black tree.
- Node* w = xParent->right();
+ NodeType* w = xParent->right();
ASSERT(w); // x's sibling should not be null.
if (w->color() == Red) {
// Case 1
@@ -536,7 +527,7 @@ private:
// The reason is not obvious from simply looking at
// the code; it comes about from the properties of the
// red-black tree.
- Node* w = xParent->left();
+ NodeType* w = xParent->left();
ASSERT(w); // x's sibling should not be null.
if (w->color() == Red) {
// Case 1
@@ -574,7 +565,7 @@ private:
x->setColor(Black);
}
- Node* m_root;
+ NodeType* m_root;
};
}
diff --git a/Source/JavaScriptCore/wtf/RefCountedLeakCounter.h b/Source/JavaScriptCore/wtf/RefCountedLeakCounter.h
index 22c7506ac..476b1735a 100644
--- a/Source/JavaScriptCore/wtf/RefCountedLeakCounter.h
+++ b/Source/JavaScriptCore/wtf/RefCountedLeakCounter.h
@@ -27,14 +27,14 @@
namespace WTF {
struct RefCountedLeakCounter {
- static void suppressMessages(const char*);
- static void cancelMessageSuppression(const char*);
+ WTF_EXPORT_PRIVATE static void suppressMessages(const char*);
+ WTF_EXPORT_PRIVATE static void cancelMessageSuppression(const char*);
- explicit RefCountedLeakCounter(const char* description);
- ~RefCountedLeakCounter();
+ WTF_EXPORT_PRIVATE explicit RefCountedLeakCounter(const char* description);
+ WTF_EXPORT_PRIVATE ~RefCountedLeakCounter();
- void increment();
- void decrement();
+ WTF_EXPORT_PRIVATE void increment();
+ WTF_EXPORT_PRIVATE void decrement();
#ifndef NDEBUG
private:
diff --git a/Source/JavaScriptCore/wtf/SHA1.h b/Source/JavaScriptCore/wtf/SHA1.h
index dad6dc867..e8cc802e9 100644
--- a/Source/JavaScriptCore/wtf/SHA1.h
+++ b/Source/JavaScriptCore/wtf/SHA1.h
@@ -37,16 +37,16 @@ namespace WTF {
class SHA1 {
public:
- SHA1();
+ WTF_EXPORT_PRIVATE SHA1();
void addBytes(const Vector<uint8_t>& input)
{
addBytes(input.data(), input.size());
}
- void addBytes(const uint8_t* input, size_t length);
+ WTF_EXPORT_PRIVATE void addBytes(const uint8_t* input, size_t length);
// computeHash has a side effect of resetting the state of the object.
- void computeHash(Vector<uint8_t, 20>&);
+ WTF_EXPORT_PRIVATE void computeHash(Vector<uint8_t, 20>&);
private:
void finalize();
diff --git a/Source/JavaScriptCore/wtf/StdLibExtras.h b/Source/JavaScriptCore/wtf/StdLibExtras.h
index 3f99c4d3f..e4d7c8fc0 100644
--- a/Source/JavaScriptCore/wtf/StdLibExtras.h
+++ b/Source/JavaScriptCore/wtf/StdLibExtras.h
@@ -107,6 +107,13 @@ TypePtr reinterpret_cast_ptr(const void* ptr)
namespace WTF {
+static const size_t KB = 1024;
+
+inline bool isPointerAligned(void* p)
+{
+ return !((intptr_t)(p) & (sizeof(char*) - 1));
+}
+
/*
* C++'s idea of a reinterpret_cast lacks sufficient cojones.
*/
@@ -283,6 +290,8 @@ inline void* operator new(size_t, NotNullTag, void* location)
return location;
}
+using WTF::KB;
+using WTF::isPointerAligned;
using WTF::binarySearch;
using WTF::bitwise_cast;
using WTF::safeCast;
diff --git a/Source/JavaScriptCore/wtf/Threading.cpp b/Source/JavaScriptCore/wtf/Threading.cpp
index f2e0565e9..d8dbbae4f 100644
--- a/Source/JavaScriptCore/wtf/Threading.cpp
+++ b/Source/JavaScriptCore/wtf/Threading.cpp
@@ -89,7 +89,7 @@ ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char*
// This function is deprecated but needs to be kept around for backward
// compatibility. Use the 3-argument version of createThread above.
-ThreadIdentifier createThread(ThreadFunction entryPoint, void* data);
+WTF_EXPORT_PRIVATE ThreadIdentifier createThread(ThreadFunction entryPoint, void* data);
ThreadIdentifier createThread(ThreadFunction entryPoint, void* data)
{
diff --git a/Source/JavaScriptCore/wtf/Threading.h b/Source/JavaScriptCore/wtf/Threading.h
index 3a89757a9..1dee5da1c 100644
--- a/Source/JavaScriptCore/wtf/Threading.h
+++ b/Source/JavaScriptCore/wtf/Threading.h
@@ -83,11 +83,11 @@ typedef void* (*ThreadFunction)(void* argument);
// This function must be called from the main thread. It is safe to call it repeatedly.
// Darwin is an exception to this rule: it is OK to call it from any thread, the only
// requirement is that the calls are not reentrant.
-void initializeThreading();
+WTF_EXPORT_PRIVATE void initializeThreading();
// Returns 0 if thread creation failed.
// The thread name must be a literal since on some platforms it's passed in to the thread.
-ThreadIdentifier createThread(ThreadFunction, void*, const char* threadName);
+WTF_EXPORT_PRIVATE ThreadIdentifier createThread(ThreadFunction, void*, const char* threadName);
// Internal platform-specific createThread implementation.
ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char* threadName);
@@ -96,14 +96,14 @@ ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char* threadN
// Helpful for platforms where the thread name must be set from within the thread.
void initializeCurrentThreadInternal(const char* threadName);
-ThreadIdentifier currentThread();
-int waitForThreadCompletion(ThreadIdentifier, void**);
-void detachThread(ThreadIdentifier);
+WTF_EXPORT_PRIVATE ThreadIdentifier currentThread();
+WTF_EXPORT_PRIVATE int waitForThreadCompletion(ThreadIdentifier, void**);
+WTF_EXPORT_PRIVATE void detachThread(ThreadIdentifier);
-void yield();
+WTF_EXPORT_PRIVATE void yield();
-void lockAtomicallyInitializedStaticMutex();
-void unlockAtomicallyInitializedStaticMutex();
+WTF_EXPORT_PRIVATE void lockAtomicallyInitializedStaticMutex();
+WTF_EXPORT_PRIVATE void unlockAtomicallyInitializedStaticMutex();
} // namespace WTF
diff --git a/Source/JavaScriptCore/wtf/ThreadingPrimitives.h b/Source/JavaScriptCore/wtf/ThreadingPrimitives.h
index 1bed5d3ae..2ac42c8f1 100644
--- a/Source/JavaScriptCore/wtf/ThreadingPrimitives.h
+++ b/Source/JavaScriptCore/wtf/ThreadingPrimitives.h
@@ -82,12 +82,12 @@ typedef void* PlatformCondition;
class Mutex {
WTF_MAKE_NONCOPYABLE(Mutex); WTF_MAKE_FAST_ALLOCATED;
public:
- Mutex();
- ~Mutex();
+ WTF_EXPORT_PRIVATE Mutex();
+ WTF_EXPORT_PRIVATE ~Mutex();
- void lock();
- bool tryLock();
- void unlock();
+ WTF_EXPORT_PRIVATE void lock();
+ WTF_EXPORT_PRIVATE bool tryLock();
+ WTF_EXPORT_PRIVATE void unlock();
public:
PlatformMutex& impl() { return m_mutex; }
@@ -118,15 +118,15 @@ private:
class ThreadCondition {
WTF_MAKE_NONCOPYABLE(ThreadCondition);
public:
- ThreadCondition();
- ~ThreadCondition();
+ WTF_EXPORT_PRIVATE ThreadCondition();
+ WTF_EXPORT_PRIVATE ~ThreadCondition();
- void wait(Mutex& mutex);
+ WTF_EXPORT_PRIVATE void wait(Mutex& mutex);
// Returns true if the condition was signaled before absoluteTime, false if the absoluteTime was reached or is in the past.
// The absoluteTime is in seconds, starting on January 1, 1970. The time is assumed to use the same time zone as WTF::currentTime().
- bool timedWait(Mutex&, double absoluteTime);
- void signal();
- void broadcast();
+ WTF_EXPORT_PRIVATE bool timedWait(Mutex&, double absoluteTime);
+ WTF_EXPORT_PRIVATE void signal();
+ WTF_EXPORT_PRIVATE void broadcast();
private:
PlatformCondition m_condition;
diff --git a/Source/JavaScriptCore/wtf/Uint8Array.h b/Source/JavaScriptCore/wtf/Uint8Array.h
index 58fdb842b..a0959706c 100644
--- a/Source/JavaScriptCore/wtf/Uint8Array.h
+++ b/Source/JavaScriptCore/wtf/Uint8Array.h
@@ -46,7 +46,7 @@ public:
inline PassRefPtr<Uint8Array> subarray(int start) const;
inline PassRefPtr<Uint8Array> subarray(int start, int end) const;
-private:
+protected:
inline Uint8Array(PassRefPtr<ArrayBuffer>,
unsigned byteOffset,
unsigned length);
diff --git a/Source/JavaScriptCore/wtf/Uint8ClampedArray.h b/Source/JavaScriptCore/wtf/Uint8ClampedArray.h
new file mode 100644
index 000000000..f1044091b
--- /dev/null
+++ b/Source/JavaScriptCore/wtf/Uint8ClampedArray.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * 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 COMPUTER, 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 COMPUTER, 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 Uint8ClampedArray_h
+#define Uint8ClampedArray_h
+
+#include "Uint8Array.h"
+
+namespace WTF {
+
+class Uint8ClampedArray : public Uint8Array {
+public:
+ static inline PassRefPtr<Uint8ClampedArray> create(unsigned length);
+ static inline PassRefPtr<Uint8ClampedArray> create(unsigned char* array, unsigned length);
+ static inline PassRefPtr<Uint8ClampedArray> create(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length);
+
+ // Can’t use "using" here due to a bug in the RVCT compiler.
+ bool set(TypedArrayBase<unsigned char>* array, unsigned offset) { return TypedArrayBase<unsigned char>::set(array, offset); }
+ inline void set(unsigned index, double value);
+
+ inline PassRefPtr<Uint8ClampedArray> subarray(int start) const;
+ inline PassRefPtr<Uint8ClampedArray> subarray(int start, int end) const;
+
+private:
+ inline Uint8ClampedArray(PassRefPtr<ArrayBuffer>,
+ unsigned byteOffset,
+ unsigned length);
+ // Make constructor visible to superclass.
+ friend class TypedArrayBase<unsigned char>;
+
+ // Overridden from ArrayBufferView.
+ virtual bool isUnsignedByteClampedArray() const { return true; }
+};
+
+PassRefPtr<Uint8ClampedArray> Uint8ClampedArray::create(unsigned length)
+{
+ return TypedArrayBase<unsigned char>::create<Uint8ClampedArray>(length);
+}
+
+PassRefPtr<Uint8ClampedArray> Uint8ClampedArray::create(unsigned char* array, unsigned length)
+{
+ return TypedArrayBase<unsigned char>::create<Uint8ClampedArray>(array, length);
+}
+
+PassRefPtr<Uint8ClampedArray> Uint8ClampedArray::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length)
+{
+ return TypedArrayBase<unsigned char>::create<Uint8ClampedArray>(buffer, byteOffset, length);
+}
+
+void Uint8ClampedArray::set(unsigned index, double value)
+{
+ if (index >= m_length)
+ return;
+ if (isnan(value) || value < 0)
+ value = 0;
+ else if (value > 255)
+ value = 255;
+ data()[index] = static_cast<unsigned char>(value + 0.5);
+}
+
+Uint8ClampedArray::Uint8ClampedArray(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length)
+: Uint8Array(buffer, byteOffset, length)
+{
+}
+
+PassRefPtr<Uint8ClampedArray> Uint8ClampedArray::subarray(int start) const
+{
+ return subarray(start, length());
+}
+
+PassRefPtr<Uint8ClampedArray> Uint8ClampedArray::subarray(int start, int end) const
+{
+ return subarrayImpl<Uint8ClampedArray>(start, end);
+}
+
+} // namespace WTF
+
+using WTF::Uint8ClampedArray;
+
+#endif // Uint8ClampedArray_h
diff --git a/Source/JavaScriptCore/wtf/Vector.h b/Source/JavaScriptCore/wtf/Vector.h
index 1368ac99b..175f1a582 100644
--- a/Source/JavaScriptCore/wtf/Vector.h
+++ b/Source/JavaScriptCore/wtf/Vector.h
@@ -194,7 +194,7 @@ namespace WTF {
static bool compare(const T* a, const T* b, size_t size)
{
for (size_t i = 0; i < size; ++i)
- if (a[i] != b[i])
+ if (!(a[i] == b[i]))
return false;
return true;
}
diff --git a/Source/JavaScriptCore/wtf/WTFThreadData.h b/Source/JavaScriptCore/wtf/WTFThreadData.h
index 81b817f6f..b02d10d7c 100644
--- a/Source/JavaScriptCore/wtf/WTFThreadData.h
+++ b/Source/JavaScriptCore/wtf/WTFThreadData.h
@@ -78,8 +78,8 @@ typedef void (*AtomicStringTableDestructor)(AtomicStringTable*);
class WTFThreadData {
WTF_MAKE_NONCOPYABLE(WTFThreadData);
public:
- WTFThreadData();
- ~WTFThreadData();
+ WTF_EXPORT_PRIVATE WTFThreadData();
+ WTF_EXPORT_PRIVATE ~WTFThreadData();
AtomicStringTable* atomicStringTable()
{
diff --git a/Source/JavaScriptCore/wtf/dtoa.h b/Source/JavaScriptCore/wtf/dtoa.h
index df33e2cdc..d27c59206 100644
--- a/Source/JavaScriptCore/wtf/dtoa.h
+++ b/Source/JavaScriptCore/wtf/dtoa.h
@@ -31,19 +31,19 @@ extern WTF::Mutex* s_dtoaP5Mutex;
typedef char DtoaBuffer[80];
-void dtoa(DtoaBuffer result, double dd, bool& sign, int& exponent, unsigned& precision);
-void dtoaRoundSF(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision);
-void dtoaRoundDP(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision);
+WTF_EXPORT_PRIVATE void dtoa(DtoaBuffer result, double dd, bool& sign, int& exponent, unsigned& precision);
+WTF_EXPORT_PRIVATE void dtoaRoundSF(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision);
+WTF_EXPORT_PRIVATE void dtoaRoundDP(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision);
// s00: input string. Must not be 0 and must be terminated by 0.
// se: *se will have the last consumed character position + 1.
-double strtod(const char* s00, char** se);
+WTF_EXPORT_PRIVATE double strtod(const char* s00, char** se);
// Size = 80 for sizeof(DtoaBuffer) + some sign bits, decimal point, 'e', exponent digits.
const unsigned NumberToStringBufferLength = 96;
typedef char NumberToStringBuffer[NumberToStringBufferLength];
typedef UChar NumberToUStringBuffer[NumberToStringBufferLength];
-const char* numberToString(double, NumberToStringBuffer);
+WTF_EXPORT_PRIVATE const char* numberToString(double, NumberToStringBuffer);
const char* numberToFixedPrecisionString(double, unsigned significantFigures, NumberToStringBuffer, bool truncateTrailingZeros = false);
const char* numberToFixedWidthString(double, unsigned decimalPlaces, NumberToStringBuffer);
diff --git a/Source/JavaScriptCore/wtf/efl/OwnPtrEfl.cpp b/Source/JavaScriptCore/wtf/efl/OwnPtrEfl.cpp
index 7ec517029..3f3ad6420 100644
--- a/Source/JavaScriptCore/wtf/efl/OwnPtrEfl.cpp
+++ b/Source/JavaScriptCore/wtf/efl/OwnPtrEfl.cpp
@@ -29,6 +29,7 @@
#include <Ecore.h>
#include <Ecore_Evas.h>
+#include <Eina.h>
#include <Evas.h>
namespace WTF {
@@ -50,4 +51,10 @@ void deleteOwnedPtr(Ecore_Pipe* ptr)
ecore_pipe_del(ptr);
}
+void deleteOwnedPtr(Eina_Module* ptr)
+{
+ if (ptr)
+ eina_module_free(ptr); // If module wasn't unloaded, eina_module_free() calls eina_module_unload().
+}
+
}
diff --git a/Source/JavaScriptCore/wtf/gobject/GOwnPtr.cpp b/Source/JavaScriptCore/wtf/gobject/GOwnPtr.cpp
index 50c7b9ffc..c727956ce 100644
--- a/Source/JavaScriptCore/wtf/gobject/GOwnPtr.cpp
+++ b/Source/JavaScriptCore/wtf/gobject/GOwnPtr.cpp
@@ -49,6 +49,18 @@ template <> void freeOwnedGPtr<GDir>(GDir* ptr)
g_dir_close(ptr);
}
+template <> void freeOwnedGPtr<GTimer>(GTimer* ptr)
+{
+ if (ptr)
+ g_timer_destroy(ptr);
+}
+
+template <> void freeOwnedGPtr<GKeyFile>(GKeyFile* ptr)
+{
+ if (ptr)
+ g_key_file_free(ptr);
+}
+
} // namespace WTF
#endif // ENABLE(GLIB_SUPPORT)
diff --git a/Source/JavaScriptCore/wtf/gobject/GOwnPtr.h b/Source/JavaScriptCore/wtf/gobject/GOwnPtr.h
index 9ff85c5a4..221971f97 100644
--- a/Source/JavaScriptCore/wtf/gobject/GOwnPtr.h
+++ b/Source/JavaScriptCore/wtf/gobject/GOwnPtr.h
@@ -37,6 +37,8 @@ template<> void freeOwnedGPtr<GError>(GError*);
template<> void freeOwnedGPtr<GList>(GList*);
template<> void freeOwnedGPtr<GPatternSpec>(GPatternSpec*);
template<> void freeOwnedGPtr<GDir>(GDir*);
+template<> void freeOwnedGPtr<GTimer>(GTimer*);
+template<> void freeOwnedGPtr<GKeyFile>(GKeyFile*);
template <typename T> class GOwnPtr {
WTF_MAKE_NONCOPYABLE(GOwnPtr);
diff --git a/Source/JavaScriptCore/wtf/gobject/GTypedefs.h b/Source/JavaScriptCore/wtf/gobject/GTypedefs.h
index 66cedd6d2..e2b2ba6b8 100644
--- a/Source/JavaScriptCore/wtf/gobject/GTypedefs.h
+++ b/Source/JavaScriptCore/wtf/gobject/GTypedefs.h
@@ -58,6 +58,8 @@ typedef struct _GSocketConnection GSocketConnection;
typedef struct _GSource GSource;
typedef struct _GVariant GVariant;
typedef union _GdkEvent GdkEvent;
+typedef struct _GTimer GTimer;
+typedef struct _GKeyFile GKeyFile;
#if USE(CAIRO)
typedef struct _cairo_surface cairo_surface_t;
diff --git a/Source/JavaScriptCore/wtf/text/AtomicString.cpp b/Source/JavaScriptCore/wtf/text/AtomicString.cpp
index 966879827..d775e7bb9 100644
--- a/Source/JavaScriptCore/wtf/text/AtomicString.cpp
+++ b/Source/JavaScriptCore/wtf/text/AtomicString.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
* Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
+ * Copyright (C) 2012 Google Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -250,11 +251,52 @@ PassRefPtr<StringImpl> AtomicString::add(const UChar* s)
return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer);
}
-PassRefPtr<StringImpl> AtomicString::addSlowCase(StringImpl* r)
+struct SubstringLocation {
+ StringImpl* baseString;
+ unsigned start;
+ unsigned length;
+};
+
+struct SubstringTranslator {
+ static unsigned hash(const SubstringLocation& buffer)
+ {
+ return StringHasher::computeHash(buffer.baseString->characters() + buffer.start, buffer.length);
+ }
+
+ static bool equal(StringImpl* const& string, const SubstringLocation& buffer)
+ {
+ return WTF::equal(string, buffer.baseString->characters() + buffer.start, buffer.length);
+ }
+
+ static void translate(StringImpl*& location, const SubstringLocation& buffer, unsigned hash)
+ {
+ location = StringImpl::create(buffer.baseString, buffer.start, buffer.length).leakRef();
+ location->setHash(hash);
+ location->setIsAtomic(true);
+ }
+};
+
+PassRefPtr<StringImpl> AtomicString::add(StringImpl* baseString, unsigned start, unsigned length)
{
- if (!r || r->isAtomic())
- return r;
+ if (!baseString)
+ return 0;
+
+ if (!length || start >= baseString->length())
+ return StringImpl::empty();
+ unsigned maxLength = baseString->length() - start;
+ if (length >= maxLength) {
+ if (!start)
+ return add(baseString);
+ length = maxLength;
+ }
+
+ SubstringLocation buffer = { baseString, start, length };
+ return addToStringTable<SubstringLocation, SubstringTranslator>(buffer);
+}
+
+PassRefPtr<StringImpl> AtomicString::addSlowCase(StringImpl* r)
+{
if (!r->length())
return StringImpl::empty();
diff --git a/Source/JavaScriptCore/wtf/text/AtomicString.h b/Source/JavaScriptCore/wtf/text/AtomicString.h
index 43b38d179..b135845fe 100644
--- a/Source/JavaScriptCore/wtf/text/AtomicString.h
+++ b/Source/JavaScriptCore/wtf/text/AtomicString.h
@@ -38,7 +38,7 @@ struct AtomicStringHash;
class AtomicString {
public:
- static void init();
+ WTF_EXPORT_PRIVATE static void init();
AtomicString() { }
AtomicString(const LChar* s) : m_string(add(s)) { }
@@ -49,12 +49,13 @@ public:
ATOMICSTRING_CONVERSION AtomicString(StringImpl* imp) : m_string(add(imp)) { }
AtomicString(AtomicStringImpl* imp) : m_string(imp) { }
ATOMICSTRING_CONVERSION AtomicString(const String& s) : m_string(add(s.impl())) { }
+ AtomicString(StringImpl* baseString, unsigned start, unsigned length) : m_string(add(baseString, start, length)) { }
// Hash table deleted values, which are only constructed and never copied or destroyed.
AtomicString(WTF::HashTableDeletedValueType) : m_string(WTF::HashTableDeletedValue) { }
bool isHashTableDeletedValue() const { return m_string.isHashTableDeletedValue(); }
- static AtomicStringImpl* find(const UChar* s, unsigned length, unsigned existingHash);
+ WTF_EXPORT_PRIVATE static AtomicStringImpl* find(const UChar* s, unsigned length, unsigned existingHash);
operator const String&() const { return m_string; }
const String& string() const { return m_string; };
@@ -83,7 +84,7 @@ public:
bool endsWith(const String& s, bool caseSensitive = true) const
{ return m_string.endsWith(s, caseSensitive); }
- AtomicString lower() const;
+ WTF_EXPORT_PRIVATE AtomicString lower() const;
AtomicString upper() const { return AtomicString(impl()->upper()); }
int toInt(bool* ok = 0) const { return m_string.toInt(ok); }
@@ -120,20 +121,21 @@ public:
private:
String m_string;
- static PassRefPtr<StringImpl> add(const LChar*);
+ WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> add(const LChar*);
ALWAYS_INLINE static PassRefPtr<StringImpl> add(const char* s) { return add(reinterpret_cast<const LChar*>(s)); };
- static PassRefPtr<StringImpl> add(const UChar*, unsigned length);
+ WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> add(const UChar*, unsigned length);
ALWAYS_INLINE static PassRefPtr<StringImpl> add(const char* s, unsigned length) { return add(reinterpret_cast<const char*>(s), length); };
- static PassRefPtr<StringImpl> add(const UChar*, unsigned length, unsigned existingHash);
- static PassRefPtr<StringImpl> add(const UChar*);
- ALWAYS_INLINE PassRefPtr<StringImpl> add(StringImpl* r)
+ WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> add(const UChar*, unsigned length, unsigned existingHash);
+ WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> add(const UChar*);
+ WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> add(StringImpl*, unsigned offset, unsigned length);
+ ALWAYS_INLINE static PassRefPtr<StringImpl> add(StringImpl* r)
{
if (!r || r->isAtomic())
return r;
return addSlowCase(r);
}
- static PassRefPtr<StringImpl> addSlowCase(StringImpl*);
- static AtomicString fromUTF8Internal(const char*, const char*);
+ WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> addSlowCase(StringImpl*);
+ WTF_EXPORT_PRIVATE static AtomicString fromUTF8Internal(const char*, const char*);
};
inline bool operator==(const AtomicString& a, const AtomicString& b) { return a.impl() == b.impl(); }
diff --git a/Source/JavaScriptCore/wtf/text/CString.h b/Source/JavaScriptCore/wtf/text/CString.h
index 343a7a525..d43ad4bd7 100644
--- a/Source/JavaScriptCore/wtf/text/CString.h
+++ b/Source/JavaScriptCore/wtf/text/CString.h
@@ -52,16 +52,16 @@ private:
class CString {
public:
CString() { }
- CString(const char*);
- CString(const char*, size_t length);
+ WTF_EXPORT_PRIVATE CString(const char*);
+ WTF_EXPORT_PRIVATE CString(const char*, size_t length);
CString(CStringBuffer* buffer) : m_buffer(buffer) { }
- static CString newUninitialized(size_t length, char*& characterBuffer);
+ WTF_EXPORT_PRIVATE static CString newUninitialized(size_t length, char*& characterBuffer);
const char* data() const
{
return m_buffer ? m_buffer->data() : 0;
}
- char* mutableData();
+ WTF_EXPORT_PRIVATE char* mutableData();
size_t length() const
{
return m_buffer ? m_buffer->length() - 1 : 0;
@@ -77,7 +77,7 @@ private:
RefPtr<CStringBuffer> m_buffer;
};
-bool operator==(const CString& a, const CString& b);
+WTF_EXPORT_PRIVATE bool operator==(const CString& a, const CString& b);
inline bool operator!=(const CString& a, const CString& b) { return !(a == b); }
} // namespace WTF
diff --git a/Source/JavaScriptCore/wtf/text/StringBuilder.cpp b/Source/JavaScriptCore/wtf/text/StringBuilder.cpp
index 6d3c310e6..4eac75649 100644
--- a/Source/JavaScriptCore/wtf/text/StringBuilder.cpp
+++ b/Source/JavaScriptCore/wtf/text/StringBuilder.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,7 +33,7 @@ namespace WTF {
static const unsigned minimumCapacity = 16;
-void StringBuilder::reifyString()
+void StringBuilder::reifyString() const
{
// Check if the string already exists.
if (!m_string.isNull()) {
@@ -68,6 +69,7 @@ void StringBuilder::resize(unsigned newSize)
// If there is a buffer, we only need to duplicate it if it has more than one ref.
if (m_buffer) {
+ m_string = String(); // Clear the string to remove the reference to m_buffer if any before checking the reference count of m_buffer.
if (!m_buffer->hasOneRef()) {
if (m_buffer->is8Bit())
allocateBuffer(m_buffer->characters8(), m_buffer->length());
@@ -75,7 +77,6 @@ void StringBuilder::resize(unsigned newSize)
allocateBuffer(m_buffer->characters16(), m_buffer->length());
}
m_length = newSize;
- m_string = String();
return;
}
@@ -285,10 +286,15 @@ void StringBuilder::append(const LChar* characters, unsigned length)
}
}
+bool StringBuilder::canShrink() const
+{
+ // Only shrink the buffer if it's less than 80% full. Need to tune this heuristic!
+ return m_buffer && m_buffer->length() > (m_length + (m_length >> 2));
+}
+
void StringBuilder::shrinkToFit()
{
- // If the buffer is at least 80% full, don't bother copying. Need to tune this heuristic!
- if (m_buffer && m_buffer->length() > (m_length + (m_length >> 2))) {
+ if (canShrink()) {
if (m_is8Bit)
reallocateBuffer<LChar>(m_length);
else
diff --git a/Source/JavaScriptCore/wtf/text/StringBuilder.h b/Source/JavaScriptCore/wtf/text/StringBuilder.h
index da1e8320d..d896d17b1 100644
--- a/Source/JavaScriptCore/wtf/text/StringBuilder.h
+++ b/Source/JavaScriptCore/wtf/text/StringBuilder.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,12 +27,15 @@
#ifndef StringBuilder_h
#define StringBuilder_h
-#include <wtf/Vector.h>
+#include <wtf/text/AtomicString.h>
#include <wtf/text/WTFString.h>
namespace WTF {
class StringBuilder {
+ // Disallow copying since it's expensive and we don't want code to do it by accident.
+ WTF_MAKE_NONCOPYABLE(StringBuilder);
+
public:
StringBuilder()
: m_length(0)
@@ -41,8 +45,8 @@ public:
{
}
- void append(const UChar*, unsigned);
- void append(const LChar*, unsigned);
+ WTF_EXPORT_PRIVATE void append(const UChar*, unsigned);
+ WTF_EXPORT_PRIVATE void append(const LChar*, unsigned);
ALWAYS_INLINE void append(const char* characters, unsigned length) { append(reinterpret_cast<const LChar*>(characters), length); }
@@ -51,9 +55,8 @@ public:
if (!string.length())
return;
- // If we're appending to an empty string, and there is not buffer
- // (in case reserveCapacity has been called) then just retain the
- // string.
+ // If we're appending to an empty string, and there is not a buffer (reserveCapacity has not been called)
+ // then just retain the string.
if (!m_length && !m_buffer) {
m_string = string;
m_length = string.length();
@@ -67,6 +70,36 @@ public:
append(string.characters16(), string.length());
}
+ void append(const StringBuilder& other)
+ {
+ if (!other.m_length)
+ return;
+
+ // If we're appending to an empty string, and there is not a buffer (reserveCapacity has not been called)
+ // then just retain the string.
+ if (!m_length && !m_buffer && !other.m_string.isNull()) {
+ m_string = other.m_string;
+ m_length = other.m_length;
+ return;
+ }
+
+ append(other.characters(), other.m_length);
+ }
+
+ void append(const String& string, unsigned offset, unsigned length)
+ {
+ if (!string.length())
+ return;
+
+ if ((offset + length) > string.length())
+ return;
+
+ if (string.is8Bit())
+ append(string.characters8() + offset, length);
+ else
+ append(string.characters16() + offset, length);
+ }
+
void append(const char* characters)
{
if (characters)
@@ -94,44 +127,59 @@ public:
void append(char c)
{
- if (m_buffer && m_length < m_buffer->length() && m_string.isNull()) {
- if (m_is8Bit)
- m_bufferCharacters8[m_length++] = (LChar)c;
- else
- m_bufferCharacters16[m_length++] = (LChar)c;
- }
- else
- append(&c, 1);
+ append(static_cast<LChar>(c));
}
String toString()
{
- if (m_string.isNull()) {
- shrinkToFit();
+ shrinkToFit();
+ if (m_string.isNull())
reifyString();
- }
return m_string;
}
- String toStringPreserveCapacity()
+ const String& toStringPreserveCapacity() const
{
if (m_string.isNull())
reifyString();
return m_string;
}
+ AtomicString toAtomicString() const
+ {
+ if (!m_length)
+ return AtomicString();
+
+ // If the buffer is sufficiently over-allocated, make a new AtomicString from a copy so its buffer is not so large.
+ if (canShrink())
+ return AtomicString(characters(), length());
+
+ if (!m_string.isNull())
+ return AtomicString(m_string);
+
+ ASSERT(m_buffer);
+ return AtomicString(m_buffer.get(), 0, m_length);
+ }
+
unsigned length() const
{
return m_length;
}
- bool isEmpty() const { return !length(); }
+ bool isEmpty() const { return !m_length; }
- void reserveCapacity(unsigned newCapacity);
+ WTF_EXPORT_PRIVATE void reserveCapacity(unsigned newCapacity);
- void resize(unsigned newSize);
+ unsigned capacity() const
+ {
+ return m_buffer ? m_buffer->length() : m_length;
+ }
+
+ WTF_EXPORT_PRIVATE void resize(unsigned newSize);
+
+ WTF_EXPORT_PRIVATE bool canShrink() const;
- void shrinkToFit();
+ WTF_EXPORT_PRIVATE void shrinkToFit();
UChar operator[](unsigned i) const
{
@@ -178,6 +226,8 @@ public:
return m_buffer->characters();
}
+ bool is8Bit() const { return m_is8Bit; }
+
void clear()
{
m_length = 0;
@@ -188,6 +238,16 @@ public:
m_valid16BitShadowLength = 0;
}
+ void swap(StringBuilder& stringBuilder)
+ {
+ std::swap(m_length, stringBuilder.m_length);
+ m_string.swap(stringBuilder.m_string);
+ m_buffer.swap(stringBuilder.m_buffer);
+ std::swap(m_is8Bit, stringBuilder.m_is8Bit);
+ std::swap(m_valid16BitShadowLength, stringBuilder.m_valid16BitShadowLength);
+ std::swap(m_bufferCharacters8, stringBuilder.m_bufferCharacters8);
+ }
+
private:
void allocateBuffer(const LChar* currentCharacters, unsigned requiredLength);
void allocateBuffer(const UChar* currentCharacters, unsigned requiredLength);
@@ -200,10 +260,10 @@ private:
CharType* appendUninitializedSlow(unsigned length);
template <typename CharType>
ALWAYS_INLINE CharType * getBufferCharacters();
- void reifyString();
+ WTF_EXPORT_PRIVATE void reifyString() const;
unsigned m_length;
- String m_string;
+ mutable String m_string;
RefPtr<StringImpl> m_buffer;
bool m_is8Bit;
mutable unsigned m_valid16BitShadowLength;
@@ -227,6 +287,45 @@ ALWAYS_INLINE UChar* StringBuilder::getBufferCharacters<UChar>()
return m_bufferCharacters16;
}
+template <typename CharType>
+bool equal(const StringBuilder& s, const CharType* buffer, unsigned length)
+{
+ if (s.length() != length)
+ return false;
+
+ if (s.is8Bit())
+ return equal(s.characters8(), buffer, length);
+
+ return equal(s.characters16(), buffer, length);
+}
+
+template <typename StringType>
+bool equal(const StringBuilder& a, const StringType& b)
+{
+ if (a.length() != b.length())
+ return false;
+
+ if (!a.length())
+ return true;
+
+ if (a.is8Bit()) {
+ if (b.is8Bit())
+ return equal(a.characters8(), b.characters8(), a.length());
+ return equal(a.characters8(), b.characters16(), a.length());
+ }
+
+ if (b.is8Bit())
+ return equal(a.characters16(), b.characters8(), a.length());
+ return equal(a.characters16(), b.characters16(), a.length());
+}
+
+inline bool operator==(const StringBuilder& a, const StringBuilder& b) { return equal(a, b); }
+inline bool operator!=(const StringBuilder& a, const StringBuilder& b) { return !equal(a, b); }
+inline bool operator==(const StringBuilder& a, const String& b) { return equal(a, b); }
+inline bool operator!=(const StringBuilder& a, const String& b) { return !equal(a, b); }
+inline bool operator==(const String& a, const StringBuilder& b) { return equal(b, a); }
+inline bool operator!=(const String& a, const StringBuilder& b) { return !equal(b, a); }
+
} // namespace WTF
using WTF::StringBuilder;
diff --git a/Source/JavaScriptCore/wtf/text/StringHash.h b/Source/JavaScriptCore/wtf/text/StringHash.h
index cde591c18..1b7a2ee2c 100644
--- a/Source/JavaScriptCore/wtf/text/StringHash.h
+++ b/Source/JavaScriptCore/wtf/text/StringHash.h
@@ -100,7 +100,9 @@ namespace WTF {
static unsigned hash(StringImpl* str)
{
- return hash(str->characters(), str->length());
+ if (str->is8Bit())
+ return hash(str->characters8(), str->length());
+ return hash(str->characters16(), str->length());
}
static unsigned hash(const LChar* data, unsigned length)
diff --git a/Source/JavaScriptCore/wtf/text/StringImpl.cpp b/Source/JavaScriptCore/wtf/text/StringImpl.cpp
index aa5a8d56e..3f73556b5 100644
--- a/Source/JavaScriptCore/wtf/text/StringImpl.cpp
+++ b/Source/JavaScriptCore/wtf/text/StringImpl.cpp
@@ -30,6 +30,8 @@
#include "StringHash.h"
#include <wtf/StdLibExtras.h>
#include <wtf/WTFThreadData.h>
+#include <wtf/unicode/CharacterNames.h>
+
using namespace std;
@@ -378,19 +380,53 @@ PassRefPtr<StringImpl> StringImpl::upper()
return newImpl.release();
// Do a slower implementation for cases that include non-ASCII Latin-1 characters.
- for (int32_t i = 0; i < length; i++)
- data8[i] = static_cast<LChar>(Unicode::toUpper(m_data8[i]));
+ int numberSharpSCharacters = 0;
+
+ // There are two special cases.
+ // 1. latin-1 characters when converted to upper case are 16 bit characters.
+ // 2. Lower case sharp-S converts to "SS" (two characters)
+ for (int32_t i = 0; i < length; i++) {
+ LChar c = m_data8[i];
+ if (UNLIKELY(c == smallLetterSharpS))
+ numberSharpSCharacters++;
+ UChar upper = Unicode::toUpper(c);
+ if (UNLIKELY(upper > 0xff)) {
+ // Since this upper-cased character does not fit in an 8-bit string, we need to take the 16-bit path.
+ goto upconvert;
+ }
+ data8[i] = static_cast<LChar>(upper);
+ }
+
+ if (!numberSharpSCharacters)
+ return newImpl.release();
+
+ // We have numberSSCharacters sharp-s characters, but none of the other special characters.
+ newImpl = createUninitialized(m_length + numberSharpSCharacters, data8);
+
+ LChar* dest = data8;
+
+ for (int32_t i = 0; i < length; i++) {
+ LChar c = m_data8[i];
+ if (c == smallLetterSharpS) {
+ *dest++ = 'S';
+ *dest++ = 'S';
+ } else
+ *dest++ = static_cast<LChar>(Unicode::toUpper(c));
+ }
return newImpl.release();
}
+upconvert:
+ const UChar* source16 = characters();
+
UChar* data16;
RefPtr<StringImpl> newImpl = createUninitialized(m_length, data16);
// Do a faster loop for the case where all the characters are ASCII.
UChar ored = 0;
for (int i = 0; i < length; i++) {
- UChar c = m_data16[i];
+ UChar c = source16[i];
ored |= c;
data16[i] = toASCIIUpper(c);
}
@@ -400,11 +436,11 @@ PassRefPtr<StringImpl> StringImpl::upper()
// Do a slower implementation for cases that include non-ASCII characters.
bool error;
newImpl = createUninitialized(m_length, data16);
- int32_t realLength = Unicode::toUpper(data16, length, m_data16, m_length, &error);
+ int32_t realLength = Unicode::toUpper(data16, length, source16, m_length, &error);
if (!error && realLength == length)
return newImpl;
newImpl = createUninitialized(realLength, data16);
- Unicode::toUpper(data16, realLength, m_data16, m_length, &error);
+ Unicode::toUpper(data16, realLength, source16, m_length, &error);
if (error)
return this;
return newImpl.release();
@@ -715,6 +751,16 @@ float StringImpl::toFloat(bool* ok, bool* didReadNumber)
return charactersToFloat(characters16(), m_length, ok, didReadNumber);
}
+bool equalIgnoringCase(const LChar* a, const LChar* b, unsigned length)
+{
+ while (length--) {
+ LChar bc = *b++;
+ if (foldCase(*a++) != foldCase(bc))
+ return false;
+ }
+ return true;
+}
+
bool equalIgnoringCase(const UChar* a, const LChar* b, unsigned length)
{
while (length--) {
@@ -849,6 +895,35 @@ size_t StringImpl::findIgnoringCase(const LChar* matchString, unsigned index)
return index + i;
}
+template <typename CharType>
+ALWAYS_INLINE static size_t findInner(const CharType* searchCharacters, const CharType* matchCharacters, unsigned index, unsigned searchLength, unsigned matchLength)
+{
+ // Optimization: keep a running hash of the strings,
+ // only call memcmp if the hashes match.
+
+ // delta is the number of additional times to test; delta == 0 means test only once.
+ unsigned delta = searchLength - matchLength;
+
+ unsigned searchHash = 0;
+ unsigned matchHash = 0;
+
+ for (unsigned i = 0; i < matchLength; ++i) {
+ searchHash += searchCharacters[i];
+ matchHash += matchCharacters[i];
+ }
+
+ unsigned i = 0;
+ // keep looping until we match
+ while (searchHash != matchHash || memcmp(searchCharacters + i, matchCharacters, matchLength * sizeof(CharType))) {
+ if (i == delta)
+ return notFound;
+ searchHash += searchCharacters[i + matchLength];
+ searchHash -= searchCharacters[i];
+ ++i;
+ }
+ return index + i;
+}
+
size_t StringImpl::find(StringImpl* matchString, unsigned index)
{
// Check for null or empty string to match against
@@ -871,31 +946,12 @@ size_t StringImpl::find(StringImpl* matchString, unsigned index)
unsigned searchLength = length() - index;
if (matchLength > searchLength)
return notFound;
- // delta is the number of additional times to test; delta == 0 means test only once.
- unsigned delta = searchLength - matchLength;
- const UChar* searchCharacters = characters() + index;
- const UChar* matchCharacters = matchString->characters();
+ if (is8Bit() && matchString->is8Bit())
+ return findInner(characters8() + index, matchString->characters8(), index, searchLength, matchLength);
- // Optimization 2: keep a running hash of the strings,
- // only call memcmp if the hashes match.
- unsigned searchHash = 0;
- unsigned matchHash = 0;
- for (unsigned i = 0; i < matchLength; ++i) {
- searchHash += searchCharacters[i];
- matchHash += matchCharacters[i];
- }
+ return findInner(characters() + index, matchString->characters(), index, searchLength, matchLength);
- unsigned i = 0;
- // keep looping until we match
- while (searchHash != matchHash || memcmp(searchCharacters + i, matchCharacters, matchLength * sizeof(UChar))) {
- if (i == delta)
- return notFound;
- searchHash += searchCharacters[i + matchLength];
- searchHash -= searchCharacters[i];
- ++i;
- }
- return index + i;
}
size_t StringImpl::findIgnoringCase(StringImpl* matchString, unsigned index)
@@ -936,33 +992,15 @@ size_t StringImpl::reverseFind(UChar c, unsigned index)
return WTF::reverseFind(characters16(), m_length, c, index);
}
-size_t StringImpl::reverseFind(StringImpl* matchString, unsigned index)
+template <typename CharType>
+ALWAYS_INLINE static size_t reverseFindInner(const CharType* searchCharacters, const CharType* matchCharacters, unsigned index, unsigned length, unsigned matchLength)
{
- // Check for null or empty string to match against
- if (!matchString)
- return notFound;
- unsigned matchLength = matchString->length();
- if (!matchLength)
- return min(index, length());
-
- // Optimization 1: fast case for strings of length 1.
- if (matchLength == 1) {
- if (is8Bit() && matchString->is8Bit())
- return WTF::reverseFind(characters8(), length(), matchString->characters8()[0], index);
- return WTF::reverseFind(characters(), length(), matchString->characters()[0], index);
- }
+ // Optimization: keep a running hash of the strings,
+ // only call memcmp if the hashes match.
- // Check index & matchLength are in range.
- if (matchLength > length())
- return notFound;
// delta is the number of additional times to test; delta == 0 means test only once.
- unsigned delta = min(index, length() - matchLength);
-
- const UChar *searchCharacters = characters();
- const UChar *matchCharacters = matchString->characters();
-
- // Optimization 2: keep a running hash of the strings,
- // only call memcmp if the hashes match.
+ unsigned delta = min(index, length - matchLength);
+
unsigned searchHash = 0;
unsigned matchHash = 0;
for (unsigned i = 0; i < matchLength; ++i) {
@@ -971,7 +1009,7 @@ size_t StringImpl::reverseFind(StringImpl* matchString, unsigned index)
}
// keep looping until we match
- while (searchHash != matchHash || memcmp(searchCharacters + delta, matchCharacters, matchLength * sizeof(UChar))) {
+ while (searchHash != matchHash || memcmp(searchCharacters + delta, matchCharacters, matchLength * sizeof(CharType))) {
if (!delta)
return notFound;
delta--;
@@ -981,6 +1019,33 @@ size_t StringImpl::reverseFind(StringImpl* matchString, unsigned index)
return delta;
}
+size_t StringImpl::reverseFind(StringImpl* matchString, unsigned index)
+{
+ // Check for null or empty string to match against
+ if (!matchString)
+ return notFound;
+ unsigned matchLength = matchString->length();
+ unsigned ourLength = length();
+ if (!matchLength)
+ return min(index, ourLength);
+
+ // Optimization 1: fast case for strings of length 1.
+ if (matchLength == 1) {
+ if (is8Bit() && matchString->is8Bit())
+ return WTF::reverseFind(characters8(), ourLength, matchString->characters8()[0], index);
+ return WTF::reverseFind(characters(), ourLength, matchString->characters()[0], index);
+ }
+
+ // Check index & matchLength are in range.
+ if (matchLength > ourLength)
+ return notFound;
+
+ if (is8Bit() && matchString->is8Bit())
+ return reverseFindInner(characters8(), matchString->characters8(), index, ourLength, matchLength);
+
+ return reverseFindInner(characters(), matchString->characters(), index, ourLength, matchLength);
+}
+
size_t StringImpl::reverseFindIgnoringCase(StringImpl* matchString, unsigned index)
{
// Check for null or empty string to match against
@@ -995,7 +1060,20 @@ size_t StringImpl::reverseFindIgnoringCase(StringImpl* matchString, unsigned ind
return notFound;
// delta is the number of additional times to test; delta == 0 means test only once.
unsigned delta = min(index, length() - matchLength);
-
+
+ if (is8Bit() && matchString->is8Bit()) {
+ const LChar *searchCharacters = characters8();
+ const LChar *matchCharacters = matchString->characters8();
+
+ // keep looping until we match
+ while (!equalIgnoringCase(searchCharacters + delta, matchCharacters, matchLength)) {
+ if (!delta)
+ return notFound;
+ delta--;
+ }
+ return delta;
+ }
+
const UChar *searchCharacters = characters();
const UChar *matchCharacters = matchString->characters();
diff --git a/Source/JavaScriptCore/wtf/text/StringImpl.h b/Source/JavaScriptCore/wtf/text/StringImpl.h
index 003c44ce6..3862effb6 100644
--- a/Source/JavaScriptCore/wtf/text/StringImpl.h
+++ b/Source/JavaScriptCore/wtf/text/StringImpl.h
@@ -52,6 +52,7 @@ namespace WTF {
struct CStringTranslator;
struct HashAndCharactersTranslator;
struct HashAndUTF8CharactersTranslator;
+struct SubstringTranslator;
struct UCharBufferTranslator;
enum TextCaseSensitivity { TextCaseSensitive, TextCaseInsensitive };
@@ -68,6 +69,7 @@ class StringImpl {
friend struct WTF::CStringTranslator;
friend struct WTF::HashAndCharactersTranslator;
friend struct WTF::HashAndUTF8CharactersTranslator;
+ friend struct WTF::SubstringTranslator;
friend struct WTF::UCharBufferTranslator;
friend class AtomicStringImpl;
@@ -190,12 +192,12 @@ private:
}
public:
- ~StringImpl();
+ WTF_EXPORT_PRIVATE ~StringImpl();
- static PassRefPtr<StringImpl> create(const UChar*, unsigned length);
+ WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> create(const UChar*, unsigned length);
static PassRefPtr<StringImpl> create(const LChar*, unsigned length);
ALWAYS_INLINE static PassRefPtr<StringImpl> create(const char* s, unsigned length) { return create(reinterpret_cast<const LChar*>(s), length); }
- static PassRefPtr<StringImpl> create(const LChar*);
+ WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> create(const LChar*);
ALWAYS_INLINE static PassRefPtr<StringImpl> create(const char* s) { return create(reinterpret_cast<const LChar*>(s)); }
static ALWAYS_INLINE PassRefPtr<StringImpl> create8(PassRefPtr<StringImpl> rep, unsigned offset, unsigned length)
@@ -226,7 +228,7 @@ public:
}
static PassRefPtr<StringImpl> createUninitialized(unsigned length, LChar*& data);
- static PassRefPtr<StringImpl> createUninitialized(unsigned length, UChar*& data);
+ WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> createUninitialized(unsigned length, UChar*& data);
template <typename T> static ALWAYS_INLINE PassRefPtr<StringImpl> tryCreateUninitialized(unsigned length, T*& output)
{
if (!length) {
@@ -275,7 +277,7 @@ public:
}
static PassRefPtr<StringImpl> adopt(StringBuffer<LChar>& buffer);
- static PassRefPtr<StringImpl> adopt(StringBuffer<UChar>& buffer);
+ WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> adopt(StringBuffer<UChar>& buffer);
unsigned length() const { return m_length; }
bool is8Bit() const { return m_hashAndFlags & s_hashFlag8BitBuffer; }
@@ -308,7 +310,7 @@ public:
}
bool has16BitShadow() const { return m_hashAndFlags & s_hashFlagHas16BitShadow; }
- void upconvertCharacters(unsigned, unsigned) const;
+ WTF_EXPORT_PRIVATE void upconvertCharacters(unsigned, unsigned) const;
bool isIdentifier() const { return m_hashAndFlags & s_hashFlagIsIdentifier; }
void setIsIdentifier(bool isIdentifier)
{
@@ -393,7 +395,7 @@ public:
m_refCount -= s_refCountIncrement;
}
- static StringImpl* empty();
+ WTF_EXPORT_PRIVATE static StringImpl* empty();
// FIXME: Does this really belong in StringImpl?
template <typename T> static void copyChars(T* destination, const T* source, unsigned numCharacters)
@@ -428,7 +430,7 @@ public:
// its own copy of the string.
PassRefPtr<StringImpl> isolatedCopy() const;
- PassRefPtr<StringImpl> substring(unsigned pos, unsigned len = UINT_MAX);
+ WTF_EXPORT_PRIVATE PassRefPtr<StringImpl> substring(unsigned pos, unsigned len = UINT_MAX);
UChar operator[](unsigned i) const
{
@@ -437,9 +439,9 @@ public:
return m_data8[i];
return m_data16[i];
}
- UChar32 characterStartingAt(unsigned);
+ WTF_EXPORT_PRIVATE UChar32 characterStartingAt(unsigned);
- bool containsOnlyWhitespace();
+ WTF_EXPORT_PRIVATE bool containsOnlyWhitespace();
int toIntStrict(bool* ok = 0, int base = 10);
unsigned toUIntStrict(bool* ok = 0, int base = 10);
@@ -447,7 +449,7 @@ public:
uint64_t toUInt64Strict(bool* ok = 0, int base = 10);
intptr_t toIntPtrStrict(bool* ok = 0, int base = 10);
- int toInt(bool* ok = 0); // ignores trailing garbage
+ WTF_EXPORT_PRIVATE int toInt(bool* ok = 0); // ignores trailing garbage
unsigned toUInt(bool* ok = 0); // ignores trailing garbage
int64_t toInt64(bool* ok = 0); // ignores trailing garbage
uint64_t toUInt64(bool* ok = 0); // ignores trailing garbage
@@ -456,44 +458,44 @@ public:
double toDouble(bool* ok = 0, bool* didReadNumber = 0);
float toFloat(bool* ok = 0, bool* didReadNumber = 0);
- PassRefPtr<StringImpl> lower();
- PassRefPtr<StringImpl> upper();
+ WTF_EXPORT_PRIVATE PassRefPtr<StringImpl> lower();
+ WTF_EXPORT_PRIVATE PassRefPtr<StringImpl> upper();
- PassRefPtr<StringImpl> fill(UChar);
+ WTF_EXPORT_PRIVATE PassRefPtr<StringImpl> fill(UChar);
// FIXME: Do we need fill(char) or can we just do the right thing if UChar is ASCII?
PassRefPtr<StringImpl> foldCase();
PassRefPtr<StringImpl> stripWhiteSpace();
PassRefPtr<StringImpl> stripWhiteSpace(IsWhiteSpaceFunctionPtr);
- PassRefPtr<StringImpl> simplifyWhiteSpace();
+ WTF_EXPORT_PRIVATE PassRefPtr<StringImpl> simplifyWhiteSpace();
PassRefPtr<StringImpl> simplifyWhiteSpace(IsWhiteSpaceFunctionPtr);
PassRefPtr<StringImpl> removeCharacters(CharacterMatchFunctionPtr);
template <typename CharType>
ALWAYS_INLINE PassRefPtr<StringImpl> removeCharacters(const CharType* characters, CharacterMatchFunctionPtr);
- size_t find(UChar, unsigned index = 0);
- size_t find(CharacterMatchFunctionPtr, unsigned index = 0);
+ WTF_EXPORT_PRIVATE size_t find(UChar, unsigned index = 0);
+ WTF_EXPORT_PRIVATE size_t find(CharacterMatchFunctionPtr, unsigned index = 0);
size_t find(const LChar*, unsigned index = 0);
ALWAYS_INLINE size_t find(const char* s, unsigned index = 0) { return find(reinterpret_cast<const LChar*>(s), index); };
- size_t find(StringImpl*, unsigned index = 0);
+ WTF_EXPORT_PRIVATE size_t find(StringImpl*, unsigned index = 0);
size_t findIgnoringCase(const LChar*, unsigned index = 0);
ALWAYS_INLINE size_t findIgnoringCase(const char* s, unsigned index = 0) { return findIgnoringCase(reinterpret_cast<const LChar*>(s), index); };
- size_t findIgnoringCase(StringImpl*, unsigned index = 0);
+ WTF_EXPORT_PRIVATE size_t findIgnoringCase(StringImpl*, unsigned index = 0);
- size_t reverseFind(UChar, unsigned index = UINT_MAX);
- size_t reverseFind(StringImpl*, unsigned index = UINT_MAX);
- size_t reverseFindIgnoringCase(StringImpl*, unsigned index = UINT_MAX);
+ WTF_EXPORT_PRIVATE size_t reverseFind(UChar, unsigned index = UINT_MAX);
+ WTF_EXPORT_PRIVATE size_t reverseFind(StringImpl*, unsigned index = UINT_MAX);
+ WTF_EXPORT_PRIVATE size_t reverseFindIgnoringCase(StringImpl*, unsigned index = UINT_MAX);
bool startsWith(StringImpl* str, bool caseSensitive = true) { return (caseSensitive ? reverseFind(str, 0) : reverseFindIgnoringCase(str, 0)) == 0; }
- bool endsWith(StringImpl*, bool caseSensitive = true);
+ WTF_EXPORT_PRIVATE bool endsWith(StringImpl*, bool caseSensitive = true);
- PassRefPtr<StringImpl> replace(UChar, UChar);
- PassRefPtr<StringImpl> replace(UChar, StringImpl*);
- PassRefPtr<StringImpl> replace(StringImpl*, StringImpl*);
- PassRefPtr<StringImpl> replace(unsigned index, unsigned len, StringImpl*);
+ WTF_EXPORT_PRIVATE PassRefPtr<StringImpl> replace(UChar, UChar);
+ WTF_EXPORT_PRIVATE PassRefPtr<StringImpl> replace(UChar, StringImpl*);
+ WTF_EXPORT_PRIVATE PassRefPtr<StringImpl> replace(StringImpl*, StringImpl*);
+ WTF_EXPORT_PRIVATE PassRefPtr<StringImpl> replace(unsigned index, unsigned len, StringImpl*);
- WTF::Unicode::Direction defaultWritingDirection(bool* hasStrongDirectionality = 0);
+ WTF_EXPORT_PRIVATE WTF::Unicode::Direction defaultWritingDirection(bool* hasStrongDirectionality = 0);
#if USE(CF)
CFStringRef createCFString();
@@ -510,8 +512,8 @@ private:
bool isStatic() const { return m_refCount & s_refCountFlagIsStaticString; }
template <class UCharPredicate> PassRefPtr<StringImpl> stripMatchedCharacters(UCharPredicate);
template <typename CharType, class UCharPredicate> PassRefPtr<StringImpl> simplifyMatchedCharactersToSpace(UCharPredicate);
- NEVER_INLINE const UChar* getData16SlowCase() const;
- NEVER_INLINE unsigned hashSlowCase() const;
+ WTF_EXPORT_PRIVATE NEVER_INLINE const UChar* getData16SlowCase() const;
+ WTF_EXPORT_PRIVATE NEVER_INLINE unsigned hashSlowCase() const;
// The bottom bit in the ref count indicates a static (immortal) string.
static const unsigned s_refCountFlagIsStaticString = 0x1;
@@ -548,16 +550,16 @@ template <>
ALWAYS_INLINE const LChar* StringImpl::getCharacters<LChar>() const { return characters8(); }
template <>
-ALWAYS_INLINE const UChar* StringImpl::getCharacters<UChar>() const { return characters16(); }
+ALWAYS_INLINE const UChar* StringImpl::getCharacters<UChar>() const { return characters(); }
-bool equal(const StringImpl*, const StringImpl*);
-bool equal(const StringImpl*, const LChar*);
+WTF_EXPORT_PRIVATE bool equal(const StringImpl*, const StringImpl*);
+WTF_EXPORT_PRIVATE bool equal(const StringImpl*, const LChar*);
inline bool equal(const StringImpl* a, const char* b) { return equal(a, reinterpret_cast<const LChar*>(b)); }
-bool equal(const StringImpl*, const LChar*, unsigned);
+WTF_EXPORT_PRIVATE bool equal(const StringImpl*, const LChar*, unsigned);
inline bool equal(const StringImpl* a, const char* b, unsigned length) { return equal(a, reinterpret_cast<const LChar*>(b), length); }
inline bool equal(const LChar* a, StringImpl* b) { return equal(b, a); }
inline bool equal(const char* a, StringImpl* b) { return equal(b, reinterpret_cast<const LChar*>(a)); }
-bool equal(const StringImpl*, const UChar*, unsigned);
+WTF_EXPORT_PRIVATE bool equal(const StringImpl*, const UChar*, unsigned);
// Do comparisons 8 or 4 bytes-at-a-time on architectures where it's safe.
#if CPU(X86_64)
@@ -715,15 +717,16 @@ ALWAYS_INLINE bool equal(const UChar* a, const LChar* b, unsigned length)
return true;
}
-bool equalIgnoringCase(StringImpl*, StringImpl*);
-bool equalIgnoringCase(StringImpl*, const LChar*);
+WTF_EXPORT_PRIVATE bool equalIgnoringCase(StringImpl*, StringImpl*);
+WTF_EXPORT_PRIVATE bool equalIgnoringCase(StringImpl*, const LChar*);
inline bool equalIgnoringCase(const LChar* a, StringImpl* b) { return equalIgnoringCase(b, a); }
-bool equalIgnoringCase(const UChar*, const LChar*, unsigned);
+WTF_EXPORT_PRIVATE bool equalIgnoringCase(const LChar*, const LChar*, unsigned);
+WTF_EXPORT_PRIVATE bool equalIgnoringCase(const UChar*, const LChar*, unsigned);
inline bool equalIgnoringCase(const UChar* a, const char* b, unsigned length) { return equalIgnoringCase(a, reinterpret_cast<const LChar*>(b), length); }
inline bool equalIgnoringCase(const LChar* a, const UChar* b, unsigned length) { return equalIgnoringCase(b, a, length); }
inline bool equalIgnoringCase(const char* a, const UChar* b, unsigned length) { return equalIgnoringCase(b, reinterpret_cast<const LChar*>(a), length); }
-bool equalIgnoringNullity(StringImpl*, StringImpl*);
+WTF_EXPORT_PRIVATE bool equalIgnoringNullity(StringImpl*, StringImpl*);
template<size_t inlineCapacity>
bool equalIgnoringNullity(const Vector<UChar, inlineCapacity>& a, StringImpl* b)
@@ -735,7 +738,7 @@ bool equalIgnoringNullity(const Vector<UChar, inlineCapacity>& a, StringImpl* b)
return !memcmp(a.data(), b->characters(), b->length());
}
-int codePointCompare(const StringImpl*, const StringImpl*);
+WTF_EXPORT_PRIVATE int codePointCompare(const StringImpl*, const StringImpl*);
static inline bool isSpaceOrNewline(UChar c)
{
diff --git a/Source/JavaScriptCore/wtf/text/WTFString.cpp b/Source/JavaScriptCore/wtf/text/WTFString.cpp
index 4c42ed6a2..df74c65af 100644
--- a/Source/JavaScriptCore/wtf/text/WTFString.cpp
+++ b/Source/JavaScriptCore/wtf/text/WTFString.cpp
@@ -687,6 +687,13 @@ CString String::latin1() const
// preserved, characters outside of this range are converted to '?'.
unsigned length = this->length();
+
+ if (!length)
+ return CString("", 0);
+
+ if (is8Bit())
+ return CString(reinterpret_cast<const char*>(this->characters8()), length);
+
const UChar* characters = this->characters();
char* characterBuffer;
diff --git a/Source/JavaScriptCore/wtf/text/WTFString.h b/Source/JavaScriptCore/wtf/text/WTFString.h
index 3cecc0afd..2d32e6916 100644
--- a/Source/JavaScriptCore/wtf/text/WTFString.h
+++ b/Source/JavaScriptCore/wtf/text/WTFString.h
@@ -62,9 +62,9 @@ struct StringHash;
// Declarations of string operations
-WTF_EXPORT_PRIVATE int charactersToIntStrict(const LChar*, size_t, bool* ok = 0, int base = 10);
+int charactersToIntStrict(const LChar*, size_t, bool* ok = 0, int base = 10);
WTF_EXPORT_PRIVATE int charactersToIntStrict(const UChar*, size_t, bool* ok = 0, int base = 10);
-WTF_EXPORT_PRIVATE unsigned charactersToUIntStrict(const LChar*, size_t, bool* ok = 0, int base = 10);
+unsigned charactersToUIntStrict(const LChar*, size_t, bool* ok = 0, int base = 10);
WTF_EXPORT_PRIVATE unsigned charactersToUIntStrict(const UChar*, size_t, bool* ok = 0, int base = 10);
int64_t charactersToInt64Strict(const LChar*, size_t, bool* ok = 0, int base = 10);
int64_t charactersToInt64Strict(const UChar*, size_t, bool* ok = 0, int base = 10);
@@ -74,7 +74,7 @@ intptr_t charactersToIntPtrStrict(const LChar*, size_t, bool* ok = 0, int base =
intptr_t charactersToIntPtrStrict(const UChar*, size_t, bool* ok = 0, int base = 10);
int charactersToInt(const LChar*, size_t, bool* ok = 0); // ignores trailing garbage
-int charactersToInt(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage
+WTF_EXPORT_PRIVATE int charactersToInt(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage
unsigned charactersToUInt(const LChar*, size_t, bool* ok = 0); // ignores trailing garbage
unsigned charactersToUInt(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage
int64_t charactersToInt64(const LChar*, size_t, bool* ok = 0); // ignores trailing garbage
@@ -87,7 +87,7 @@ intptr_t charactersToIntPtr(const UChar*, size_t, bool* ok = 0); // ignores trai
WTF_EXPORT_PRIVATE double charactersToDouble(const LChar*, size_t, bool* ok = 0, bool* didReadNumber = 0);
WTF_EXPORT_PRIVATE double charactersToDouble(const UChar*, size_t, bool* ok = 0, bool* didReadNumber = 0);
float charactersToFloat(const LChar*, size_t, bool* ok = 0, bool* didReadNumber = 0);
-float charactersToFloat(const UChar*, size_t, bool* ok = 0, bool* didReadNumber = 0);
+WTF_EXPORT_PRIVATE float charactersToFloat(const UChar*, size_t, bool* ok = 0, bool* didReadNumber = 0);
enum FloatConversionFlags {
ShouldRoundSignificantFigures = 1 << 0,
@@ -187,7 +187,7 @@ public:
return m_impl->characters()[index];
}
- WTF_EXPORT_PRIVATE static String number(short);
+ static String number(short);
WTF_EXPORT_PRIVATE static String number(unsigned short);
WTF_EXPORT_PRIVATE static String number(int);
WTF_EXPORT_PRIVATE static String number(unsigned);
@@ -301,8 +301,8 @@ public:
WTF_EXPORT_PRIVATE int toIntStrict(bool* ok = 0, int base = 10) const;
WTF_EXPORT_PRIVATE unsigned toUIntStrict(bool* ok = 0, int base = 10) const;
WTF_EXPORT_PRIVATE int64_t toInt64Strict(bool* ok = 0, int base = 10) const;
- WTF_EXPORT_PRIVATE uint64_t toUInt64Strict(bool* ok = 0, int base = 10) const;
- WTF_EXPORT_PRIVATE intptr_t toIntPtrStrict(bool* ok = 0, int base = 10) const;
+ uint64_t toUInt64Strict(bool* ok = 0, int base = 10) const;
+ intptr_t toIntPtrStrict(bool* ok = 0, int base = 10) const;
WTF_EXPORT_PRIVATE int toInt(bool* ok = 0) const;
WTF_EXPORT_PRIVATE unsigned toUInt(bool* ok = 0) const;
diff --git a/Source/JavaScriptCore/wtf/unicode/CharacterNames.h b/Source/JavaScriptCore/wtf/unicode/CharacterNames.h
index 10fdbf0ef..4acb5f0b1 100644
--- a/Source/JavaScriptCore/wtf/unicode/CharacterNames.h
+++ b/Source/JavaScriptCore/wtf/unicode/CharacterNames.h
@@ -72,6 +72,7 @@ const UChar rightToLeftEmbed = 0x202B;
const UChar rightToLeftMark = 0x200F;
const UChar rightToLeftOverride = 0x202E;
const UChar sesameDot = 0xFE45;
+const UChar smallLetterSharpS = 0x00DF;
const UChar softHyphen = 0x00AD;
const UChar space = 0x0020;
const UChar tibetanMarkIntersyllabicTsheg = 0x0F0B;
diff --git a/Source/JavaScriptCore/wtf/unicode/Collator.h b/Source/JavaScriptCore/wtf/unicode/Collator.h
index 00ab16e6a..7994ff8e5 100644
--- a/Source/JavaScriptCore/wtf/unicode/Collator.h
+++ b/Source/JavaScriptCore/wtf/unicode/Collator.h
@@ -45,13 +45,13 @@ namespace WTF {
public:
enum Result { Equal = 0, Greater = 1, Less = -1 };
- Collator(const char* locale); // Parsing is lenient; e.g. language identifiers (such as "en-US") are accepted, too.
- ~Collator();
- void setOrderLowerFirst(bool);
+ WTF_EXPORT_PRIVATE Collator(const char* locale); // Parsing is lenient; e.g. language identifiers (such as "en-US") are accepted, too.
+ WTF_EXPORT_PRIVATE ~Collator();
+ WTF_EXPORT_PRIVATE void setOrderLowerFirst(bool);
static PassOwnPtr<Collator> userDefault();
- Result collate(const ::UChar*, size_t, const ::UChar*, size_t) const;
+ WTF_EXPORT_PRIVATE Result collate(const ::UChar*, size_t, const ::UChar*, size_t) const;
private:
#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION
diff --git a/Source/JavaScriptCore/wtf/unicode/UTF8.h b/Source/JavaScriptCore/wtf/unicode/UTF8.h
index bd3dd8a0a..bc2497b72 100644
--- a/Source/JavaScriptCore/wtf/unicode/UTF8.h
+++ b/Source/JavaScriptCore/wtf/unicode/UTF8.h
@@ -62,7 +62,7 @@ namespace Unicode {
// to the replacement character; otherwise (when the flag is set to strict)
// they constitute an error.
- ConversionResult convertUTF8ToUTF16(
+ WTF_EXPORT_PRIVATE ConversionResult convertUTF8ToUTF16(
const char** sourceStart, const char* sourceEnd,
UChar** targetStart, UChar* targetEnd, bool strict = true);
@@ -70,7 +70,7 @@ namespace Unicode {
const LChar** sourceStart, const LChar* sourceEnd,
char** targetStart, char* targetEnd);
- ConversionResult convertUTF16ToUTF8(
+ WTF_EXPORT_PRIVATE ConversionResult convertUTF16ToUTF8(
const UChar** sourceStart, const UChar* sourceEnd,
char** targetStart, char* targetEnd, bool strict = true);
diff --git a/Source/JavaScriptCore/wtf/wtf.pri b/Source/JavaScriptCore/wtf/wtf.pri
deleted file mode 100644
index 176949f75..000000000
--- a/Source/JavaScriptCore/wtf/wtf.pri
+++ /dev/null
@@ -1,42 +0,0 @@
-# -------------------------------------------------------------------
-# This file contains shared rules used both when building WTF itself
-# and for targets that depend in some way on WTF.
-#
-# See 'Tools/qmake/README' for an overview of the build system
-# -------------------------------------------------------------------
-
-load(features)
-
-SOURCE_DIR = $${ROOT_WEBKIT_DIR}/Source/JavaScriptCore/wtf
-
-INCLUDEPATH += \
- $$SOURCE_DIR/.. \
- $$SOURCE_DIR \
- $$SOURCE_DIR/gobject \
- $$SOURCE_DIR/qt \
- $$SOURCE_DIR/unicode
-
-contains(CONFIG, use_system_icu) {
- DEFINES += WTF_USE_ICU_UNICODE=1
- DEFINES -= WTF_USE_QT4_UNICODE
- LIBS += -licuuc -licui18n
-} else {
- DEFINES += WTF_USE_QT4_UNICODE=1
- DEFINES -= WTF_USE_ICU_UNICODE
-}
-
-v8 {
- !haveQt(5): error("To build QtWebKit+V8 you need to use Qt 5")
- DEFINES *= WTF_USE_V8=1
- INCLUDEPATH += $${ROOT_WEBKIT_DIR}/Source/WebKit/qt/v8/ForwardingHeaders
- QT += v8-private declarative
-}
-
-linux-*:!contains(DEFINES, USE_QTMULTIMEDIA=1) {
- !contains(QT_CONFIG, no-pkg-config):system(pkg-config --exists glib-2.0 gio-2.0 gstreamer-0.10): {
- DEFINES += ENABLE_GLIB_SUPPORT=1
- PKGCONFIG += glib-2.0 gio-2.0
- }
-}
-
-win32-*: LIBS += -lwinmm
diff --git a/Source/JavaScriptCore/wtf/wtf.pro b/Source/JavaScriptCore/wtf/wtf.pro
deleted file mode 100644
index 234348f2b..000000000
--- a/Source/JavaScriptCore/wtf/wtf.pro
+++ /dev/null
@@ -1,252 +0,0 @@
-# -------------------------------------------------------------------
-# Project file for WTF
-#
-# See 'Tools/qmake/README' for an overview of the build system
-# -------------------------------------------------------------------
-
-TEMPLATE = lib
-TARGET = WTF
-
-include(wtf.pri)
-
-CONFIG += staticlib
-
-QT += core
-QT -= gui
-
-*-g++*:QMAKE_CXXFLAGS_RELEASE -= -O2
-*-g++*:QMAKE_CXXFLAGS_RELEASE += -O3
-
-HEADERS += \
- Alignment.h \
- AlwaysInline.h \
- ArrayBuffer.h \
- ArrayBufferView.h \
- ASCIICType.h \
- Assertions.h \
- Atomics.h \
- AVLTree.h \
- Bitmap.h \
- BitVector.h \
- BloomFilter.h \
- BoundsCheckedPointer.h \
- BumpPointerAllocator.h \
- ByteArray.h \
- CheckedArithmetic.h \
- Compiler.h \
- CryptographicallyRandomNumber.h \
- CurrentTime.h \
- DateMath.h \
- DecimalNumber.h \
- Decoder.h \
- Deque.h \
- DisallowCType.h \
- dtoa.h \
- dtoa/bignum-dtoa.h \
- dtoa/bignum.h \
- dtoa/cached-powers.h \
- dtoa/diy-fp.h \
- dtoa/double-conversion.h \
- dtoa/double.h \
- dtoa/fast-dtoa.h \
- dtoa/fixed-dtoa.h \
- dtoa/strtod.h \
- dtoa/utils.h \
- DynamicAnnotations.h \
- Encoder.h \
- FastAllocBase.h \
- FastMalloc.h \
- FixedArray.h \
- Float32Array.h \
- Float64Array.h \
- Forward.h \
- Functional.h \
- GetPtr.h \
- HashCountedSet.h \
- HashFunctions.h \
- HashIterators.h \
- HashMap.h \
- HashSet.h \
- HashTable.h \
- HashTraits.h \
- HexNumber.h \
- Int16Array.h \
- Int32Array.h \
- Int8Array.h \
- ListHashSet.h \
- ListRefPtr.h \
- Locker.h \
- MainThread.h \
- MallocZoneSupport.h \
- MathExtras.h \
- MD5.h \
- MessageQueue.h \
- MetaAllocator.h \
- MetaAllocatorHandle.h \
- Noncopyable.h \
- NonCopyingSort.h \
- NotFound.h \
- NullPtr.h \
- OSAllocator.h \
- OSRandomSource.h \
- OwnArrayPtr.h \
- OwnPtr.h \
- OwnPtrCommon.h \
- PackedIntVector.h \
- PageAllocation.h \
- PageAllocationAligned.h \
- PageBlock.h \
- PageReservation.h \
- ParallelJobs.h \
- ParallelJobsGeneric.h \
- ParallelJobsLibdispatch.h \
- ParallelJobsOpenMP.h \
- PassOwnArrayPtr.h \
- PassOwnPtr.h \
- PassRefPtr.h \
- PassTraits.h \
- Platform.h \
- PossiblyNull.h \
- qt/UtilsQt.h \
- RandomNumber.h \
- RandomNumberSeed.h \
- RedBlackTree.h \
- RefCounted.h \
- RefCountedLeakCounter.h \
- RefPtr.h \
- RefPtrHashMap.h \
- RetainPtr.h \
- SHA1.h \
- Spectrum.h \
- StackBounds.h \
- StaticConstructors.h \
- StdLibExtras.h \
- StringExtras.h \
- StringHasher.h \
- TCPackedCache.h \
- TCSpinLock.h \
- TCSystemAlloc.h \
- text/ASCIIFastPath.h \
- text/AtomicString.h \
- text/AtomicStringHash.h \
- text/AtomicStringImpl.h \
- text/CString.h \
- text/StringBuffer.h \
- text/StringBuilder.h \
- text/StringConcatenate.h \
- text/StringHash.h \
- text/StringImpl.h \
- text/StringOperators.h \
- text/TextPosition.h \
- text/WTFString.h \
- Threading.h \
- ThreadingPrimitives.h \
- ThreadRestrictionVerifier.h \
- ThreadSafeRefCounted.h \
- ThreadSpecific.h \
- TypeTraits.h \
- Uint16Array.h \
- Uint32Array.h \
- Uint8Array.h \
- unicode/CharacterNames.h \
- unicode/Collator.h \
- unicode/icu/UnicodeIcu.h \
- unicode/qt4/UnicodeQt4.h \
- unicode/ScriptCodesFromICU.h \
- unicode/Unicode.h \
- unicode/UnicodeMacrosFromICU.h \
- unicode/UTF8.h \
- UnusedParam.h \
- ValueCheck.h \
- Vector.h \
- VectorTraits.h \
- VMTags.h \
- WTFThreadData.h
-
-
-unix: HEADERS += ThreadIdentifierDataPthreads.h
-
-SOURCES += \
- ArrayBuffer.cpp \
- ArrayBufferView.cpp \
- Assertions.cpp \
- BitVector.cpp \
- ByteArray.cpp \
- CryptographicallyRandomNumber.cpp \
- CurrentTime.cpp \
- DateMath.cpp \
- DecimalNumber.cpp \
- dtoa.cpp \
- dtoa/bignum-dtoa.cc \
- dtoa/bignum.cc \
- dtoa/cached-powers.cc \
- dtoa/diy-fp.cc \
- dtoa/double-conversion.cc \
- dtoa/fast-dtoa.cc \
- dtoa/fixed-dtoa.cc \
- dtoa/strtod.cc \
- FastMalloc.cpp \
- gobject/GOwnPtr.cpp \
- gobject/GRefPtr.cpp \
- HashTable.cpp \
- MD5.cpp \
- MainThread.cpp \
- MetaAllocator.cpp \
- NullPtr.cpp \
- OSRandomSource.cpp \
- qt/MainThreadQt.cpp \
- qt/StringQt.cpp \
- PageAllocationAligned.cpp \
- PageBlock.cpp \
- ParallelJobsGeneric.cpp \
- RandomNumber.cpp \
- RefCountedLeakCounter.cpp \
- SHA1.cpp \
- StackBounds.cpp \
- TCSystemAlloc.cpp \
- Threading.cpp \
- TypeTraits.cpp \
- WTFThreadData.cpp \
- text/AtomicString.cpp \
- text/CString.cpp \
- text/StringBuilder.cpp \
- text/StringImpl.cpp \
- text/StringStatics.cpp \
- text/WTFString.cpp \
- unicode/CollatorDefault.cpp \
- unicode/icu/CollatorICU.cpp \
- unicode/UTF8.cpp
-
-unix: SOURCES += \
- OSAllocatorPosix.cpp \
- ThreadIdentifierDataPthreads.cpp \
- ThreadingPthreads.cpp
-
-win*|wince*: SOURCES += \
- OSAllocatorWin.cpp \
- ThreadSpecificWin.cpp \
- ThreadingWin.cpp
-
-*sh4* {
- QMAKE_CXXFLAGS += -mieee -w
- QMAKE_CFLAGS += -mieee -w
-}
-
-lessThan(QT_GCC_MAJOR_VERSION, 5) {
- # GCC 4.5 and before
- lessThan(QT_GCC_MINOR_VERSION, 6) {
- # Disable C++0x mode in JSC for those who enabled it in their Qt's mkspec.
- *-g++*:QMAKE_CXXFLAGS -= -std=c++0x -std=gnu++0x
- }
-
- # GCC 4.6 and after.
- greaterThan(QT_GCC_MINOR_VERSION, 5) {
- if (!contains(QMAKE_CXXFLAGS, -std=c++0x) && !contains(QMAKE_CXXFLAGS, -std=gnu++0x)) {
- # We need to deactivate those warnings because some names conflicts with upcoming c++0x types (e.g.nullptr).
- QMAKE_CFLAGS_WARN_ON += -Wno-c++0x-compat
- QMAKE_CXXFLAGS_WARN_ON += -Wno-c++0x-compat
- QMAKE_CFLAGS += -Wno-c++0x-compat
- QMAKE_CXXFLAGS += -Wno-c++0x-compat
- }
- }
-}
diff --git a/Source/JavaScriptCore/yarr/Yarr.h b/Source/JavaScriptCore/yarr/Yarr.h
index 501afac5f..3495fc7e4 100644
--- a/Source/JavaScriptCore/yarr/Yarr.h
+++ b/Source/JavaScriptCore/yarr/Yarr.h
@@ -62,8 +62,8 @@ enum YarrCharSize {
Char16
};
-PassOwnPtr<BytecodePattern> byteCompile(YarrPattern&, BumpPointerAllocator*);
-int interpret(BytecodePattern*, const UString& input, unsigned start, unsigned length, int* output);
+JS_EXPORT_PRIVATE PassOwnPtr<BytecodePattern> byteCompile(YarrPattern&, BumpPointerAllocator*);
+JS_EXPORT_PRIVATE int interpret(BytecodePattern*, const UString& input, unsigned start, unsigned length, int* output);
} } // namespace JSC::Yarr
diff --git a/Source/JavaScriptCore/yarr/YarrInterpreter.cpp b/Source/JavaScriptCore/yarr/YarrInterpreter.cpp
index b6bfb2c98..a452bb7f2 100644
--- a/Source/JavaScriptCore/yarr/YarrInterpreter.cpp
+++ b/Source/JavaScriptCore/yarr/YarrInterpreter.cpp
@@ -565,7 +565,10 @@ public:
if (matchEnd == -1)
return true;
- ASSERT((matchBegin == -1) || (matchBegin <= matchEnd));
+ if (matchBegin == -1)
+ return true;
+
+ ASSERT(matchBegin <= matchEnd);
if (matchBegin == matchEnd)
return true;
@@ -607,7 +610,11 @@ public:
int matchBegin = output[(term.atom.subpatternId << 1)];
int matchEnd = output[(term.atom.subpatternId << 1) + 1];
- ASSERT((matchBegin == -1) || (matchBegin <= matchEnd));
+
+ if (matchBegin == -1)
+ return false;
+
+ ASSERT(matchBegin <= matchEnd);
if (matchBegin == matchEnd)
return false;
@@ -1443,13 +1450,16 @@ public:
int interpret()
{
+ if (input.isNotAvailableInput(0))
+ return -1;
+
+ for (unsigned i = 0; i < pattern->m_body->m_numSubpatterns + 1; ++i)
+ output[i << 1] = -1;
+
allocatorPool = pattern->m_allocator->startAllocator();
if (!allocatorPool)
CRASH();
- for (unsigned i = 0; i < ((pattern->m_body->m_numSubpatterns + 1) << 1); ++i)
- output[i] = -1;
-
DisjunctionContext* context = allocDisjunctionContext(pattern->m_body.get());
JSRegExpResult result = matchDisjunction(pattern->m_body.get(), context, false);
@@ -1462,7 +1472,6 @@ public:
pattern->m_allocator->stopAllocator();
- // RegExp.cpp currently expects all error to be converted to -1.
ASSERT((result == JSRegExpMatch) == (output[0] != -1));
return output[0];
}
diff --git a/Source/JavaScriptCore/yarr/YarrJIT.cpp b/Source/JavaScriptCore/yarr/YarrJIT.cpp
index a3f467dc1..06faeaa1a 100644
--- a/Source/JavaScriptCore/yarr/YarrJIT.cpp
+++ b/Source/JavaScriptCore/yarr/YarrJIT.cpp
@@ -2477,6 +2477,14 @@ public:
{
generateEnter();
+ Jump hasInput = checkInput();
+ move(TrustedImm32(-1), returnRegister);
+ generateReturn();
+ hasInput.link(this);
+
+ for (unsigned i = 0; i < m_pattern.m_numSubpatterns + 1; ++i)
+ store32(TrustedImm32(-1), Address(output, (i << 1) * sizeof(int)));
+
if (!m_pattern.m_body->m_hasFixedSize)
store32(index, Address(output));
@@ -2497,7 +2505,7 @@ public:
backtrack();
// Link & finalize the code.
- LinkBuffer linkBuffer(*globalData, this);
+ LinkBuffer linkBuffer(*globalData, this, REGEXP_CODE_ID);
m_backtrackingState.linkDataLabels(linkBuffer);
if (m_charSize == Char8)
jitObject.set8BitCode(linkBuffer.finalizeCode());
diff --git a/Source/JavaScriptCore/yarr/YarrPattern.h b/Source/JavaScriptCore/yarr/YarrPattern.h
index 2cbb79586..a31deee67 100644
--- a/Source/JavaScriptCore/yarr/YarrPattern.h
+++ b/Source/JavaScriptCore/yarr/YarrPattern.h
@@ -316,7 +316,7 @@ struct TermChain {
};
struct YarrPattern {
- YarrPattern(const UString& pattern, bool ignoreCase, bool multiline, const char** error);
+ JS_EXPORT_PRIVATE YarrPattern(const UString& pattern, bool ignoreCase, bool multiline, const char** error);
~YarrPattern()
{